Building Enterprise Side-loaded apps with OWIN

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 :-) } } } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } 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: .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } 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; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } 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

Building Enterprise apps using Brokered Windows Runtime Components

This article shows step by step how to connect a side-loaded modern app to a legacy component via the “Brokered Windows Runtime Components for Side-Loaded applications” feature. This feature comes with Windows 8.1 Update and allows Modern apps to break outside the AppContainer and connect to desktop components such as legacy .NET class libraries. This gives the side-loaded app direct access to native platform capabilities, including COM Interop and P/Invoke. For a detailed introduction I would encourage you to take a look at this Build 2014 session by @devhawk and read this MSDN white paper. A Brokered Windows Runtime Component is a new type of component that bridges the technology gap between the Windows Runtime and the .NET world. It allows you to write a touch optimized modern Store app against legacy components that sit on the same desktop. As an example I created a legacy application with a data access layer DLL that uses SQL Server Express and Linq-to-SQL, and a Windows forms executable: Here’s the code from the data access layer that fetches the employees from the Northwind database (for the fans: the SQL script to create that database is in the source code of the attached project):public static Dto.Employee[] GetAllEmployees() { using (NorthwindDataContext northWind = new NorthwindDataContext()) { var query = from e in northWind.Employees select new Dto.Employee() { Name = e.FirstName + " " + e.LastName, Title = e.Title, BirthDate = e.BirthDate, Picture = e.Photo.ToArray() }; return query.ToArray(); } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } A combination of a Brokered Windows Runtime Component and a Brokered Windows ProxyStub allowed me to reuse the data access layer of that legacy application in a modern app: I tried for a couple of hours to build and link the necessary components the manual way, as explained in the White Paper. But I’m not really skilled in building Runtime Components, and the last time I saw the internals of a C++ project was a very long time ago in a galaxy far away. When I was about to give up, the Brokered WinRT Component Project Templates for Visual Studio were released. And this is what happened then: I installed the templates: Then I added a brokered component to the solution: The Brokered Component is the component to which the side-loaded app talks. It’s a hybrid component that can get a reference to the legacy data access layer, but all its public members should be Windows Runtime compatible. This overview of Windows Runtime base data types came in handy. It’s probably obsolete in this particular sample app, but I did a bit of massaging the data. In a production application this would be the main responsibility of the Brokered Component:public Employee[] GetAllEmployees() { var dbe = Dal.GetAllEmployees(); var result = new List<Employee>(); foreach (var item in dbe) { result.Add(new Employee() { Name = item.Name, Title = item.Title, Age = Age(item.BirthDate) }); } return result.ToArray(); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } The side-loaded app can not directly talk to the Brokered Component since it’s targeting a different framework family. The following happens when you try this out: There needs to be a so called Brokered ProxySub in between the Modern app and the Brokered Windows Runtime Component. Fortunately there is a template for this: The ProxyStub project is preconfigured for its task and is populated by making a reference to the Brokered Runtime Component: Before the side-loaded app can use it, the ProxyStub needs to be registered as a COM-component. This task gets automated if you run Visual Studio as an Administrator, and configure the Linker: The Modern app needs to make a reference to the ProxyStub: The side-loaded app now has access to the Brokered Component (no MVVM here since I wanted to keep this sample as straightforward as possible):private void AppBarButton_Click(object sender, RoutedEventArgs e) { var broker = new U2UC.WinLob.BrokeredComponent.RunTimeClass(); var data = broker.GetAllEmployees(); this.Employees.ItemsSource = data; } If you run the app now, it still goes wrong: You have to make sure that the fully qualified name of the Brokered Component together with its path are defined in the app’s manifest: .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Brokered Windows Runtime Components will enable the development of a new breed of corporate line-of-business apps: touch-first modern apps that are connected to existing enterprise data and processes. Here’s the sample app, it was written with Visual Studio 2013 Update 2 (RC) for Windows 8.1 Update. If you want to play with it, don’t forget to run as Adminstrator and change the path in the app’s manifest: U2UC.WinLob.Sample.zip (1.2MB) Enjoy! XAML Brewer