Reputation: 95
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
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