November 22, 2014
Hot Topics:

Self-Hosting an ASP.NET Web API

  • July 21, 2014
  • By Bipin Joshi
  • Send Email »
  • More Articles »

Introduction

ASP.NET Web API can be either be hosted in IIS or in a separate host process. The former approach is usually appropriate when the Web API is part of a web application and one or more web applications are going to consume it. The later approach is suitable when you wish to avoid the overhead of hosting the Web API in IIS and want to have something lightweight. Hosting a Web API inside IIS is quite straightforward as the process is identical to hosting a web application. On the other hand, hosting a Web API in it's own process requires the creation of a host application and is referred as self-hosting. This article shows in step-by-step manner how to self-host a Web API and how to consume it using a client application.

Example - Customer Web API

To illustrate how self-hosting of Web API works, you will develop a simple example. The example consists of three projects:

  • A class library project representing a Customer Web API
  • A Windows Forms application that represents a Web API host.
  • A Windows Forms client application the represents a Web API client.

The class library project will have an ApiController. The Customer ApiController contains only one method GetCustomerByID() that accepts customer ID as its parameter and returns a Customer object representing that customer. Although this ApiController can be included in the host application itself, we deliberately decide to isolate it in its own class library. In a more complex scenario or when you have more than one ApiController class you may want to separate them from rest of the system for the sake of proper organization. This way your ApiController classes are not dependent on any specific host application as such. You can use the class library with any host as per your requirement.

The host application is a Windows Forms application as shown below:

Windows Forms Application
Windows Forms Application

Clicking on the Host Web API button starts the self-hosting server and the Web API is made available at http://localhost:9001. Note that currently there are two ways to self-host a Web API - Non-OWIN and OWIN based. This article uses the Non-OWIN way of hosting a Web API. For an example of the OWIN based self-hosting read this article.

The client application calls the Customer Web API hosted by the host application. The client application looks like this:

The Client Application
The Client Application

As you can see the client application accepts a CustomerID and calls the Web API with that ID. The CompanyName of the returned Customer is displayed in a Label control.

Creating a Customer Web API

Begin by creating a Class Library type of project and name it CustomerWebAPI. Add Models folder to the project and add an ADO.NET Entity Framework Data Model for the Customers table of the Northwind database. This model is shown below:

Customer Table
Customer Table

Then add a reference to System.Web.Http assembly and also add a class named CustomerController. The completed CustomerController class is shown below:

using System.Web.Http;
using CustomerWebAPI.Models;
 
namespace CustomerWebAPI
{
    public class CustomerController : ApiController
    {
        public Customer GetCustomerByID(string id)
        {
            NorthwindEntities db = new NorthwindEntities();
            Customer obj = db.Customers.Find(id);
            return obj;
        }
    }
}

Notice that the code imports two namespaces - System.Web.Http and CustomerWebAPI.Models. The CustomerController class inherits from the ApiController base class residing in the System.Web.Http namespace. The CustomerController class contains just one method - GetCustomerByID(). The GetCustomerByID() method accepts an ID parameter. Inside, it finds a Customer whose CustomerID is the specified ID value and returns that Customer back to the caller.

This completes the Customer Web API.

Self-Hosting the Web API

In this section you will create the Web API host application. Add a new Windows Forms project to the same solution and name it WebAPISelfHost. Then add a reference to three assemblies - CustomerWebAPI, System.Web.Http and System.Web.Http.SelfHost.

As mentioned earlier our host application needs to publish the Customer Web API residing in a separate assembly. To host and call the Customer Web API successfully the CustomerWebAPI assembly must be loaded in the host process. Although you referenced the CustomerWebAPI assembly it won't be loaded automatically unless you use any of its types or load it explicitly. In our case we need to explicitly load it so that it can be consumed successfully by the client application. This loading requires that you create a custom assembly loader (know more about this here) that does the job. So, add a new class to the host project named WebAPILoaded. This class is shown below:

using System.Reflection;
using System.Web.Http.Dispatcher;
 
namespace WebAPISelfHostNonOWIN
{
    public class WebAPILoader : DefaultAssembliesResolver
    {
        public override ICollection<Assembly> GetAssemblies()
        {
            ICollection<Assembly> defaultAssemblies = base.GetAssemblies();
            List<Assembly> assemblies = new List<Assembly>(defaultAssemblies);
            Type t=typeof(CustomerWebAPI.CustomerController);
            Assembly a = t.Assembly;
            defaultAssemblies.Add(a);
            return assemblies;
        }
    }
}

