bitbonk
bitbonk

Reputation: 49619

Am I reinventing the wheel with this ASP.NET Web API based webserver?

In a standalone (selfhosted) application, I would like to have an httpserver that on a single base adress can either serve simple web pages (without any serverside dynamics/scripting, it just returns the content request files) or serve RESTful webservices:

My current approach uses ASP.NET Web API to server both the html pages and the REST APIs:

 var config = new HttpSelfHostConfiguration("http://localhost:8070/");
 config.Formatters.Add(new WebFormatter());
 config.Routes.MapHttpRoute(
   name: "Default Web",
   routeTemplate: "{fileName}",
   defaults: new { controller = "web", fileName = RouteParameter.Optional });
 config.Routes.MapHttpRoute(
   name: "Default API",
   routeTemplate: "api/{controller}/{id}",
   defaults: new { id = RouteParameter.Optional });

The WebController is the controller that serves the web pages with this naive code:

public class WebController : ApiController
{
    public HttpResponseMessage Get(string fileName = null)
    {
        /// ...
        var filePath = Path.Combine(wwwRoot, fileName);
        if (File.Exists(filePath))
        {
            if (HasCssExtension(filePath))
            {
                return this.Request.CreateResponse(
                   HttpStatusCode.OK, 
                   GetFileContent(filePath), 
                   "text/css");
            }

            if (HasJavaScriptExtension(filePath))
            {
                return this.Request.CreateResponse(
                   HttpStatusCode.OK,
                   GetFileContent(filePath),
                   "application/javascript");
            }

            return this.Request.CreateResponse(
              HttpStatusCode.OK, 
              GetFileContent(filePath), 
              "text/html");
        }

        return this.Request.CreateResponse(
            HttpStatusCode.NotFound,
            this.GetFileContnet(Path.Combine(wwwRoot, "404.html")),
            "text/html");
    }
}

And again, for everything behind /api, controllers for normal REST APIs are used.

My question now is: Am I on the right track? I kind of feel that I am rebuilding a webserver here, reinventing the wheel. And I guess that there are probably a lot of http request web browsers could make that I do not handle correctly here.

But what other option do I have if I want to self host and at the same time server REST web APIs and web pages over the same base address?

Upvotes: 2

Views: 2242

Answers (3)

David Alan Thomas
David Alan Thomas

Reputation: 11

See this link which uses a more straigftforward approach

Setting app a separate Web API project and ASP.NET app

RouteTable.Routes.IgnoreRoute(".js"); RouteTable.Routes.IgnoreRoute(".html");

Upvotes: 0

Darrel Miller
Darrel Miller

Reputation: 142094

IMO there is nothing wrong with what you are doing. I use self-host for delivering files, html docs as well as being a regular API. At the core, self-host is using HTTP.SYS just as IIS is.

As RaghuRam mentioned there are Owin hosts that have some optimizations for serving static files, but WCF selfhost is quite capable of getting decent perf for serving files.

Upvotes: 1

RaghuRam Nadiminti
RaghuRam Nadiminti

Reputation: 6793

Looks like you are trying to recreate asp.net FileHandler for self host. There is a better solution though. Using Katana(an OWIN host) as the hosting layer for web API. OWIN supports hosting multiple OWIN frameworks in the same app. In your case, you can host both web API and a file handler in the same OWIN app.

Filip has a good blog post on this to get you started here. You can use configuration code like this,

public void Configuration(IAppBuilder appBuilder)
{
    // configure your web api.
    var config = new HttpConfiguration();
    config.Routes.MapHttpRoute("default-api", "api/{controller}");
    appBuilder.UseWebApi(config);

    // configure your static file handler.
    appBuilder.UseStaticFiles();
}

Upvotes: 3

Related Questions