0

We have a CMS that we want to convert to .NET Core. In our CMS we can add pages and templates, including CSS and Javascript templates. On a page we can select one or more CSS and/or Javascript templates that should be loaded on that page.

To make that work, I would like to dynamically build an URL to a CSS or Javascript file inside my controller (or service) and add that file to my _Layout.cshtml. At the moment I do something like this:

My controller method:

public IActionResult Test() 
{
    var listOfCssIds = new List<int>() { 1, 2, 3 };
    var cssFile = $"/css/customCss_{String.Join("_", listOfNumbers)}.css";
    ViewData["MyCssFile"] = cssFile;
    return View();
}

My _Layout.cshtml:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    @{
        if (@ViewData["MyCssFile"] != null)
        {
            <link href="@ViewData["MyCssFile"]" rel="stylesheet" />
        }
    }
</head>
<body>
    <h1>Layout from library</h1>
    @RenderBody()
</body>
</html>

We can also add links to external CSS / Javascript files, to a CDN for example. We also want to add those to our view. I can do that the same way as the code above, but this feels wrong and I'm wondering if there's a better way to do this?

I thought about using sections and then adding @RenderSection() to my _Layout.cshtml, but I can't find how to add stuff to a section via a controller or service, it only seems to be possible to do that in another view.

I have been searching the internet for answers/ideas, but can't really find anything. Can anyone tell me what the best practices for cases like this are?

I have the same question for HTML, our CMS decides most of the HTML that the page should have. Currently I build that HTML in my controller, then add it to the ViewData and put that in my view like so: @Html.Raw(ViewData["Html"]). I'm also wondering if there is a better way to do this?

1 Answer 1

2

I'm assuming the CSS files that are selected are persisted via a database by your CMS, and rather than having a static list of CSS ids, you're actually pull the info from a database. In that scenario, your best bet is a view component:

public class CustomCssViewComponent : ViewComponent
{
    private readonly MyContext _context;

    public CustomCssViewComponent(MyContext context)
    {
        _context = context;
    }

    public async Task<IViewComponentResult> InvokeAsync()
    {
        var ids = // pull in the ids from your context;
        return View(ids); 
    }
}

Now, you're essentially just passing in the ids as the model for the view backing this view component. So, go ahead and create that view at Views/Shared/Components/CustomCss/Default.cshtml:

@model List<int>
<link href="/css/customCss_@(String.Join("_", Model)).css" rel="stylesheet" />

Finally, in your layout or wherever you want this included:

@await Component.InvokeAsync("CustomCss")

Rinse and repeat with your custom JS. You can probably handle your custom HTML the same way, but you may also consider using custom tag helpers.

Sign up to request clarification or add additional context in comments.

2 Comments

You are correct in your assumption that I don't actually have a static list of IDs, they come from the database of our CMS. I only made my example like this to make it short and only show relevant code.
Thanks for your answer, I'm still working on implementing your suggestion, but I think it might work. I have to stop my work on this project for now and won't be able to continue until next week, so I will accept your answer for now, but might have more questions next week.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.