I have a self-hosted WebService/WebApplication using the wonderful Service Stack.
My views are embedded in the DLL, and so are the images. I am using the ResourceVirtualPathProvider
code from GitHub. It finds the index page and layouts correctly, but it can't find the embedded images/css (probably obviously).
How would I go about configuring the Razor plugin to search the path providers. I've checked in debug mode and the path providers have found all the css and images. They're just not getting routed.
EDIT
I have tried setting the AppHost's VirtualPathProvider
property to the same provider that I configured the RazorFormat
plugin with, but to no avail.
LAST EDIT
Thanks to Mythz's response, I have now got this working and provide the solution below:
Firstly (and I had this before), I used the
Embedded
code from GitHub to create resource virtual path providers, directories, and files.Implemented a VirtualFileHandler:
public sealed class VirtualFileHandler : IHttpHandler, IServiceStackHttpHandler { private IVirtualFile _file; /// <summary> /// Constructor /// </summary> /// <param name="file">File to serve up</param> public VirtualFileHandler(IVirtualFile file) { _file = file.ThrowIfDefault("file"); } // eo ctor public bool IsReusable { get { return false; } } public void ProcessRequest(HttpContext context) { ProcessRequest(new HttpRequestWrapper(null, context.Request), new HttpResponseWrapper(context.Response), null); } // eo ProcessRequest public void ProcessRequest(IHttpRequest request, IHttpResponse response, string operationName) { try { response.ContentType = ALHEnvironment.GetMimeType(_file.Extension); using (Stream reader = _file.OpenRead()) { byte[] data = reader.ReadFully(); response.SetContentLength(data.Length); response.OutputStream.Write(data, 0, data.Length); response.OutputStream.Flush(); } } catch (System.Net.HttpListenerException ex) { //Error: 1229 is "An operation was attempted on a nonexistent network connection" //This exception occures when http stream is terminated by the web browser. if (ex.ErrorCode == 1229) return; throw; } } // eo ProcessRequest } // eo class VirtualFileHandler
Configured everything in my configuration function (the fact it is static is unique to my scenario, but it's effectively called from the regular AppHost's
Configure
function)protected static void Configure(WebHostConfiguration config) { _pathProvider = new MultiVirtualPathProvider(config.AppHost, new ResourceVirtualPathProvider(config.AppHost, WebServiceContextBase.Instance.GetType()), new ResourceVirtualPathProvider(config.AppHost, typeof(ResourceVirtualPathProvider))); config.Plugins.Add(new RazorFormat() { EnableLiveReload = false, VirtualPathProvider = _pathProvider }); /* * We need to be able to locate other embedded resources other than views, such as CSS, javascript files, * and images. To do this, we implement a CatchAllHandler and locate the resource ourselves */ config.AppHost.CatchAllHandlers.Add((httpMethod, pathInfo, filePath) => { IVirtualFile file = _pathProvider.GetFile(pathInfo); if (file == null) return null; return new VirtualFileHandler(file); }); } // eo Configure
Have you had a look at the self-hosted version of RazorRockstars?
It's not the RazorFormat that needs to know about static files, they're just handled by ServiceStack itself.
You need to set the Build Action of each of the static files to Copy if newer so they're copied to the
bin/
directory so ServiceStack can find them as it's the base directory where the self-hosted version of ServiceStack is hosted from.