Sunday, April 8, 2018

Convert Dot net Core application to Service Fabric application

How to convert my existing dot.net Core Web API application to Azure service fabric web api.

I've dot.net core web api already been built and deployed in the azure web app. Now, I'm trying to deploy the same application in the azure service fabric. Also I want run the service fabric web api individually on IIS express without SF cluster.

Here is the steps, I followed to modify the existing dot.net core to SF application

1. Add Service Fabric Project into existing solution (Either existing solution or new solution)
2. Add the following Service fabric packages to the existing web api project

    <PackageReference Include="Microsoft.ServiceFabric" Version="6.1.472" />
    <PackageReference Include="Microsoft.ServiceFabric.AspNetCore.Kestrel" Version="3.0.472" />
    <PackageReference Include="Microsoft.ServiceFabric.Data" Version="3.0.472" />
    <PackageReference Include="Microsoft.ServiceFabric.Services" Version="3.0.472" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="2.3.0" />


3. Add the following folders to the existing web api project

    Add PackageRoot folder and config folder. Settings.xml and ServiceManifest.xml



4. In Settings.xml, add the following default content

<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <!-- Add your custom configuration sections and parameters here -->
  <!--
  <Section Name="MyConfigSection">
    <Parameter Name="MyParameter" Value="Value1" />
  </Section>
  -->
</Settings>
5. In ServiceManfiest.xml, add the following content

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="Caterpillar.Application.WebApi"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType.
         This name must match the string used in RegisterServiceType call in Program.cs. -->
    <StatefulServiceType ServiceTypeName="existingWebApiType" HasPersistedState="true" />
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>exisitingWebApi.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
  </CodePackage>

  <!-- Config package is the contents of the Config directoy under PackageRoot that contains an
       independently-updateable and versioned set of custom configuration settings for your service. -->
  <ConfigPackage Name="Config" Version="1.0.0" />

</ServiceManifest>


Here,

  •  I've used StatefulService, It can also be StatelessService. Just change the serviceType based on the need 
  • existingWebApiType - is the name of the service type (change based on your application name)
  • exisitingWebApi.exe - is the dot.net core application exe name

4. In general, Dot.net Core application is created and run on 32 bit(x86), whereas  ServiceFabric application needs to run on 64 bit. Convert your existing project runtime as x64.


5. Changes in Program.cs

Remove the existing webHostBuilder and add the following code

using Microsoft.ServiceFabric.Services.Runtime;       
         ServiceRuntime.RegisterServiceAsync("existingWebApiType", context => new WebApi(context)).GetAwaiter().GetResult();
                Thread.Sleep(Timeout.Infinite);

6. Add WebApi.cs to the existing application with following content

using System;
using System.Collections.Generic;
using System.Fabric;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ServiceFabric.Services.Communication.AspNetCore;
using Microsoft.ServiceFabric.Services.Communication.Runtime;
using Microsoft.ServiceFabric.Services.Runtime;
using Microsoft.ServiceFabric.Data;

namespace existingApplication
{
    /// <summary>
    /// The FabricRuntime creates an instance of this class for each service type instance.
    /// </summary>
    internal sealed class WebApi : StatefulService
    {
        public WebApi(StatefulServiceContext context)
            : base(context)
        { }

        /// <summary>
        /// Optional override to create listeners (like tcp, http) for this service instance.
        /// </summary>
        /// <returns>The collection of listeners.</returns>
        protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
        {
            return new ServiceReplicaListener[]
            {
                new ServiceReplicaListener(serviceContext =>
                    new KestrelCommunicationListener(serviceContext, (url, listener) =>
                    {
                        //ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                        return new WebHostBuilder()
                       
                                    .UseKestrel()
                                    .ConfigureServices(
                                        services => services
                                            .AddSingleton<StatefulServiceContext>(serviceContext)
                                            .AddSingleton<IReliableStateManager>(this.StateManager))
                                    .UseContentRoot(Directory.GetCurrentDirectory())
                                    .UseStartup<Startup>()
                                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
                                    .UseUrls(url)
                                    .Build();
                    }))
            };
        }
    }
}



7. Add existing project reference to service fabric project

