This article shows how a side-loaded line-of-business Windows app can communicate through HTTP with a locally installed desktop component (a .NET class library) by making use of the Open Web Interface for .NET. Apps that are loaded from the Store can still not leave the sandbox and can only connect to servers, but since Windows 8.1 side-loaded Enterprise apps are allowed to open ports in the firewall around their own app container. Such apps are now allowed e.g. to connect to http://localhost. For more info, just check the first half of this Build 2014 session.
I can imagine that a lot of companies would like to roll out some Modern LOB apps that talk to locally installed components. HTTP is a nice protocol for that, and ASP.NET Web API would make a nice host to expose local components. If that’s your idea too, then here’s the bad news: most network administrators will simply not allow the installation/activation of an infrastructure such as IIS on the regular workstation of each employee. But don’t worry, here’s the good news: among a lot of other capabilities, the Open Web Interface for .NET (OWIN) allows you to self-host a lightweight web server in a Windows service or a console application without the need for IIS.
To illustrate this configuration, I built a small app that talks to a localhost REST provider in a .NET console app which in its turn accesses a local “legacy” .NET class library. Here’s how the app looks like:
The resemblance of this app with the one from my previous blog post is not a coincidence, of course; and I’m also reusing the legacy projects. I just added an extra button to the Windows Forms application to test the new OWIN call:
This particular use of OWIN has the same purpose as Brokered Windows Runtime Components: connecting Modern touch-optimized apps to software components local to the desktop.
Here we go, let’s start with a self-hosted Web API server. In a production environment we would do this in a Windows Service, but for now just create a new C# Windows console, no special template needed:
It may add too many references, but the fastest way to take off with OWIN as a Web API host, is installing the ASP.NET Web API OWIN Self Host Nuget package:
Create a StartUp class to configure the host. If you ever encountered ASP.NET MVC or Web API, then it should look familiar:
namespace U2UC.WinLob.OwinHost
{
using Owin;
using System.Web.Http;
public class Startup
{
// This code configures Web API. The Startup class is specified as a type
// parameter in the WebApp.Start method.
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
}
Then add a Web API controller that wraps the legacy component (add a reference) in a REST interface. The sample app will only use a GET call to retrieve the list of Northwind employees (as a JSON array):
namespace U2UC.WinLob.OwinHost
{
using System;
using System.Collections.Generic;
using System.Web.Http;
public class NorthwindController : ApiController
{
public IEnumerable<Employee> Get()
{
List<Employee> result = new List<Employee>();
foreach (var emp in U2UC.WinLob.Legacy.Dal.GetAllEmployees())
{
result.Add(
new Employee()
{
Name = emp.Name,
Title = emp.Title,
BirthDate = emp.BirthDate,
Picture = Convert.ToBase64String(emp.Picture)
}
);
}
return result;
}
}
}
The last step is to start up the OWIN host, that’s done in the console’s Main routine. The test call is not really necessary, but it’s there to show us that the host is operational:
namespace U2UC.WinLob.OwinHost
{
using Microsoft.Owin.Hosting;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
// More details on hosting WebApi here:
// http://www.asp.net/web-api/overview/hosting-aspnet-web-api/use-owin-to-self-host-web-api
public class Program
{
static void Main()
{
string baseAddress = "http://localhost:9000/";
// Start OWIN host
using (WebApp.Start<Startup>(url: baseAddress))
{
// Create HttpCient and make a request to api/northwind
HttpClient client = new HttpClient();
var response = client.GetStringAsync(baseAddress + "api/northwind").Result;
List<Employee> employees = JsonConvert.DeserializeObject<List<Employee>>(response);
Console.WriteLine("{0} Northwind employees found.", employees.Count);
Console.ReadLine(); // In the using, not after it like in the demo :-)
}
}
}
}
When the console app is started, it looks like this:
The console app is now exposing the functionality of the legacy library through HTTP, REST, and JSON.
Let’s take a look at the side-loaded Modern app now. It helps to make a reference to JSON.NET:
When the app needs to call the legacy code, it creates a HttpClient, executes the asynchronous call, and parses the JSON result. By the way: JSON.NET comes with excellent LINQ capabilities for that last step. The following code snippet comes from the code-behind of the page. I'm not using MVVM here, shame on me:
private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
// Create HttpCient and make a request to api/northwind
var client = new HttpClient();
var json = client.GetStringAsync(new Uri("http://localhost:9000/api/northwind")).Result;
var employees = JsonConvert.DeserializeObject<List<Employee>>(json);
this.Employees.ItemsSource = employees;
}
That’s it: the app now accesses local legacy code using only standard protocols. I’m missing something in the varbinary-bytearray-base64string-bitmapimage conversion of the database pictures, but it’s still a representative demo :-)
Here’s the full sample app, it was built with Visual Studio 2013. Just remember to define the App and the OwinHost as startup projects : U2UC.WinLob.Owin.zip (8MB)
Enjoy!
XAML Brewer