Saturday, 17 September 2011

Simple access of embedded resources in DLLs in MVC views

I was working with embedded views in a DLL in a MVC Razor 3 project today and I had to be able to refer to embedded Javascript .js files, images (jpg and png) and css files in the precompiled views. To make this work I tagged the files as Embedded Resource in my project, compiled the project into a dll and in the other mvc project which used the dll I could get it to fetch the embedded resources easily adding a new MVC controller action.

The mvc controller action looks like this:

The code below goes into the Home controller, ContentFile action method, which
returns a FileStreamResult below.



public FileStreamResult ContentFile(string id)
{
string resourceName = Assembly.GetExecutingAssembly().GetManifestResourceNames().ToList().FirstOrDefault(f => f.EndsWith(id));
return new FileStreamResult(Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName), GetMIMEType(id));
}

private string GetMIMEType(string fileId)
{
if (fileId.EndsWith(".js"))
{
return "text/javascript";
}
else if (fileId.EndsWith(".css"))
{
return "text/stylesheet";
}
else if (fileId.EndsWith(".jpg"))
{
return "image/jpeg";
}
return "text";
}


To use this in the views, write this:



<script type="text/javascript" src="/Home/ContentFile/test.js">
</script>

<link rel="Stylesheet" href="/Home/ContentFile/blue.css">

<img src="/Home/ContentFile/forest.jpg" />



To load up an embedded resource we look into the executing dll, which instead should perhaps load a specified assembly if necessary, and then GetManifestResourceStream and retrieving the matching resource name passed in. The MIME type must be set and is resolved by looking at the resource name passed in.

So the morale is that if you want to load a content file from a DLL in a MVC view, use a controller action and return a FileStreamResult and then load up the content file by writing the route to the ContentFile action.

5 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Updating my blog article using my Samsung Galaxy phone. The last part discusses content files. Yes, javascript, images and css is "content" - but in this context they are embedded resources.Updating my blog article using my Samsung Galaxy phone. The last part discusses content files. Yes, javascript, images and css is "content" - but in this context they are embedded resources.

    ReplyDelete
  3. umm that last comment got repeated twice. note in a deployment scenario there are issues with reflection being turned off. Anyways I mean this approach should work. An alternative is an Url extension method to a controller action. My code dont have exception handling. You probably should add that. Also a locking should be done when returning the stream to avoid thread issues of multiple requests.

    ReplyDelete
  4. After reading some more about MIME type, MIME is now considered the wrong term. Content Type or Internet media type is a better term than MIME, which now is used for email, as it stands for Multipurpose Internet Mail Extensions really ..

    ReplyDelete
  5. Hi,

    Thank you for the article.

    I've tried to apply your approach to my case, but it doesn't work immediately. Please, take a look at the issue here:

    https://stackoverflow.com/questions/45370481/the-issue-with-access-to-js-file-from-external-assembly-in-mvc-5/45410502

    What I'm doing wrong and how to make it work properly?

    ReplyDelete