8. Add ApplicationManifest.xml in Service fabric project

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="ConvertingServiceFabricAppType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="existingWebApi_TargetReplicaSetSize" DefaultValue="3" />
    <Parameter Name="existingWebApi_MinReplicaSetSize" DefaultValue="1" />
    <Parameter Name="existingWebApi_PartitionCount" DefaultValue="3" />
  </Parameters>
  <!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion
       should match the Name and Version attributes of the ServiceManifest element defined in the
       ServiceManifest.xml file. -->
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="existingWebApi" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
  </ServiceManifestImport>
  <DefaultServices>
    <!-- The section below creates instances of service types, when an instance of this
         application type is created. You can also create one or more instances of service type using the
         ServiceFabric PowerShell module.
       
         The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. -->
    <Service Name="existingWebApi">
      <StatefulService ServiceTypeName="existingWebApiType" TargetReplicaSetSize="[existingWebApi_TargetReplicaSetSize]" MinReplicaSetSize="[existingWebApi_MinReplicaSetSize]">
        <UniformInt64Partition PartitionCount="[existingWebApi_PartitionCount]" LowKey="-9223372036854775808" HighKey="9223372036854775807" />
      </StatefulService>
    </Service>
  </DefaultServices>
</ApplicationManifest>





Wednesday, April 10, 2013

Dynamically adding new HTML elements using jquery

There are times, where we need to add a new html elements in client-side using javascript or jquery. Adding a new html element using javascript requires more steps to do. If there is any ready available javascripts functions, then it will be very easy to use.

Here is the javascript function for append new element to the specified target location.

function addElement(tagType, target, parameters) {
        //Create element
        if (typeof tagType != 'undefined')
           var newElement = document.createElement(tagType);

        //Add parameters
        if (typeof newElement != 'undefined') {
            if (typeof parameters != 'undefined') {
                for (parameterName in parameters) {
                    newElement.setAttribute(parameterName, parameters[parameterName]);
                }
            }
        }
        //Append element to target
        if (typeof target != 'undefined') {
            if (document.getElementById(target) != null)
                document.getElementById(target).appendChild(newElement);
        }

        return newElement;
  }

Here is the sample to use the above function

 addElement('input', "maincontent", {
            'id': 'newElementId',
            'name': 'newElementName',
            'type': 'text',
            'value': 'javascript',
            'size': '15'
        });

The above javascript sample can be changed as jquery plugin.

Here is the jquery plugin for append new element to the target.

 $.fn.appendNewElement = function addElement(tagType, parameters) {
            //Create element
            if (typeof tagType != 'undefined')
                var newElement = document.createElement(tagType);

            //Add parameters
            if (typeof newElement != 'undefined') {
                if (typeof parameters != 'undefined') {
                    for (parameterName in parameters) {
                        newElement.setAttribute(parameterName, parameters[parameterName]);
                    }
                }
            }

            //Append element to target
            $(this).append(newElement);

            return newElement;
        }

Here is the sample to use the above jquery plugin

$('#maincontent').appendNewElement('input', {
            'id': 'newElementId',
            'name': 'newElementId',
            'type': 'text',
            'value': 'jquery',
            'size': '15'
        });

 Here is the sample, which uses the above plugins


Sunday, January 8, 2012

Asynchoronous Invocations

Functions can be invoked asynchronously via many ways. here is simplest way to call WCF function in ASP MVC asynchronously..

1. Create a new ASP.net MVC project
2. Add a new WCF project to the solution


 public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }
}

This is the default WCF project with implementation.


Add the following to the controller to invoke the function asynchronously.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyWcfService;

namespace Sample1.Controllers
{
    [HandleError]
    public class HomeController : AsyncController
    {

        IService1 service = new Service1();

        //delegate string asyncDelegate(int id);

        public void IndexAsync()
        {
            ViewData["Message"] = "Welcome to ASP.NET MVC!";

            int num = 5;

            for (int i = 0; i < num; i++)
            {
                Func<int, string> myAction = input =>
                {
                    return service.GetData(input);
                };

                AsyncCallback mycallBack = result =>
                {
                    AsyncManager.Parameters["myString"] = myAction.EndInvoke(result);
                    AsyncManager.OutstandingOperations.Decrement();
                };

                myAction.BeginInvoke(i, mycallBack, null);
             }
         }

        public ActionResult IndexCompleted(string myString)
        {
            return this.View((object)myString);
        }

        public ActionResult About()
        {
            return View();
        }
    }
}

IndexAsync & IndexCompleted is used to call the controller asynchronously.

Action or Func has BeginInvoke & EndInvoke methods which is used to call the method asynchoronously.

Properties added to AsyncManager.Parameters can be accessed in Completed async controller as a paramters.

Sunday, January 1, 2012

Simple Dot Net Extension

Simple Class Extension can be written using "this" keyword in the parameter. These extensions can be used for Dot net and static classes.

public static class MyExtension
{
     public static string myString(this string s)
     {
         return "my string is:" + s;
     }
}

public class SimpleExtensionTrial
{
   public static void Main ( )
  {
          string  name = "Dot Net Extension"
          System.Console.WriteLine( name.myString());
   }
}


Output:
my string is: Dot Net Extension