I have a partial view (.ascx) that should include its own CSS file as it's used in multiple other views. How do I inject a stylesheet in the page server-side, i.e. without using JavaScript?
Dario - due to using this for partialviews, you're going to always have the problem that the <head>
section of the document is already in place and therefore can't be modified. If you want to remain WC3 compliant, then you'll have to put any further css into the head section via javascript. This may or may not be desirable (if you've got to cater for downsteam browsers with javascript turned off).
the main problem that you may be aluding to is the fact that you can't put <asp:contentplaceholders>
into your partials. this is a pain (tho understandable as the masterpage ref would tie the partial too closely to a particular master page).
To this end, I've created a little helper method that does the basic grunt work to put the css file into the head section automatically.
edit - (as per Omu's js suggestion) this is a nice little halfway house:
// standard method - renders as defined in as(cp)x file
public static string Css(this HtmlHelper html, string path)
{
return html.Css(path, false);
}
// override - to allow javascript to put css in head
public static string Css(this HtmlHelper html, string path, bool renderAsAjax)
{
var filePath = VirtualPathUtility.ToAbsolute(path);
HttpContextBase context = html.ViewContext.HttpContext;
// don't add the file if it's already there
if (context.Items.Contains(filePath))
return "";
// otherwise, add it to the context and put on page
// this of course only works for items going in via the current
// request and by this method
context.Items.Add(filePath, filePath);
// js and css function strings
const string jsHead = "<script type='text/javascript'>";
const string jsFoot = "</script>";
const string jsFunctionStt = "$(function(){";
const string jsFunctionEnd = "});";
string linkText = string.Format("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\"></link>", filePath);
string jsBody = string.Format("$('head').prepend('{0}');", linkText);
var sb = new StringBuilder();
if (renderAsAjax)
{
// join it all up now
sb.Append(jsHead);
sb.AppendFormat("\r\n\t");
sb.Append(jsFunctionStt);
sb.AppendFormat("\r\n\t\t");
sb.Append(jsBody);
sb.AppendFormat("\r\n\t");
sb.Append(jsFunctionEnd);
sb.AppendFormat("\r\n");
sb.Append(jsFoot);
}
else
{
sb.Append(linkText);
}
return sb.ToString();
}
usage:
<%=Html.Css("~/Content/yourstyle.Css")%>
or:
<%=Html.Css("~/Content/yourstyle.Css", true)%> // or false if you want!!
worth a back-pocket approach if all else fails. it may also be possible to adapt the logic above to hit an actionfilter and add the css to the reponse headers etc.., rather than outputting the js string.
Is there a reason you cannot just put the stylesheet in the main view page? Unless it is extremely large, it should not cause your page to load significantly slower when not being used, especially after compression.
Furthermore, if the partial view is being retrieved by ajax, you will end up re-downloading the css file multiple times (depending on the browser's caching).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With