Pranay Rana: 2019

Thursday, January 31, 2019

Self Host Angular and WebApi Using Owin

Full Source code at GitHub : OwinWebapiAngularHost

In development there are situations(organization restrictions, developing POC/Demo, there is need of control on server) where developer doesn't have Server application(IIS,Tomcat etc.), where developer got and deploy Web application. So to overcome these situation developer need environment which similar to Server application, basically issue can be resolved by having Self hosting application. Self hosting application allows to deploy web application and provide similar functionality as server application.
Question rises how to create self hosting application, answer is by making use of Owin like Framework. Below post is about how to create self hosting application with help of Owin framework which in turn allows to host Asp.Net WebApi and Angular application.

Creating Self Hosting application
To create self hosting application, developer can create either Console, WPF or Windows Form Application or Windows Service by choosing Console, WPF or Windows Form or WindowsService project type provided in visual studio.
For this post I am choosing Windows Service project as given in below image

Once click "ok button" it will create windows service application in visual studio. But when run application by pressing "F5" in visual studio it display message


To avoid error in development environment , do check for service running in user interactive check flag "UserInteractive". Below code shows how to do it

static class Program
{
        /// 
        /// The main entry point for the application.
        /// 
    static void Main(string[] args)
    {
        try
        {
            //flag check service running in user interactive mode i.e. debug mode 
            if (Environment.UserInteractive)
            {
                Service1 service1 = new Service1();
                service1.TestStartup(args); // start service in debug mode
                Console.WriteLine("Service Started at: http://localhost:8081/File/action");
                Console.ReadLine(); // stop service in debug mode
                service1.TestStop();
            }
            else
            {

                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[]
                {
                 new Service1()
                };
                ServiceBase.Run(ServicesToRun);
            }
        }
        catch(Exception ex)
        {
           Console.WriteLine(ex);
           //log error 
           Console.ReadLine();
        }
    }
}


Once done add below code in service.cs file which is related to windows service application

public partial class Service1 : ServiceBase
{
    public Service1()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
       if (ConfigurationManager.AppSettings["baseAddress"] != null)
          baseAddress = ConfigurationManager.AppSettings["baseAddress"].ToString();
       server = WebApp.Start(baseAddress);
    }

    protected override void OnStop()
    {
        server.Dispose();
    }

    internal void TestStartup(string[] args)
    {
        this.OnStart(args);
    }

    internal void TestStop()
    {
        this.OnStop();
    }
    
    private IDisposable server;
    string baseAddress = "http://*:8081/";
} 
Line of code written in OnStart method of service file is most important code, "WebApp.Start()" this method start Owin web server at "8081" port by making use of settings provided in "OwinStartUp"(setup of this class discussed in detail below) class.

Installing Owin
After creating and setting Windows service, now it's time to install Owin framework which provide support for hosting web based application. Owing installation can be done via "Package Manager console (this console can be opened up from Visual studio menu Tools>>Nuget Package Manager >> Package Manager Console)" or by "Manage Nuget Packages(this is menu option comes by right clicking project in visual studio)".

//run below command in package manager console to install owin support
Install-package Microsoft.Owin.SelfHost
//or search package "Microsoft.Owin.SelfHost" in package management window  
This command installs following packages, one can view in package.json file of project or in references as dll.
  
  Microsoft.Owin
  Microsoft.Owin.Diagnostics
  Microsoft.Owin.Host.HttpListener
  Microsoft.Owin.Hosting
  Microsoft.Owin.SelfHost
  Owin

Installation of basic packages enable Owin in windows service application. To make use of Owin, developer needs to add settings which decide what type of application/files can be served by self hosted owin server application. Below is basic "OwinStartUp" class that used by "WebApp.Start()" method to start server.

//OwinStartUp.Cs
public class OwinStartUp
{
    public void Configuration(IAppBuilder app)
    {
#if DEBUG
        app.UseErrorPage();
#endif
        app.UseWelcomePage("/");
    }
}


