ASP.Net MVC Embedded Resource Helper Class

Getting embedded resources such as JavaScript, CSS and image files is a little bit more difficult when using the ASP.Net MVC framework as most of the useful methods for this will not work.

The only reliable way I have found it to invoke the GetWebResourceUrlInternal method via reflection on the assembly.

Note: I realise there are probably better ways of doing this but I posting this as a reminder to myself more than anything.

So, put your resources in the AssemblyInfo.cs folder as usual: (the following example is AssemblyName.Folder.File).

  1. [assembly: WebResource("MvcWebResourceTest.Resources.MyJavascriptFile.js", "test/javascript")]

You will need to add the following using statement System.Web.UI to the AssemblyInfo.cs file.

Note: make sure you’ve set the files Build Action property to Embedded Resource on the MyJavascriptFile.js.

You can then use the following class to generate the resource string to call in you’re html helpers, controllers etc.

 

  1. /// <summary>
  2.     /// Helper class for getting embedded resources in ASP.Net MVC.
  3.     /// </summary>
  4.     public static class WebResourceHelper
  5.     {
  6.         const string GetWebResourceUrlInternal = "GetWebResourceUrlInternal";
  7.         /// <summary>
  8.         /// Gets the internal embedded resource url.
  9.         /// </summary>
  10.         /// <typeparam name="TAssemblyObject">
  11.         /// Accepts an object that exists within the assembly containing the resources.
  12.         /// </typeparam>
  13.         /// <param name="resourcePath">Accepts a string resource path - assembly.folder.resource name</param>
  14.         /// <returns>A string web resource url.</returns>
  15.         public static string GetResourceUrl<TAssemblyObject>(string resourcePath)
  16.         {
  17.             MethodInfo getResourceUrlMethod = typeof(AssemblyResourceLoader)
  18.                 .GetMethod(GetWebResourceUrlInternal, BindingFlags.NonPublic | BindingFlags.Static);
  19.             string resourceUrl = string.Format("/{0}", getResourceUrlMethod.Invoke
  20.                 (
  21.                     null,
  22.                     new object[] { Assembly.GetAssembly(typeof(TAssemblyObject)), resourcePath, false })
  23.                 );
  24.             return resourceUrl;
  25.         }
  26.     }

 

An example call from a controller to add the resource to the view data collection could be something like the following:

  1.             ViewData["ResourceUrl"] =
  2.                 WebResourceHelper.GetResourceUrl<HomeController>("MvcWebResourceTest.Resources.MyJavascriptFile.js");

Hope this is useful.

Kind Regards,

Sean McAlinden.

www.asp-net-mvc.com

8 Comments

  • The GetWebResourceUrlInternal method doesn't change between calls, so you can improve performance by caching the result of the reflection call.

    Rather than calling Assembly.GetAssembly(type), you could just use type.Assembly, which is equivalent.

    Also, your code only works if your application is in the site root.

    public static class WebResourceHelper
    {
    private static readonly Func GetWebResourceUrlInternal = FindMethod();

    private static readonly Func FindMethod()
    {
    var method = typeof(System.Web.Handlers.AssemblyResourceLoader)
    .GetMethod("GetWebResourceUrlInternal", BindingFlags.Static | BindingFlags.NonPublic);

    return (Func)Delegate.CreateDelegate(
    typeof(Func),
    method, true);
    }

    public static string GetResourceUrl(Assembly assembly, string resourcePath)
    {
    if (null == assembly) throw new ArgumentNullException("assembly");
    if (string.IsNullOrEmpty(resourcePath)) throw new ArgumentNullException("resourcePath");

    string result = GetWebResourceUrlInternal(assembly, resourcePath, false);
    return VirtualPathUtility.ToAbsolute("~/" + result);
    }

    public static string GetResourceUrl(Type typeInAssembly, string resourcePath)
    {
    if (null == typeInAssembly) throw new ArgumentNullException("typeInAssembly");
    return GetResourceUrl(typeInAssembly.Assembly, resourcePath);
    }

    public static string GetResourceUrl(string resourcePath)
    {
    return GetResourceUrl(typeof(TAssemblyObject).Assembly, resourcePath);
    }
    }

  • Hi Richard, Thanks ever so much - that's really useful - I'll definitely give that a go - it looks much better.

    Cheers,

    Sean.

  • Asp net mvc embedded resource helper class.. I like it :)

  • This code is more resistent and prevents "Ambiguous match found." exception (AmbiguousMatchException) when you use System.Web.dll 4.0.0.0 with two "GetWebResourceUrlInternal" overloads ;)

    public static string GetResourceUrl(Type type, string resourcePath)
    {
    string resourceUrl = null;

    List methodCandidates = typeof(AssemblyResourceLoader).GetMember("GetWebResourceUrlInternal", BindingFlags.NonPublic | BindingFlags.Static).ToList();
    foreach (var methodCandidate in methodCandidates)
    {
    var method = methodCandidate as MethodInfo;
    if (method == null || method.GetParameters().Length != 5) continue;

    resourceUrl = string.Format("{0}", method.Invoke
    (
    null,
    new object[] { Assembly.GetAssembly(type), resourcePath, false, false, null })
    );
    break;
    }

    return resourceUrl;
    }

  • Hi to all, the contents present at this site are truly remarkable for people knowledge, well, keep up the
    good work fellows.

  • Your own post features proven necessary to me personally.
    It’s extremely informative and you're simply certainly quite experienced in this field. You have exposed my personal eyes to various thoughts about this specific subject matter with intriquing, notable and solid articles.

  • Your own article features confirmed beneficial to myself.
    It’s very helpful and you really are clearly extremely knowledgeable of this type.
    You get opened my own sight to be able to varying thoughts about this specific topic using intriguing, notable and strong articles.

  • The post offers verified useful to me. It’s really helpful
    and you really are clearly extremely educated in this region.
    You get exposed my own sight in order to numerous opinion of this particular subject together with intriguing, notable and
    sound articles.

Comments have been disabled for this content.