The WebAPILoader class inherits from the DefaultAssembliesResolver base class. The DefaultAssembliesResolver class resides in System.Web.Http.Dispatcher namespace. The WebAPILoader class overrides the GetAssemblies() method. Inside, the GetAssemblies() method grabs the Assembly of the CustomerController class using typeof() and Assembly property of the Type class. It then adds that Assembly to the default assemblies that are being loaded.

Next, design the Windows Form as shown earlier. Write the Click event handler of the Host Web API button as shown below:

private void button1_Click(object sender, EventArgs e)
{
    HttpSelfHostConfiguration config = new HttpSelfHostConfiguration("http://localhost:9001");
 
    config.Routes.MapHttpRoute(
        "WebAPIDefault", "api/{controller}/{id}",
        new { id = RouteParameter.Optional });
 
    WebAPILoader loader = new WebAPILoader();
    config.Services.Replace(typeof(IAssembliesResolver), loader);
 
    label1.Text = "Web API Host Started…";
 
    HttpSelfHostServer server = new HttpSelfHostServer(config);
    server.OpenAsync().Wait();
}

The Click event handler begins by creating an instance of HttpSelfHostConfiguration class. The base address of http://localhost:9001 is passed to the constructor. The port number 9001 is randomly selected. You can change this number as per your requirement. The code then defines the default route for the Web API using MapRoute() method. An instance of WebAPILoader is then created. The default assembly loader is replaced with our custom implementation using the Replace() method.

Then an instance of HttpSelfHostServer is created. The HttpSelfHostServer class represents a server that listens to the Web API requests. The HttpSelfHostConfiguration object is passed to the constructor of the HttpSelfHostServer. Finally, the OpenAsync() method is called to start the server. The OpenAsync() is an asynchronous call and hence the Wait() method is called that waits for the task to complete. A message is displayed in a Label control that informs the user that the host has been started.

One final thing that needs to be done is to add the connection string of the Northwind database to the host app.config file. You can copy it from the Class Library project and paste it in the host application's App.config file.

This completes the host application.

Consuming the Web API

The final step is to create a client application that calls the Customer Web API. Add another Windows Forms application to the same solution and name it WebAPIClient. Design the Windows Form as shown at the beginning of this article. Add a models folder to the project and create the Customer class as shown below:

namespace WebAPIClient.Models
{
    public class Customer
    {
        public string CustomerID { get; set; }
        public string CompanyName { get; set; }
        public string ContactName { get; set; }
        public string Country { get; set; }
    }
}

The client application needs Customer class so that the Customer returned by the Web API can be received in the client application. Although we created this class manually, you could also added Entity Data Model as before to generate this class.

Now add a reference to the System.Net.Http assembly. Then add the following code to the Click event handler of the Call Web API button.

using System.Net.Http;
using WebAPIClient.Models;
 
namespace WebAPIClient
{
    public partial class Form1 : Form
    {
        ...
 
        private void button1_Click(object sender, EventArgs e)
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:9001");
            var resp = client.GetAsync("api/customer/" + textBox1.Text).Result;
            Customer obj = resp.Content.ReadAsAsync<Customer>().Result;
            label1.Text = obj.CompanyName;
        }
    }
}

The code imports the System.Net.Http and WebAPIClient.Models namespaces. The Click event handler creates an instance of HttpClient. The BaseAddress property of the HttpClient is set to the URL at which the Web API is being published. Make sure that this URL matches with what you used in the host application.

The GetAsync() method is used to invoke the GetCustomerByID() Web API method. Notice that a CustomerID is passed as the route parameter. The ReadAsAsync() method is used to read the Customer object returned by the Web API. Finally, CompanyName is displayed in a Label control.

That's it! All the parts of the application are ready. Before you run the host and the client applications from within Visual Studio make sure that you are running Visual Studio as an Administrator. Then run the host application first and click on the "Host Web API" button to start the host. Now run the client application, enter some valid CustomerID and click on the Call Web API button. If everything goes well the CompanyName will be displayed in the Label control.

Summary

ASP.NET Web API does not need to always be hosted in IIS. You can host them in a separate process by creating a host application. Such a self-hosting is typically done using a Console application or a Windows application. This article demonstrated how to self-host Web API in a Windows application. You also learned to separate Web API controllers in a separate class library and then load that assembly in the host process using a custom assembly resolver. Finally, you also consumed the Customer Web API thus developed using HttpClient class.

Extra Reading Links

About the Author:

Bipin Joshi is an author and a .NET trainer who writes about apparently unrelated topics - yoga & technology! Bipin has been programming since 1995 and is working with .NET framework ever since its inception. He has authored or co-authored half a dozen books and numerous articles on .NET technologies. He has also penned a few books on Yoga. You can read more about him here.

 

Source: Code - Self Hosting Web API.


Tags: .NET, ASP.NET, Web API, Windows Forms




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel