Owin Self Hosting

 

Creating a Self-Hosted OWIN-Based Web Api

 

We’ll start by creating a bare-bones, self-hosted Web Api using a Console application as its base. First, create a new Console project in Visual Studio, then pull down the Microsoft.AspNet.WebApi.OwinSelfHost Nuget package:

 

Install Web Api 2.2 Self Host Nuget Package:

 

PM> Install-Package Microsoft.AspNet.WebApi.OwinSelfHost -Pre

 

The Microsoft.AspNet.WebApi.OwinSelfHost Nuget package installs a few new references into our project, among them Microsoft.Owin.Hosting and Microsoft.Owin.Host.HttpListener.

 

Between these two libraries, our application can now act as its own host, and listen for HTTP requests over a port specified when the application starts up.

 

With that in place, add a new Class named Startup, and add the following code:

 

The Startup Class for a Katana-based Web Api:

// Add the following usings:

using Owin;
using System.Web.Http;
 
namespace MinimalOwinWebApiSelfHost
{
    public class Startup
    {
        // This method is required by Katana:
        public void Configuration(IAppBuilder app)
        {
            var webApiConfiguration = ConfigureWebApi();
 
            // Use the extension method provided by the WebApi.Owin library:
            app.UseWebApi(webApiConfiguration);
        }
 
 
        private HttpConfiguration ConfigureWebApi()
        {
            var config = new HttpConfiguration();
            config.Routes.MapHttpRoute(
                "DefaultApi",
                "api/{controller}/{id}",
                new { id = RouteParameter.Optional });
            return config;
        }
    }
}

As we can see, all we are really doing is setting up our default routing configuration here, similar to what we see in the standard VS template project.

 

However, instead of adding the routes specified to the routes collection in the ASP.NET pipeline, we are instead passing the HttpConfiguration as an argument to the app.UseWebApi() extension method.

 

Next, lets set up the familiar ASP.NET Web Api folder structure. Add a Models folder, and a Controllers folder. Then add a Company class to the Models folder:

 

Add a Company Class to the Models Folder:

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Next, add a CompaniesController Class to the Controllers folder:

Add a CompaniesController to the Controllers Folder:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add these usings:
using System.Web.Http;
using System.Net.Http;
using MinimalOwinWebApiSelfHost.Models;
 
namespace MinimalOwinWebApiSelfHost.Controllers
{
    public class CompaniesController : ApiController
    {
        // Mock a data store:
        private static List _Db = new List
            {
                new Company { Id = 1, Name = "Microsoft" },
                new Company { Id = 2, Name = "Google" },
                new Company { Id = 3, Name = "Apple" }
            };
 
 
        public IEnumerable Get()
        {
            return _Db;
        }
 
 
        public Company Get(int id)
        {
            var company = _Db.FirstOrDefault(c => c.Id == id);
            if(company == null)
            {
                throw new HttpResponseException(
                    System.Net.HttpStatusCode.NotFound);
            }
            return company;
        }
 
 
        public IHttpActionResult Post(Company company)
        {
            if(company == null)
            {
                return BadRequest("Argument Null");
            }
            var companyExists = _Db.Any(c => c.Id == company.Id);
 
            if(companyExists)
            {
                return BadRequest("Exists");
            }
 
            _Db.Add(company);
            return Ok();
        }
 
 
        public IHttpActionResult Put(Company company)
        {
            if (company == null)
            {
                return BadRequest("Argument Null");
            }
            var existing = _Db.FirstOrDefault(c => c.Id == company.Id);
 
            if (existing == null)
            {
                return NotFound();
            }
 
            existing.Name = company.Name;
            return Ok();
        }
 
 
        public IHttpActionResult Delete(int id)
        {
            var company = _Db.FirstOrDefault(c => c.Id == id);
            if (company == null)
            {
                return NotFound();
            }
            _Db.Remove(company);
            return Ok();
        }
    }
}

In the above code, for the moment, we are simply mocking out a data store using a List<Company>. Also, in a real controller we would probably implement async controller methods, but for now, this will do.

 

To complete the most basic functionality of our self-hosted Web Api application, all we need to do is set up the Main() method to start the server functionality provided by HttpListener.

 

Add the following usings and code the the Program.cs file:

 

Start the Application in the Main() Method:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add reference to:
using Microsoft.Owin.Hosting;
 
namespace MinimalOwinWebApiSelfHost
{
    class Program
    {
        static void Main(string[] args)
        {
            // Specify the URI to use for the local host:
            string baseUri = "http://localhost:8080";
 
            Console.WriteLine("Starting web Server...");
            WebApp.Start(baseUri);
            Console.WriteLine("Server running at {0} - press Enter to quit. ", baseUri);
            Console.ReadLine();
        }
    }
}

Console Output from the Self-Hosted Web Api Startup:

 

output web api

 

 

Create a Basic Web Api Client Application

 

We will create a simple Console application to use as a client in consuming our Web Api.

 

Create a new Console application, and then add the Microsoft.AspNet.WebApi.Client library from Nuget:

 

