31 December 2015 WebAPI, ASP.NET Robert Muehsig

Embedded files? Why?

In a normal Web-Application all files are somehow stored as files in the app directory, but sometimes it could be handy to embed those files.

One scenario could be that you have a “library”, which can be integrated in a larger application. If you don’t want to pull over all files and you just want to expose a single assembly (for example as NuGet package) embedded resources might come handy.


My demo application is a simple ConsoleApp, which a selfhosting WebAPI and two Controllers (Demo and Pages):


Important is, that my “target” html and css file are marked as Embedded Resource.


In my sample I have created on “PageController”, which accepts all requests that seems to target the embedded files.


public class Startup
    public void Configuration(IAppBuilder appBuilder)
        HttpConfiguration config = new HttpConfiguration();


            name: "ApiV1",
            routeTemplate: "api/v1/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }

           name: "PageController",
           routeTemplate: "{*anything}",
           defaults: new { controller = "Page", uri = RouteParameter.Optional });



The “PageController”

This controller will try to read the HTTP GET PathAndQuery and will look inside the assembly resources for something with the same name.

public class PageController : ApiController
    private const string ResourcePath = "SelfHostWithBetterRouting.Pages{0}";

    public static string GetStreamContent(string folderAndFileInProjectPath)
        var asm = Assembly.GetExecutingAssembly();
        var resource = string.Format(ResourcePath, folderAndFileInProjectPath);

        using (var stream = asm.GetManifestResourceStream(resource))
            if (stream != null)
                var reader = new StreamReader(stream);
                return reader.ReadToEnd();
        return String.Empty;

    public HttpResponseMessage Get()
        var virtualPathRoot = this.Request.GetRequestContext().VirtualPathRoot;
        string filename = this.Request.RequestUri.PathAndQuery;

        // remove SERVER/appname from request to get the relative filename
        if (virtualPathRoot != "/")
            filename = filename.ToLowerInvariant().Replace(virtualPathRoot.ToLowerInvariant(), string.Empty);
        // input as /page-assets/js/scripts.js
        if (filename == "/" || filename == "")
            filename = ".index.html";

        // folders will be seen as "namespaces" - so replace / with the .
        filename = filename.Replace("/", ".");
        // resources can't be named with -, so it will be replaced with a _
        filename = filename.Replace("-", "_");

        var mimeType = System.Web.MimeMapping.GetMimeMapping(filename);

        var fileStreamContent = GetStreamContent(filename);

        if (string.IsNullOrWhiteSpace(fileStreamContent))
            throw new Exception(string.Format("Can't find embedded file for '{0}'", filename));

        if (virtualPathRoot != "/")
            fileStreamContent = fileStreamContent.Replace("~/", virtualPathRoot + "/");
            fileStreamContent = fileStreamContent.Replace("~/", virtualPathRoot);

        var response = new HttpResponseMessage();
        response.Content = new StringContent(fileStreamContent);
        response.Content.Headers.ContentType = new MediaTypeHeaderValue(mimeType);
        return response;


Mix the “PageController” and normal WebAPI Controllers

In my sample the “PageController” will catch all requests that are not handled by other controllers, so you could even serve a general 404 page.

Hosting in IIS

If you host this inside an IIS it will not work out of the box, because the IIS itself tries to serve static content. One easy option would be to include this inside your web.config:

<!-- prevent IIS from serving embeddded stuff -->
<location path="pages">
            <add name="nostaticfile" path="*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

With this web.config setting in place the request should route through your code.


The self hosting WebAPI returns the “index.html” and the linked “site.css” - all embedded inside the assembly:


In an older blogpost I used a similar approach, but the routing part is now “better” solved.

Hope this helps!

The code is also available on GitHub.

Written by Robert Muehsig

Software Developer - from Dresden, Germany, now living & working in Switzerland. Microsoft MVP & Web Geek.
Other Projects: KnowYourStack.com |ExpensiveMeeting | EinKofferVollerReisen.de

If you like the content and want to support me you could buy me a beer or a coffee via Litecoin LV944KWxEM3WaCYCUKJMiLtfRrXPd8Cnbh or Bitcoin 1C712oGPrTLmDjQ7SHjh6TGqchQdCzo2Sn - thanks for reading!

blog comments powered by Disqus