Creating a self-hosted OData Web API service

Some time ago Microsoft has introduced the ASP.NET Web API framework. It’s a framework you can use to create your own RESTful services. It’s much like WCF Data Services or WCF RIA Services, but a lot easier to use (IMO). I’ve never liked the WCF-stack much, probably because configuring it always posed to be a hassle.

Using the Web API framework is much easier and you have to configure a lot less, or at least I haven’t found all of the configurable options yet. Then again, it’s created for entirely different purposes of course.

To create a service you select the ASP.NET MVC4 project template and can create new controllers which inherit from the ApiController. It’s also possible to do some awesome queries on your client nowadays, because Web API is capable of supporting OData! Install the latest stable NuGet package and you are ready to go!

Because I was put on a new project, I was finally able to do some real work with ASP.NET Web API. We had to develop a solution containing a so called self-hosted Web API service which also supported OData queries. This sounds like a lot of work, but it’s actually rather easy to do so nowadays.

During this new project we had some time to investigate and learn a bit about the platform. Therefore we chose to use the latest version of everything we could find, just to keep us up-to-date. To get OData working we used the beta2 version which works great for the simple stuff we were doing.

Now, all you have to do to get OData working is return IQueryable from your controller actions. For example:

[Queryable]
public IQueryable<functionalevent> GetEverything()
{
    using (var ctx = new HMOEvents("TheRepositoryConnectionStringName"))
    {
		return ctx.TableContainingEverything.OrderByDescending(e => e.TimeCreated).ToList().AsQueryable();
    }
}

Hit F5 and you are ready to do some OData queries on this action. Awesome, huh?

After we had figured this out, we still had to make this Web API service self-hosted. The reason for this requirement was because the webserver wasn’t in our control and the administrators had the tendency of resetting IIS quite a lot of times during the day (don’t ask.). I was already pulling my hair on figuring out how we had to do this, but as it turns out this is quite easy to do also.

There’s a reference you can add called System.Web.Http.SelfHost. You just have to create a new Console Application, add the reference and paste this piece of code over your Main method


static void Main(string[] args)
{
    HttpSelfHostServer server = null;
    try
    {
        // Set up server configuration
	    var config = new HttpSelfHostConfiguration(new Uri("https://localhost:2132"));
        config.EnableQuerySupport();
	    config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
	    config.Routes.MapHttpRoute(
				name: "ActionApi",
				routeTemplate: "api/{controller}/{action}",
				defaults: new { action = "Get" }
	);
	config.Routes.MapHttpRoute(
		            name: "DefaultApi",
		            routeTemplate: "api/{controller}/{id}",
       			    defaults: new { id = RouteParameter.Optional }
        );
	config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
	config.ReceiveTimeout = new TimeSpan(0, 0, 3, 0);
	config.SendTimeout = new TimeSpan(0, 0, 3, 0);
	// Create server
	server = new HttpSelfHostServer(config);
        // Start listening
        server.OpenAsync().Wait();
        Console.WriteLine("Listening on https://localhost:2132");
        Console.ReadLine();
    }
    catch (Exception e)
    {
        Console.WriteLine("Could not start server: {0}", e.GetBaseException().Message);
        Console.WriteLine("Hit ENTER to exit...");
        Console.ReadLine();
    }
    finally
    {
        if (server != null)
        {
            // Stop listening
            server.CloseAsync().Wait();
        }
    }
}

After doing so you can add your Web API controllers to this Console Application and start the application. Once the application is started you are able to do your queries on https://localhost:2132.

Note: You might need to check the firewall and run this application as an Administrator, otherwise it might cause some problems. Something about Windows security and setting up new ‘webservers’. It’s possible to do this without Administrator priviliges, to do this isexplained on Stack Overflow.

Again, pretty awesome, huh? This saves up a lot of development time!

You might have noticed I’ve used the following line to enable CORS on the service:

config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

This isn’t some extension method and class that I’ve written myself. There’s something called Microsoft.AspNet.WebApi.Cors which is a NuGet package you can implement. At the time of the project, beta2 was the most recent version of these bits. Once you’ve included this in your project, you are able to enable CORS with just this extra line in the configuration.

For self-hosted services you have use this, because it’s rather hard (impossible?) to add the ‘Acces-Control-Allow-Origin’ headers.


Share