Enable WebApi Hosting
To enable WebApi hosting in above created self hosted owin based application, Add below package

//run below command in package manager console to install WebApi support
Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
//or search package "Microsoft.AspNet.WebApi.OwinSelfHost" in package management window  

This command installs following packages, one can view in package.json file of project or in references as dll.
  
  Microsoft.AspNet.WebApi.Client
  Microsoft.AspNet.WebApi.Core
  Microsoft.AspNet.WebApi.Owin
  Microsoft.AspNet.WebApi.OwinSelfHost
  Newtonsoft.Json

Once installation done, below line of code in start setting class enable support of WebApi hosting in application

public class OwinStartUp
{
    public void Configuration(IAppBuilder appBuilder)
    {
  // Configure Web API for self-host.
  //Install-Package Microsoft.AspNet.WebApi.OwinSelfHost

  //removing support of xmlformatter
  HttpConfiguration config = new HttpConfiguration();
  config.Formatters.Remove(config.Formatters.XmlFormatter);

  //webapi route configuration
  config.Routes.MapHttpRoute(
   name: "DefaultApi",
   routeTemplate: "api/{controller}/{action}/{id}",
   defaults: new { id = RouteParameter.Optional }
  );

  config.MapHttpAttributeRoutes();

  //adding config for WebApi support
  appBuilder.UseWebApi(config);
    }
}

After adding support for WebApi, developer can add WebApi controller as given below.

public class TestController : ApiController
{
    [HttpGet]
    public string GetFileName()
    {
        return "Test";
    }
} 


Enable support for CORS
Above add support for WebApi, but it won't allows to access form other domain apart form hosted domain i.e. from Cross domain. Developer can resolve issue of CORS as below.

//run below command in package manager console to install Cors support
Install-Package Microsoft.Owin.Cors
//or search package "Microsoft.Owin.Cors" in package management window  

This command installs following packages, one can view in package.json file of project or in references as dll.
  
  Microsoft.Owin.Cors
  Microsoft.AspNet.Cors

Once installation done, below line of code enable CORS
  
public class OwinStartUp
{
    public void Configuration(IAppBuilder appBuilder)
    {
        //webapi code done before remain as is
  
        //Install-Package Microsoft.Owin.Cors
        appBuilder.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    }
}

So now self host is ready with WebApi hosted in it.

Enabling Angular/Static file hosting
Enabling self host for angular is similar to enable self host for allowing browsing of static html files i.e. web site. Because angular is framework for creating single page application which access by accessing "index.html" file only.

Note:
For hosting angular application please perform prod build (by using angular cli command ng build --prod) of you application as it has prod generated code i.e. html page with javascript only. Guide for Angular deployment : https://angular.io/guide/deployment

To enable WebApi hosting in above created self hosted owin based application, Add below package

//run below command in package manager console to provide static website /angular app support
Install-Package Microsoft.Owin.StaticFiles
//or search package "Microsoft.Owin.StaticFiles" in package management window  

This command installs following packages, one can view in package.json file of project or in references as dll.
  
  Microsoft.Owin.FileSystems
  Microsoft.Owin.StaticFiles

Once installation done, below line of code in start setting class enable support of Static Web app/Angualr app hosting in application

public class OwinStartUp
{
    public void Configuration(IAppBuilder appBuilder)
    {
       //hosting static files i.e. angular
       //install-package Microsoft.Owin.SelfHost
       //install-package Microsoft.Owin.StaticFiles
       var options = new FileServerOptions();
       options.EnableDirectoryBrowsing = true;
       options.FileSystem = new PhysicalFileSystem("./app");
       options.StaticFileOptions.ServeUnknownFileTypes = true;
       appBuilder.UseFileServer(options);

      //code done for WebApi remain as is if you want webapi support 
   }
}

