Porting your WebApi 2.2 app to Azure Service Fabric

Now, to start talking about this, you gotta know why this is spawned off instead of spawning off a “hello world” to service fabric. I’m back to writing after a long time and it’s only fitting I do share what I have been doing meanwhile.

Usually in a production scenario you’d end up with a case where you have your applications lying around in several tiers. To be honest, I’m pointing reference to a production environment which is microservices driven. If you’re reading this and questioning why I did that you probably want to go down here to get yourself started with the basic concepts of Azure Service Fabric.

Now, I hope you have familiarized yourself with service fabric by now and I can start talking about how you can port your existing IIS hosted Asp.net Web Api 2.2 application to a self-hosted statless web api service in Azure Service Fabric.

To get yourself started please install Azure Service Fabric local development environment in your machine from here and go through the set of instructions to get yourself started. When you’re done with these, you’d see Visual Studio come up with a new set of project types for service fabric.

And it would pretty much like the following:

servicefabricprojecttype

Now, before we click the that elusive OK button, we need to understand what are the tasks at hand here. We have to do two things here.

1. Make sure our web api 2.2 app is compatible with self host as it was using IIS.

2. Make sure we can salvage the same Visual Studio project we used for our web project.

Making sure the existing web api 2.2 app is compatible of self hosting:

  1. For number one, one might think it should be farely easy to port a IIS driven web api app to a self hosted app, the reality might not be that easy. First, make sure you have a OWIN startup class initiated. Usually you would have one if you are using OWIN. And you’d also need a Program.cs file which is standard one for a console application as now your web app would be  a self-hosted application. So go ahead and add these two files to your web project and if you need reference, both of them are shown here.
  2. Now, although you have a startup.cs and Program.cs initiated already, you still haven’t converted your web app project to a console application. To do so, please go over your project properties and  on the Applications section, select Output Type as Console Application and set the Program class as the Startup object. Now, if you forget to add Program.cs as startup object which you’d only be able to do after you have created that file with a static void Main(string[] args) initiated on it, as long as it is named Program.cs the project would invoke it automatically.
  3. If you are using anything from Microsoft.Owin.Host.SystemWeb library, please make sure that these wont work anymore for you. For example if you are using code segments like the following to resolve file path to your traditional web app deployment and subsidiary folders like App_data, it wont work anymore for you.
     string path = System.Web.Hosting.HostingEnvironment.MapPath(@"~/App_Data/EmailTemplates/");
    

    So for things like these you might have to resort yourself to solutions that resolves deployment path in a console application.

  4. Now, there are some other pranks too. If you are familiar with Asp.net Identity and use it for your default identity provider, you’re in for a treat. Usually when you develop a expirable token generation paradigm for email and passwords, you’d need to use a IDataProtectionProvider which is usually the MachineKeyDataProtectionProvider under the namespace of Microsoft.Owin.Host.SystemWeb.DataProtection which you’d probably ditch because you would be using owin self host/Katana now. So, expect a null there where you try something like app.GetDataProtectionProvider() where app is your IAppBuilder. I ran into this myself and thanks to Katana being open source, you just pick up the MachineKeyDataProtectionProovider class from here.Just make sure you use it as  IDataProtectionProvider like the following:
    using System;
    using System.Web.Security;
    using Microsoft.Owin.Security.DataProtection;
    
    namespace TaskCat.Lib.DataProtection
    {
        using DataProtectionProviderDelegate = Func<string[], Tuple<Func<byte[], byte[]>, Func<byte[], byte[]>>>;
        using DataProtectionTuple = Tuple<Func<byte[], byte[]>, Func<byte[], byte[]>>;
    
        ///
    <summary>
        /// Used to provide the data protection services that are derived from the MachineKey API. It is the best choice of
        /// data protection when you application is hosted by ASP.NET and all servers in the farm are running with the same Machine Key values.
        /// </summary>
    
        internal class MachineKeyDataProtectionProvider: IDataProtectionProvider
        {
            ///
    <summary>
            /// Returns a new instance of IDataProtection for the provider.
            /// </summary>
    
            /// <param name="purposes">Additional entropy used to ensure protected data may only be unprotected for the correct purposes.</param>
            /// <returns>An instance of a data protection service</returns>
            public virtual MachineKeyDataProtector Create(params string[] purposes)
            {
                return new MachineKeyDataProtector(purposes);
            }
    
            public virtual DataProtectionProviderDelegate ToOwinFunction()
            {
                return purposes =>
                {
                    MachineKeyDataProtector dataProtecter = Create(purposes);
                    return new DataProtectionTuple(dataProtecter.Protect, dataProtecter.Unprotect);
                };
            }
    
            IDataProtector IDataProtectionProvider.Create(params string[] purposes)
            {
                return this.Create(purposes);
            }
        }
    }
    

    And you’d need to do the same with MachineKeyDataProtector class and use it as a IDataProtector like the following:

    using System.Web.Security;
    using Microsoft.Owin.Security.DataProtection;
    
    namespace TaskCat.Lib.DataProtection
    {
        internal class MachineKeyDataProtector: IDataProtector
        {
            private readonly string[] _purposes;
    
            public MachineKeyDataProtector(params string[] purposes)
            {
                _purposes = purposes;
            }
    
            public virtual byte[] Protect(byte[] userData)
            {
                return MachineKey.Protect(userData, _purposes);
            }
    
            public virtual byte[] Unprotect(byte[] protectedData)
            {
                return MachineKey.Unprotect(protectedData, _purposes);
            }
        }
    }
    
    

    Then you can use it as your replacement of your old one from Microsoft.Owin.Host.SystemWeb.DataProtection. This is not really needed if you don’t use Asp.net Identity but of to good use if you land in the same problem.Now, hopefully your current web api app would be self hosted just fine if you try something like the following:

    // Start OWIN host
    using (WebApp.Start<Startup>(url: baseAddress))
    {
      Console.WriteLine("Press ENTER to stop the server and close app...");
      Console.ReadLine();
    }
    

Now, lets try salvaging that Visual Studio project as much as we can.

Project changes when it comes to Visual Studio

  1. Now, you can use the converted project but from my personal experience it would be easier for you if you just click the new ServiceFabric project button now and create a new Stateless WebApi project. You can port/reuse most of your code and as the boilerplates are already written, you don’t really have to rewrite that.
  2. If you want to keep the old project intact, you can of course reference the old project in the new stateless web api service project and use your old startup class to hook up the OwinCommunicationListener instead of the one that it comes with. But beware, nuget might make it a nightmare for you if dependencies are not met/mismatched.

Hope you guys have fun with Azure Service Fabric and if you really want to look for more how you can do you own stateless web api from scratch take a look here. If I find time, I’d write one too.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s