Search code examples
c#servicestackservicestack-bsd

ServiceStack: Set Root URL for Index page to /


I asked a question a few weeks ago about this, found here: ServiceStack: URL Re-writing with Self-Hosted application

However, I'm encountering an issue when I create this application as a windows service. I get the following error when I browse the root URL of my application:

error CodeFileNotFoundExceptionmessage
Could not find file 'C:\Windows\system32\index.html'.

Here is what I have done:

var handleRoot = new CustomActionHandler((httpReq, httpRes) =>
{
    httpRes.ContentType = "text/html";
    httpRes.WriteFile("index.html");
    httpRes.End();
});

SetConfig(new EndpointHostConfig
{
    DebugMode = false,
    RawHttpHandlers =
    {
        httpReq => (httpReq.RawUrl == "/") ? handleRoot : null
    }
});

public class CustomActionHandler : IServiceStackHttpHandler, IHttpHandler
{
    public Action<IHttpRequest, IHttpResponse> Action { get; set; }

    public CustomActionHandler(Action<IHttpRequest, IHttpResponse> action)
    {
        if (action == null)
            throw new Exception("Action was not supplied to ActionHandler");

        Action = action;
    }

    public void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName)
    {
        Action(httpReq, httpRes);
    }

    public void ProcessRequest(HttpContext context)
    {
        ProcessRequest(context.Request.ToRequest(GetType().Name),
            context.Response.ToResponse(),
            GetType().Name);
    }

    public bool IsReusable
    {
        get { return false; }
    }
}

If I take this out and browse the root of my service, it works but I have /index.html appended onto the end where as I would like it to be / like it is when I host this as a console application


Solution

  • When you run as a Windows service then the execution directory of your service becomes the System32 folder of your system, because this where the service DLL host executes from.

    This means it becomes your base directory for your ServiceStack application. Hence if you do httpRes.WriteFile("index.html"); it will look for index.html in c:\windows\system32\ and seeing your index.html doesn't reside there it will not find the index.

    You can resolve this issue in one of two ways. Either you can set the base directory from which files will be read; Or you can specify the full path when selecting the file to write.

    Set the current directory:

    You can change the directory to be that of the executing service assembly rather than the system directory, by including this line when you application starts.

    System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);
    ...
    httpRes.WriteFile("index.html"); // index.html is read from the application directory now
    

    Get the application directory:

    Or you can determine the application directory and combine it with the index.html to form the full path.

    var directory = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
    httpRes.WriteFile(Path.Combine(directory, "index.html"));