Below is full source code done in this excercise
    
    public class OwinStartUp
    {
        public void Configuration(IAppBuilder appBuilder)
        {

            //hosting static files i.e. angular
            //install-package Microsoft.Owin.SelfHost
            //install-package Microsoft.Owin.StaticFiles
            var options = new FileServerOptions();
            options.EnableDirectoryBrowsing = true;
            options.FileSystem = new PhysicalFileSystem("./app");
            options.StaticFileOptions.ServeUnknownFileTypes = true;
            appBuilder.UseFileServer(options);


            // Configure Web API for self-host.
            //Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
            HttpConfiguration config = new HttpConfiguration();
            config.Formatters.Remove(config.Formatters.XmlFormatter);

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            config.MapHttpAttributeRoutes();
            appBuilder.UseWebApi(config);

            //Install-Package Microsoft.Owin.Cors
            appBuilder.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        }
    }

Full Source code at GitHub : OwinWebapiAngularHost

Saturday, January 19, 2019

Return Given Type from Generic method

In C#, Genetic method as below, which can return value of multiple types (i.e. below method can return value of any primitive types or reference types).
   public T GetValue<T>()
   {
  
   }
so one cannot return value directly from method. As T is template type & it can be any of type, so compiler doesn't allow direct conversation of return value to type T.
   public T GetValue<T>()
   {
     //Compilation error (line 13, col 10): Cannot implicitly convert type 'Customer' to 'T'
     return new Customer();
     //this error says that T is template type and it can be of any type (primitive or reference)
   }
Above will not work because Template type of Generic method get replaced at Runtime and Compiler of C# cannot able to figure out Generic type actual type at compile time. for example call to method is like as below
// call to method
GetValue<int>()

//then at runtime method will be like as below 
public int GetValue<int>()
{
 //assuming generic method return customer object only 
 return new Customer();
}

Solution 
As explained in detail problem with generic method is to return value of requested return type (i.e. Runtime type which replaces generic Template type T). So to solve problem return value to object type(as object is base class of all types in C# .net) and then convert it to generic template type. Below is code for that solves problem
public T GetValue<T>()
{
  Type typeParameterType = typeof(T);
    Type typeParameterType = typeof(T);
  if(typeParameterType.ToString()=="System.Int32")
    return (T)(object)1;
   if(typeParameterType.ToString()=="Customer")
    return (T)(object)new Customer()
}

But problem with above code is ,for every new return type value new condition required to be added in method i.e it requires to change method for every new return type and it violates Single responsibility principle.

This can easily be resolved by making use of C# in built method Convert.ChangeType, below is code for the same
  (T)Convert.ChangeType(1, typeParameterType)//here T is generic type

Below is code for getting value of column form DataRow object which is based on above discussion
  public static T GetColumnValue<T>(this DataRow dr, string columnName)
  {
     //get type of Template type T
     Type typeParameterType = typeof(T);
     //get type of Template type T, this works when requested type is nullable
     typeParameterType = Nullable.GetUnderlyingType(typeParameterType) ?? typeParameterType;

     //check value present or not , if not return default value of generic type
     return dr[columnName] != DBNull.Value
                ? (T)Convert.ChangeType(dr[columnName], typeParameterType)
                : default(T);
   } 
//use of this method in code 

datarow.GetColumnValue<int>("id");
datarow.GetColumnValue<int?>("orderid");
datarow.GetColumnValue<double>("amount");

so above is Generic method to get value of datacolumn of given type. Method get value of return type from template type T and then does conversation of datacolumn value using Convert.ChangeType.

Below is example of Factory Design pattern using same technique
public class CommandFactory
{       
    //only create object of type which implement ICommand
    public static T GetCommand<T>() where T:  ICommand
    {
      //it create object using Template type T and by making use of reflection
      //once create factory this way there is no need to open it again for modification
        Type type = typeof(T);
        Object obj = Activator.CreateInstance(type);
        return (T)obj;
    }
}

Read about this in detail here : Factory Design Pattern With Generics