Add the Web Api 2.2 Client Library from Nuget:


PM> Install-Package Microsoft.AspNet.WebApi.Client -Pre

 

Now, add a class named CompanyClient and add the following using statements and code:

 

Define the CompanyClient Class in the Web Api Client Application:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add Usings:
using System.Net.Http;
 
namespace MinimalOwinWebApiClient
{
    public class CompanyClient
    {
        string _hostUri;
        public CompanyClient(string hostUri)
        {
            _hostUri = hostUri;
        }
 
 
        public HttpClient CreateClient()
        {
            var client = new HttpClient();
            client.BaseAddress = new Uri(new Uri(_hostUri), "api/companies/");
            return client;
        }
 
 
        public IEnumerable GetCompanies()
        {
            HttpResponseMessage response;
            using (var client = CreateClient())
            {
                response = client.GetAsync(client.BaseAddress).Result;
            }
            var result = response.Content.ReadAsAsync>().Result;
            return result;
        }
 
 
        public Company GetCompany(int id)
        {
            HttpResponseMessage response;
            using (var client = CreateClient())
            {
                response = client.GetAsync(
                    new Uri(client.BaseAddress, id.ToString())).Result;
            }
            var result = response.Content.ReadAsAsync().Result;
            return result;
        }
 
 
        public System.Net.HttpStatusCode AddCompany(Company company)
        {
            HttpResponseMessage response;
            using (var client = CreateClient())
            {
                response = client.PostAsJsonAsync(client.BaseAddress, company).Result;
            }
            return response.StatusCode;
        }
 
 
        public System.Net.HttpStatusCode UpdateCompany(Company company)
        {
            HttpResponseMessage response;
            using (var client = CreateClient())
            {
                response = client.PutAsJsonAsync(client.BaseAddress, company).Result;
            }
            return response.StatusCode;
        }
 
 
        public System.Net.HttpStatusCode DeleteCompany(int id)
        {
            HttpResponseMessage response;
            using (var client = CreateClient())
            {
                response = client.DeleteAsync(
                    new Uri(client.BaseAddress, id.ToString())).Result;
            }
            return response.StatusCode;
        }
    }
}

We’ve written (rather hastily, I might add) a crude but simple client class which will exercise the basic API methods we have defined on out Web Api application.

 

We’re working against a mock data set here, so we take some liberties with Id’s and such in order to run and re-run the client application without running into key collisions.

 

We see in the above, we created a convenience/factory method to provide an instance of HttpClient as needed, pre-configured with a base Uri matching the route for the ClientController in our Web Api.

 

From there, we simply define a local method corresponding to each API method, which we can use in our console application.

 

We can get this thing into running order by adding the following code to the Program.cs file of the client application:

 

The Program.cs File for the API Client Application:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
// Add Usings:
using System.Net.Http;
 
 
namespace MinimalOwinWebApiClient
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Read all the companies...");
            var companyClient = new CompanyClient("http://localhost:8080");
            var companies = companyClient.GetCompanies();
            WriteCompaniesList(companies);
 
            int nextId  = (from c in companies select c.Id).Max() + 1;
 
            Console.WriteLine("Add a new company...");
            var result = companyClient.AddCompany(
                new Company 
                { 
                    Id = nextId, 
                    Name = string.Format("New Company #{0}", nextId) 
                });
            WriteStatusCodeResult(result);
 
            Console.WriteLine("Updated List after Add:");
            companies = companyClient.GetCompanies();
            WriteCompaniesList(companies);
 
            Console.WriteLine("Update a company...");
            var updateMe = companyClient.GetCompany(nextId);
            updateMe.Name = string.Format("Updated company #{0}", updateMe.Id);
            result = companyClient.UpdateCompany(updateMe);
            WriteStatusCodeResult(result);
 
            Console.WriteLine("Updated List after Update:");
            companies = companyClient.GetCompanies();
            WriteCompaniesList(companies);
 
            Console.WriteLine("Delete a company...");
            result = companyClient.DeleteCompany(nextId -1);
            WriteStatusCodeResult(result);
 
            Console.WriteLine("Updated List after Delete:");
            companies = companyClient.GetCompanies();
            WriteCompaniesList(companies);
 
            Console.Read();
        }
 
 
        static void WriteCompaniesList(IEnumerable companies)
        {
            foreach(var company in companies)
            {
                Console.WriteLine("Id: {0} Name: {1}", company.Id, company.Name);
            }
            Console.WriteLine("");
        }
 
 
        static void WriteStatusCodeResult(System.Net.HttpStatusCode statusCode)
        {
            if(statusCode == System.Net.HttpStatusCode.OK)
            {
                Console.WriteLine("Opreation Succeeded - status code {0}", statusCode);
            }
            else
            {
                Console.WriteLine("Opreation Failed - status code {0}", statusCode);
            }
            Console.WriteLine("");
        }
    }
}

Now, if we run the Self-Hosted Web Api, we should see the following console output after it has started up:

Console Output from the Web Api Client Application:

 

Owin web API check endpoints get