Using ClientDependency with MVC 3 beta's Razor view engine

by James Diacono 28. October 2010 11:06

ClientDependency already has full support for MVC...but how do you get it work with the Razor view engine?

Razor and helpers: what’s the deal man?

@Html.HelperA()

@{
	Html.HelperB();
}

In the above code, the first example is equivalent to

<%:Html.HelperA() %>

(the HTML escaped version of <%=Html.HelperA() %>) and the second to

<% Html.HelperB() %>

Client “Deep”-endancy

As such, I assumed ClientDependency would look something like this in Razor world:

@{
    Html.RequiresCss("Site.css", "Styles");
    Html.RequiresJs("Site.js", "Scripts");
}

@Html.RenderCssHere(new List<IClientDependencyPath>() {
    new BasicPath("Styles", "/Content/Css")
})

@Html.RenderJsHere(new List<IClientDependencyPath>() { 
    new BasicPath("Scripts", "/Scripts")
})

Sadly not. I got a compilation error: CS1061: 'System.Web.Mvc.HtmlHelper<object>' does not contain a definition for 'RequiresCss' and no extension method 'RequiresCss' accepting a first argument of type 'System.Web.Mvc.HtmlHelper<object>' could be found (are you missing a using directive or an assembly reference?)

Okay, so I need to include the ClientDependency helpers in the page namespace config. My Web.config (the one in the "Views" folder) turned out looking like this:

<configuration>
    <system.web.webpages.razor>
        <host factorytype="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <pages pagebasetype="System.Web.Mvc.WebViewPage">
            <namespaces>
                <add namespace="System.Web.Mvc" />
                <add namespace="System.Web.Mvc.Ajax" />
                <add namespace="System.Web.Mvc.Html" />
                <add namespace="System.Web.Routing" />
                <add namespace="ClientDependency.Core" />
                <add namespace="ClientDependency.Core.Mvc" />
                <add namespace="MySite.Web.Views.Helpers" />
            </namespaces>
        </pages>
    </system.web.webpages.razor>
</configuration>

So I tried running it again, but the @Html.RenderCssHere() and @Html.RenderJsHere() methods had resulted in this

<!--[Css:Name="StandardRenderer"]//-->

<!--[Javascript:Name="StandardRenderer"]//-->

Yuck.

Razor automatically HTML escapes anything returned by a helper when called in the @Html.HelperA() style, unless that helper returns an HtmlString type.  Hence the Html.RenderCssHere and Html.RenderJsHere need to be wrapped by an HTML string.  Shannon provided this solution in a comment below:

@MvcHtmlString.Create(Html.RenderCssHere(new List<IClientDependencyPath>() {
    new BasicPath("Styles", "/Content/Css")
}))

@MvcHtmlString.Create(Html.RenderJsHere(new List<IClientDependencyPath>() { 
    new BasicPath("Scripts", "/Scripts")
}))

and voila! The best, of the best, of the best.

Tags: ,
Categories: .Net | ClientDependency

Comments

10/28/2010 11:22:34 AM #

In Umbraco v5 source we are doing it like this:

@MvcHtmlString.Create(Html.RenderCssHere(new List<IClientDependencyPath>() .....

ShannonDeminick United States

2/16/2011 7:58:40 PM #

Awesome....the one i was looking for. Thanks

Lakshman India

3/30/2011 7:11:46 PM #

And how would this work in Umbraco 4.7?
I'm getting:
System.Web.WebPages.Html.HtmlHelper' does not contain a definition for 'RenderCssHere'

Yannick Netherlands