eWorld.UI - Matt Hawley

Ramblings of Matt

ASP.NET MVC - Extracting Web Resources

May 13, 2008 11:40 by matthaw

One nice feature that ASP.NET added in the 2.0 feature set was the ability to embed resources directly within an assembly and then later extract them through a separate Http Handler. You've notably saw this by all the WebResource.axd calls. If you're building a ASP.NET MVC view, you have two ways of extracting web resource urls.

Way 1

If you are using the default view engine, all of your views should derive either from ViewPage or ViewUserControl, which ultimately has access to ClientScript.WebResourceUrl, etc. This method is the easiest to use as it doesn't require anything special:

<script src="<%= ClientScript.WebResourceUrl(typeof(Foo), "Foo.Bar.js") %>" type="text/javascript">
</script>

This way works great, as I said if you're using the WebFormsViewEngine and you're within the view itself. However sometimes you have a controller action or other html helper extension methods that are rendering HTML directly ... or you're just using a completely different view engine. At this point, you don't have access to ClientScript.

Way 2

The second way is by having your own extension method that will generate the web resource url for you. This way, you can get a web resource url anywhere you have an instance of your HtmlHelper object.

   1:  public static class HtmlHelperExtensions
   2:  {
   3:     private static MethodInfo getWebResourceUrlMethod;
   4:     private static object getWebResourceUrlLock = new object();
   5:   
   6:     public static string WebResourceUrl<T>(this HtmlHelper htmlHelper, string resourceName)
   7:     {
   8:        if (string.IsNullOrEmpty(resourceName)
   9:           throw new ArgumentNullException("resourceName");
  10:   
  11:        if (getWebResourceUrlMethod == null)
  12:        {
  13:           lock (getWebResourceUrlLock)
  14:           {
  15:              if (getWebResourceUrlMethod == null)
  16:              {
  17:                 getWebResourceUrlMethod = typeof(AssemblyResourceLoader).GetMethod(
  18:                                                  "GetWebResourceUrlInternal",
  19:                                                  BindingFlags.NonPublic | BindingFlags.Static);
  20:              }
  21:           }
  22:        }
  23:   
  24:        return "/" + (string) getWebResourceUrlMethod.Invoke(null,
  25:                         new object[] { Assembly.GetAssembly(typeof(T)), resourceName, false });
  26:     }
  27:  }

And that's it. Now, in your code you can get a web resource url very similarly as with ClientScript:

<script src="<%= Html.WebResourceUrl<Foo>("Foo.Bar.js") %>" type="text/javascript">
</script>

What I don't like about this approach is that it is using reflection to invoke the private method, but considering these methods are not exposed anywhere (ohh, and you cannot create an instance of ClientScriptManager) this is the only approach that can be taken. Furthermore, remember this is an ASP.NET feature, and works very nicely within the MVC framework. The url, WebResource.axd, is mapped to the AssemblyResourceLoader Http Handler which is independent of the ASP.NET web forms runtime. Hope this helps some people!

kick it on DotNetKicks.com



Categories: .NET | ASP.NET | Development | MVC
Actions: E-mail | Permalink | Comments (8) | Comment RSSRSS comment feed

Comments

May 16. 2008 01:06

Pingback from weblogs.asp.net

ASP.NET MVC - Extracting Web Resources - eWorld.UI - Matt Hawley

weblogs.asp.net

May 16. 2008 09:58

Your second way will not work of most of the share servers (such GoDaddy) if you will use it in your own code because such reflection
is not permitted on their servers.

Miron

May 16. 2008 10:38

@Miron - good to know, it's probably a wise thing they lock stuff like that down. Other than that, you need reference to Page or UserControl to do anything which limits you to your view instance then.

matthaw

May 16. 2008 14:25

Can you explain, please, the cases you can't use the first option:
ClientScript.WebResourceUrl

Miron

May 16. 2008 14:45

Cool idea.  Seems like it could be handy to go a step futhur, too:
Html.WebResourceScript<Foo>("Foo.Bar.js") //output the script element
Html.WebResourceStyle<Foo>("Foo.css") //output a style element
Html.WebResourceImage<Foo>("foo.png", "alt text") //output an image element

Daniel

May 16. 2008 16:27

@Daniel - yeah, was thinking of exposing other HtmlHelpers like

Html.Image<Foo>("Foo.jpg");
Html.Script<Foo>("Foo.jpg");
Html.Style<Foo>("Foo.css");

@Miron - you can't use ClientScript when you're in your action methods OR if you've created your own view engine.

matthaw

May 20. 2008 12:41

Pingback from code-inside.de

Wöchentliche Rundablage: Silverlight 2, ASP.NET MVC, C# 3.0, .NET 3.5 SP1… | Code-Inside Blog

code-inside.de

March 21. 2009 08:13

Thanks great article

Bayram Çelik

Comments are closed

Copyright © 2000 - 2024 , Excentrics World