Walance
Walance

Reputation: 95

How to dynamically add links to CSS and Javascript files in ASP.NET Core

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?

Upvotes: 0

Views: 1364

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239340

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.

Upvotes: 2

Related Questions