Architecture – Proxmedia https://pxm-software.com Software Outsourcing & Nearshore Development Mon, 27 Feb 2017 14:01:08 +0000 en-US hourly 1 https://wordpress.org/?v=4.7.2 Using Windows Azure Service Bus Topics in distributed systems https://pxm-software.com/using-windows-azure-service-bus-topics-in-distributed-systems/ Wed, 02 Dec 2015 19:47:26 +0000 https://proxmedia.pl:99/en/?p=4087 Service Bus topics allow to perform one way communication using publish/subscribe model. In that model the Service Bus topic can be treated as a intermediary queue that multiple users/components can subscribe to. When publishing a message we can choose to route it to all subscribers or to apply filters for each subscription resulting in each […]

Artykuł Using Windows Azure Service Bus Topics in distributed systems pochodzi z serwisu Proxmedia.

]]>
Service Bus topics allow to perform one way communication using publish/subscribe model. In that model the Service Bus topic can be treated as a intermediary queue that multiple users/components can subscribe to.

When publishing a message we can choose to route it to all subscribers or to apply filters for each subscription resulting in each subscriber receiving messages that are addressed to him. With Service Bus topics we can easily scale distributed applications communicating with each other within or across multiple networks.

In this article I will show you how to build and test Service Bus topic on your local computer. In our example we will simulate sending messages from the web, mobile and service application to the Service Bus Topic.

These messages will be then routed to relevant subscriptions based on defined filters we assigned for each of them. Subscription for messages from the web application will be using multiple auto scalable worker roles to process the business logic. Same will apply for service messages. If we don’t expect a lot of traffic coming from mobile application, we can then use single worker role (with failover settings).

Autoscaling worker roles can be performed using Enterprise Library 5.0 – Autoscaling Application Block (aka WASABi). This will ensure that appropriate number of worker roles will be automatically started when traffic increases and stopped if the traffic will ease.

See high level architecture diagram below:

ServiceBusTopic

 

In order to start, we need to first install “Service Bus 1.0 for Windows Server” (runs on Win7 as well). After installation please go to start > Service Bus 1.0 > Service Bus Configuration. Then use the wizard to set up the web farm first and after that, join your computer to that farm – this will essentially create namespace within the namespace on your local machine.

ServiceBus-configuration

After you configure the Service Bus installation you will get endpoint address that your local application will use to connect to the Service Bus. You may notice that after installation there are 2 databases created on you local MSSQL server, see below image:

ServiceBus-tables

In order to connect to our Service Bus we will use the function below. This will create connection string the pass in to the NamespaceManager class.

  //use this setting when deploying to Windows Azure
  <add key="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://[your namespace].servicebus.windows.net;SharedSecretIssuer=owner;SharedSecretValue=[your secret]" />

 public static string getLocalServiceBusConnectionString()
 {
    var ServerFQDN = System.Net.Dns.GetHostEntry(string.Empty).HostName;
    var ServiceNamespace = "ServiceBusDefaultNamespace";
    var HttpPort = 9355;
    var TcpPort = 9354;

    var connBuilder = new ServiceBusConnectionStringBuilder();
    connBuilder.ManagementPort = HttpPort;
    connBuilder.RuntimePort = TcpPort;
    connBuilder.Endpoints.Add(new UriBuilder() { Scheme = "sb", Host = ServerFQDN, Path = ServiceNamespace }.Uri);
    connBuilder.StsEndpoints.Add(new UriBuilder() { Scheme = "https", Host = ServerFQDN, Port = HttpPort, Path = ServiceNamespace }.Uri);

    return connBuilder.ToString();
 }

Within the worker role we will use NamespaceManager to create Service Bus Topic (if does not exist). We will also create subscriptions and associated filters.
Please notice that subscription will filter messages using MessageOrigin property. This property will be assigned to the message in the message send method for each application separately (web, mobile, service).

 public void CreateServiceBusTopicAndSubscriptions(NamespaceManager namespaceManager)
 {
    #region Configure and create Service Bus Topic
    var serviceBusTestTopic = new TopicDescription(TopicName);
    serviceBusTestTopic.MaxSizeInMegabytes = 5120;
    serviceBusTestTopic.DefaultMessageTimeToLive = new TimeSpan(0, 1, 0);

    if (!namespaceManager.TopicExists(TopicName))
    {
        namespaceManager.CreateTopic(serviceBusTestTopic);
    }
    #endregion

    #region Create filters and subsctiptions
    //create filters
    var messagesFilter_Web = new SqlFilter("MessageOrigin = 'Web'");
    var messagesFilter_Mobile = new SqlFilter("MessageOrigin = 'Mobile'");
    var messagesFilter_Service = new SqlFilter("MessageOrigin = 'Service'");

    if (!namespaceManager.SubscriptionExists(TopicName, "WebMessages"))
    {
        namespaceManager.CreateSubscription(TopicName, "WebMessages", messagesFilter_Web);
    }

    if (!namespaceManager.SubscriptionExists(TopicName, "MobileMessages"))
    {
        namespaceManager.CreateSubscription(TopicName, "MobileMessages", messagesFilter_Mobile);
    }

    if (!namespaceManager.SubscriptionExists(TopicName, "WCfServiceMessages"))
    {
        namespaceManager.CreateSubscription(TopicName, "WCfServiceMessages", messagesFilter_Service);
    }
    #endregion
}

We also need to create subscription clients in “OnStart” method giving each subscriber a unique name.

 public override bool OnStart()
 {
    // Set the maximum number of concurrent connections 
    ServicePointManager.DefaultConnectionLimit = 12;

    // Create the queue if it does not exist already
    //string connectionString = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
    var connectionString = getLocalServiceBusConnectionString();
    var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);

    //create topic and subscriptions
    CreateServiceBusTopicAndSubscriptions(namespaceManager);

    // Initialize subscription for web, mobile and service
    SubscriptionClients.Add(SubscriptionClient.CreateFromConnectionString(connectionString, TopicName, "WebMessages"));
    SubscriptionClients.Add(SubscriptionClient.CreateFromConnectionString(connectionString, TopicName, "MobileMessages"));
    SubscriptionClients.Add(SubscriptionClient.CreateFromConnectionString(connectionString, TopicName, "WCfServiceMessages"));

    IsStopped = false;
    return base.OnStart();
}

Inside the run method we will use Task Parallel foreach method to create separate task for each subscriber listening for incoming messages.
This is only to simulate multiple subscribers in one place. Normally each worker role will connect to the topic listening for the messages appropriate for it’s type (separate for web, mobile and service).

public override void Run()
{
 Parallel.ForEach(SubscriptionClients, currentSubscrtiption =>
 {
    while (!IsStopped)
    {
        #region Receive messages
        try
        {
            // Receive the message
            var receivedMessage = currentSubscrtiption.Receive();
         
            if (receivedMessage != null)
            {
                var messageFrom = receivedMessage.Properties["MessageOrigin"].ToString();

                switch (messageFrom)
                {
                    case "Web":
                        //send it to web processing logic

                        break;
                    case "Mobile":
                        //send it to mobile processing logic

                        break;
                    case "Service":
                        //send it to service processing logic

                        break;
                    default:
                        break;
                }

                // Process the message
                Trace.WriteLine(Environment.NewLine + "--------------------------" + Environment.NewLine);
                Trace.WriteLine(string.Format("{0} message content: {1}", messageFrom, receivedMessage.GetBody<string>()));

                receivedMessage.Complete();
            }
        }
        catch (MessagingException e)
        {
            if (!e.IsTransient)
            {
                Trace.WriteLine(e.Message);
                throw;
            }

            Thread.Sleep(10000);
        }
        catch (OperationCanceledException e)
        {
            if (!IsStopped)
            {
                Trace.WriteLine(e.Message);
                throw;
            }
        }
        #endregion
    }
});
}

Finally we can simulate sending messages from the MVC application. We will use 3 different buttons to create and send messages.

 [HttpPost]
 public ActionResult SendWebMessage()
 {
    SendMessage("Web");

    return RedirectToAction("Index", "Home");
 }

 [HttpPost]
 public ActionResult SendMobileMessage()
 {
    SendMessage("Mobile");

    return RedirectToAction("Index", "Home");
 }

 [HttpPost]
 public ActionResult SendServiceMessage()
 {
    SendMessage("Service");

    return RedirectToAction("Index", "Home");
 }

See the image below:

ServiceBusTopic-subscriptions

Please note that when sending messages we have to assign value to message.Properties[“MessageOrigin”]. This will be used by the Service Bus Topic to route messages to appropriate subscriptions.

 void SendMessage(string type)
 {
    var connectionString = getLocalServiceBusConnectionString();

    var Client = TopicClient.CreateFromConnectionString(connectionString, "ServiceBusTestTopic");

    var message = new BrokeredMessage("test message");
    message.Properties["MessageOrigin"] = type;

    Client.Send(message);
 }

As usual, I have attached working project files for your tests 🙂

AzureServiceBus

Artykuł Using Windows Azure Service Bus Topics in distributed systems pochodzi z serwisu Proxmedia.

]]>
Creating custom WCF message router – load balancer https://pxm-software.com/creating-custom-wcf-message-router-load-balancer/ Sun, 15 Nov 2015 18:10:30 +0000 https://proxmedia.pl:99/en/?p=4009 The very common requirement is to route WCF messages from the publicly exposed front-end service (perimeter network) to other services sitting within the local network. This is the good security model that lets us implement routing or load balancer if needed. The front-end service will also act as a firewall in this scenario. The routing […]

Artykuł Creating custom WCF message router – load balancer pochodzi z serwisu Proxmedia.

]]>
The very common requirement is to route WCF messages from the publicly exposed front-end service (perimeter network) to other services sitting within the local network. This is the good security model that lets us implement routing or load balancer if needed. The front-end service will also act as a firewall in this scenario. The routing may be performed based on the requested service method, content or custom algorithm.

The image below shows typical hight level service infrastructure within the organization.

wcf_router

Let’s start with defining our service that the client will use to send requests. The “Calculate” method will be used to perform time consuming operation that will require more CPU usage.

  [ServiceContract]
    public interface IMessageService
    {
        [OperationContract]
        string SendMessage(string value);

        [OperationContract]
        int Calculate(string value); 
    }

  public class MessageService : IMessageService
  {
        public string SendMessage(string value)
        {
            return string.Format("You have sent: {0}", value);
        }

        public int Calculate(string value)
        {
            //do calculation
            return 999;
        }
    }

Next, we need to define IRouter interface. In our example we will use two methods: RouteMessage, that will process and route the messages and AddAvailableEndPoints, that will be used to assign available endpoints for the requests to be routed to. Please note that our router will not be using service contracts which is very useful as we don’t want to recompile router service each time our message service interface changes. You may also implement function to assign routing rules, in our example we will hard-code the rules for better clarity.

  [ServiceContract]
    public interface IRouter
    {
        [OperationContract(Action = "*", ReplyAction = "*")]
        Message RouteMessage(Message message);

        void AddAvailableEndPoints(List<EndpointAddress> addressList);        
    }

Let’s create our router class now. Please note that we are using static constructor as we will only use one instance of the service (creating and destroying channel factory is very costly operation).

 static IChannelFactory<IRequestChannel> factory;
 List<EndpointAddress> addressList;
 int routeCount;

  //create only one instance
  static Router()
  {
    try
    {
        var binding = new BasicHttpBinding();
        factory = binding.BuildChannelFactory<IRequestChannel>(binding);

        factory.Open();
    }
    catch (Exception e)
    {
        Console.WriteLine("Exception: {0}", e.Message);
    }
  }

Now we need to implement the actual routing algorithm. In our case, when message arrives we will check the action method that proxy object will use to execute on the target service. We have hard-coded the method “Calculate” to be routed to service2, the other request will be routed equally among available services. You can also use XmlDocument class to parse message content if needed.
Of course in the production environment you may want to pass in routing rules as a object and examine that when processing arrived message prior routing it to appropriate service.

 public Message RouteMessage(Message message)
 {
    IRequestChannel channel = null;
    Console.WriteLine("Action {0}", message.Headers.Action);
    try
    {
        //Route based on custom conditions
        if (message.Headers.Action.ToLower().EndsWith("calculate")) //or use custom routing table stored in other location
        {
            //use second endpoint as it has more resources for time consuming operations
            channel = factory.CreateChannel(this.addressList.Skip(1).First());
            Console.WriteLine("Routed to: {0}\n", this.addressList.Skip(1).First().Uri);
        }
        else
        {
            //or
            #region Route other requests equally
            //we assume only 2 endpoints for this example 
            if (routeCount % 2 == 0)
            {
                channel = factory.CreateChannel(this.addressList.First());
                Console.WriteLine("Routed to: {0}\n", this.addressList.First().Uri);
            }
            else
            {
                channel = factory.CreateChannel(this.addressList.Skip(1).First());
                Console.WriteLine("Routed to: {0}\n", this.addressList.Skip(1).First().Uri);
            }
            //reset route counter
            if (routeCount > 10000) { routeCount = 0; } else { routeCount++; }
            #endregion           
        }

        //remove context as the message will be redirected
        message.Properties.Remove("ContextMessageProperty");

        channel.Open();

        var reply = channel.Request(message);

        channel.Close();

        return reply;
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
        return null;
    }
}

At this time, we can create client application that will call our front-end service(router) multiple times for our test.

 static void Main(string[] args)
 {
    Console.Write("Press enter to send multiple messages");
    Console.ReadLine();

    var baseFrontOfficeAddress = new Uri("https://localhost:81/FrontOffice");

    try
    {
        var binding = new BasicHttpBinding();
        var endpoint = new EndpointAddress(baseFrontOfficeAddress);

        var factory = new ChannelFactory<IMessageService>(binding, endpoint);
        var channel = factory.CreateChannel();

        //simulate multiple requests
        for (var i = 0; i < 10; i++)
        {
            var reply = channel.SendMessage("test message");
            Console.WriteLine(reply);

            var replyCalulated = channel.Calculate("test message");
            Console.WriteLine("Calculated value: " + replyCalulated);
        }

        Console.ReadLine();
        factory.Close();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        Console.ReadLine();
    }
}

In order to receive client requests we need to start our services. In our example we will host router and available services within the same application. Normally we would deploy router service within DMZ zone and target services on the separate computers withing our local network. For security reasons, only router service would be exposed to public network.

 static void Main(string[] args)
 {
    //execute this first using cmd (win7)
    //netsh http add urlacl url=https://+:81/FrontOffice user=Domain(or PC name)\UserName
    //netsh http add urlacl url=https://+:81/service1 user=Domain(or PC name)\UserName
    //netsh http add urlacl url=https://+:81/service2 user=Domain(or PC name)\UserName

    //front office endpoint - all clients will call this address before requests will be routed
    var baseFrontOfficeAddress = new Uri("https://localhost:81/FrontOffice");

    #region Target service endpoints that requests can be routed to (can be more than 2)
    var baseEndPointAddress1 = new Uri("https://localhost:81/service1");
    var baseEndPointAddress2 = new Uri("https://localhost:81/service2");

    var endPoint1 = new EndpointAddress(baseEndPointAddress1);
    var endPoint2 = new EndpointAddress(baseEndPointAddress2); 
    #endregion

    #region These services should normally be deployed to different servers within the organization
    //start service 1
    var hostService1 = new ServiceHost(typeof(MessageService1), baseEndPointAddress1);
    hostService1.AddServiceEndpoint(typeof(IMessageService), new BasicHttpBinding(), "");
    hostService1.Open();
    Console.WriteLine("MessageService1 service running");

    //start service 2
    var hostService2 = new ServiceHost(typeof(MessageService2), baseEndPointAddress2);
    hostService2.AddServiceEndpoint(typeof(IMessageService), new BasicHttpBinding(), "");
    hostService2.Open();
    Console.WriteLine("MessageService2 service running");        
    #endregion

    #region Start router service
    var router = new Router();

    //add available service enpoints
    router.AddAvailableEndPoints(new List<EndpointAddress>() { endPoint1, endPoint2 });

    var routerHost = new ServiceHost(router);
    routerHost.AddServiceEndpoint(typeof(IRouter), new BasicHttpBinding(), baseFrontOfficeAddress);
    routerHost.Open();

    Console.WriteLine("Router service running");           
    #endregion           
    
    Console.WriteLine("---Run client to send messages---");  
    Console.ReadLine(); 
}

The results of our test is shown below. In this example we chose to route all requests for “Caluculate” method to “service2” (as it located on faster machine within the network), the other requests are routed equally to service1 or service2.

routed_messages

Above way of routing messages is very flexible as it is implemented on the very low level. The other way of routing messages is to use RoutingService class. In this approach you would define the routing table, endpoints and filters in your configuration file. Based on these settings you would add service behavior that will use RoutingService class to route messages.

I have attached project files below for your tests. Please execute below commands before testing it:

netsh http add urlacl url=https://+:81/FrontOffice user=Domain(or PC name)\UserName”
netsh http add urlacl url=https://+:81/service1 user=Domain(or PC name)\UserName
netsh http add urlacl url=https://+:81/service2 user=Domain(or PC name)\UserName

WCF_Router

Artykuł Creating custom WCF message router – load balancer pochodzi z serwisu Proxmedia.

]]>
Using presentation model components and entities in ntier architecture https://pxm-software.com/using-presentation-model-components-and-entities-in-ntier-architecture/ Fri, 30 Oct 2015 13:48:43 +0000 https://proxmedia.pl:99/en/?p=3978 When designing applications that will run in the n-tier environment there are some additional factors to be considered. First of all it is very likely that your business entities will be located on separate machine. In this scenario there is a need to create objects in your UI layer that will have functionality of the […]

Artykuł Using presentation model components and entities in ntier architecture pochodzi z serwisu Proxmedia.

]]>
When designing applications that will run in the n-tier environment there are some additional factors to be considered. First of all it is very likely that your business entities will be located on separate machine. In this scenario there is a need to create objects in your UI layer that will have functionality of the business objects sitting on separate tier. Those objects should also include businesses validation logic and be able to easily apply bindings to UI components.

When transferring business entity data between the tiers, there is a need to create “data transformation objects” that transport object information across the network (if not invoked directly). DTOs also allow to separate layers and expose only those data that we will use (encapsulation). It is especially useful when using restful services.

Diagram below shows the typical n-tier architecture using presentation components and entities.

pres_model_components

Diagram 1. Presentation model components and entities in multi tier application (please refer to “Microsoft Application Architecture Guide, 2nd Edition” book for more details).

Please note that using DTOs may incur some performance lost as the objects need to be mapped and transformed between the layes/tiers. Solution for that could be executing batch commands at once sending final results as combined object to avoid round trips within the network.

If your tiers are located within your local network it is advisable to use TCP protocol(more efficient) otherwise use HTTP/HTTPS when transferring data across the public network.

Artykuł Using presentation model components and entities in ntier architecture pochodzi z serwisu Proxmedia.

]]>
TOGAF vs COBIT, PRINCE2 and ITIL – Webinar https://pxm-software.com/togaf-vs-cobit-prince2-and-itil-webinar/ Fri, 02 Oct 2015 21:10:09 +0000 https://proxmedia.pl:99/en/?p=4212 TOGAF is currently the most popular open architecture framework that is widely implemented in medium and big organizations. It’s ADM lets us operate within generic, proven framework when defining the Enterprise Architecture. If you are an Architect or PM, it is very useful to know how TOGAF relates to other frameworks like COBIT, ITIL and […]

Artykuł TOGAF vs COBIT, PRINCE2 and ITIL – Webinar pochodzi z serwisu Proxmedia.

]]>
TOGAF is currently the most popular open architecture framework that is widely implemented in medium and big organizations. It’s ADM lets us operate within generic, proven framework when defining the Enterprise Architecture.

If you are an Architect or PM, it is very useful to know how TOGAF relates to other frameworks like COBIT, ITIL and PRINCE2.

Digram below shows how those frameworks overlap with each other on the operation, governance and change management level.
togaf_process_change_frameworks
We can clearly see that TOGAF overlaps with COBIT in architecture governance, with ITIL in service/ operation area and with PRINCE2 in change management.

Further interaction is shown on the next diagram:

Togaf_cobit_itil_prince2

Process chain for the above diagrams depicts following image:

process_change_detials

ITIL itself, can be described as follows:

service_level_knowhow_itil

Finally, the last diagram shows how PRINCE2 relates to Architecture within its operational level:

architecture_in_prince2

For more information, please check following video:


Artykuł TOGAF vs COBIT, PRINCE2 and ITIL – Webinar pochodzi z serwisu Proxmedia.

]]>
Custom RetryPolicy class for Windows Azure transient error handling https://pxm-software.com/custom-retrypolicy-class-for-windows-azure-transient-error-handling/ Tue, 02 Jun 2015 19:21:55 +0000 https://proxmedia.pl:99/en/?p=4071 According to definition, the Cloud it’s “A set of interconnected servers located in one or more data centres”. As per definition this kind of environment is naturally prone to network latency and other related environmental issues. This is especially true if we are communicating with on premises applications to synchronize and load the data over […]

Artykuł Custom RetryPolicy class for Windows Azure transient error handling pochodzi z serwisu Proxmedia.

]]>
According to definition, the Cloud it’s “A set of interconnected servers located in one or more data centres”. As per definition this kind of environment is naturally prone to network latency and other related environmental issues. This is especially true if we are communicating with on premises applications to synchronize and load the data over public network.

In order to ensure that our systems are reliable and functioning correctly within such a environment, we should use RetryPolicy to retry error prone operation when an transient error occurs.

In this article I will show you how to use default RetryPolicy with configuration stored in web.config file. You will also learn how to create custom retry policy class to be used throughout your application for the specific error types you define.

Using retry policy objects simply allows us to retry an operation multiple times at the intervals we configure. Image below shows debugging information when retrying operations that cause the errors:

custom_retry_policy

In our example we will user Microsoft Enterprise Library 5.0 (updated version). To create instances we will use RetryPolicyFactory that can create retry policy objects of following types: AzureCachingRetryPolicy, AzureServiceBusRetryPolicy, AzureStorageRetryPolicy, SqlCommandRetryPolicy, SqlConnectionRetryPolicy. Each type handles specific error types.

The configuration also includes ErrorDetectionStrategy object that is being configured in web.config file:

   <configSections>
    <section name="RetryPolicyConfiguration" type="Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.Configuration.RetryPolicyConfigurationSettings, Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling" requirePermission="true"/>
    <section name="typeRegistrationProvidersConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.TypeRegistrationProvidersConfigurationSection, Microsoft.Practices.EnterpriseLibrary.Common"/>
  </configSections>
  <RetryPolicyConfiguration defaultRetryStrategy="Fixed Interval Retry Strategy" defaultSqlConnectionRetryStrategy="Incremental Retry Strategy">
    <incremental name="Incremental Retry Strategy" retryIncrement="00:00:01" initialInterval="00:00:01" maxRetryCount="10"/>
    <fixedInterval name="Fixed Interval Retry Strategy" retryInterval="00:00:01" maxRetryCount="10"/>
    <exponentialBackoff name="Backoff Retry Strategy" minBackoff="00:00:01" maxBackoff="00:00:30" deltaBackoff="00:00:10" maxRetryCount="10" firstFastRetry="false"/>
  </RetryPolicyConfiguration>
  <typeRegistrationProvidersConfiguration>
    <clear/>
    <add name="Caching" sectionName="cachingConfiguration"/>
    <add name="Cryptography" sectionName="securityCryptographyConfiguration"/>
    <add name="Exception Handling" sectionName="exceptionHandling"/>
    <add name="Instrumentation" sectionName="instrumentationConfiguration"/>
    <add name="Logging" sectionName="loggingConfiguration"/>
    <add name="Policy Injection" sectionName="policyInjection"/>
    <add name="Security" sectionName="securityConfiguration"/>
    <add name="Data Access" providerType="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSyntheticConfigSettings, Microsoft.Practices.EnterpriseLibrary.Data"/>
    <add name="Validation" providerType="Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.ValidationTypeRegistrationProvider, Microsoft.Practices.EnterpriseLibrary.Validation"/>
    <add sectionName="RetryPolicyConfiguration" name="RetryPolicyConfiguration"/>
  </typeRegistrationProvidersConfiguration>

Let’s create helper class to handle creation of retry policy objects. The first method retrieves the default policy with the configuration stored in web.config file.
We will also attach an Retrying event to log the retry operations.

 public static RetryPolicy GetDefaultPolicy(string name)
 {
    RetryPolicy retryPolicy;

    try
    {
        retryPolicy = RetryPolicyFactory.GetRetryPolicy<StorageTransientErrorDetectionStrategy>(name);
        retryPolicy.Retrying += retryPolicy_Retrying;
    }
    catch (NullReferenceException)
    {
        throw new Exception("Unable to read transient fault handling behaviour from web.config file - section for TransientFaultHandling could be missing.");
    }

    return retryPolicy;
}

 static void retryPolicy_Retrying(object sender, RetryingEventArgs e)
 {
    var message = string.Format(
        "Retry - Count: {0}, Delay: {1}, Exception: {2}",
         e.CurrentRetryCount,
         e.Delay,
         e.LastException.Message);

    Trace.TraceEvent(TraceEventType.Information, 0, message);// write to log
  }

Our next helper function will create custom retry policy. In the constructor we will pass in error types we want to be included in retry operations. Ideally this could be stored in config file.

 public static RetryPolicy GetCustomRetryPolicy()
 {
    var retryPolicy = new RetryPolicy(
        new CustomTransientErrorDetectionStrategy(
            new List<Type>() {
                typeof(DivideByZeroException),
                typeof(IndexOutOfRangeException),
            }),
        new CustomRetryStrategy());

    retryPolicy.Retrying += retryPolicy_Retrying;

    return retryPolicy;
}

Now let’s create custom retry policy class. The most important part of it is ShouldRetry method which simply returns the delegate allowing to evaluate whether to continue retrying operation or not. You can also apply your own logic in this place based on your requirements.

 public class CustomRetryStrategy : RetryStrategy
 {
  private readonly int retryCount = 3;
  private readonly TimeSpan retryInterval = TimeSpan.FromMilliseconds(1000);

  public CustomRetryStrategy()
    : base("customRetryStrategy", true)
  {
    //default values
  }

  public CustomRetryStrategy(int retryCount, TimeSpan retryInterval)
    : base("customRetryStrategy", true)
  {
    this.retryCount = retryCount;
    this.retryInterval = retryInterval;
  }

  public override ShouldRetry GetShouldRetry()
  {
    if (this.retryCount == 0)
    {
        return delegate(int currentRetryCount, Exception lastException, out TimeSpan interval)
        {
            interval = TimeSpan.Zero;

            return false;
        };
    }

    return delegate(int currentRetryCount, Exception lastException, out TimeSpan interval)
    {
        if (currentRetryCount < this.retryCount)
        {
            var random = new Random();
            //set random interval within the threshold
            interval = TimeSpan.FromMilliseconds(random.Next((int)(this.retryInterval.TotalMilliseconds * 0.8), (int)(this.retryInterval.TotalMilliseconds * 1.2)));


			//use your logic here
			//....

            return true;
        }

        interval = TimeSpan.Zero;

        return false;
     };
   }
 }

When creating custom retry policy we also need to create CustomTransientErrorDetectionStrategy class inheriting from ITransientErrorDetectionStrategy interface. In this class we simply evaluate the error type that is currently occurring and need to decide whether retry policy object will attempt to handle it. In order to do that we will pass in our error types to the class constructor. Next, we will check the error type within the IsTransient method to return true if error must cause the retry operation or false otherwise.

 public class CustomTransientErrorDetectionStrategy : ITransientErrorDetectionStrategy
 {
    List<Type> exceptionTypesToRetry;

    public CustomTransientErrorDetectionStrategy(List<Type> exceptionType)
    {
        exceptionTypesToRetry = exceptionType;
    }

    public bool IsTransient(Exception ex)
    {
        if (exceptionTypesToRetry.Contains(ex.GetType()))
        {
            return true;
        }
        return false;
    }
 }

Finally in our controller we can test it as follows:

 RetryPolicyHelper.GetDefaultPolicy("Incremental Retry Strategy").ExecuteAction(() =>
 {
     //index out of range exception - it won't be retried
     //as it defaults to sql connection errors
     var array = new int[] { 1, 2, 3 };
     var a = array[5];
 });

 RetryPolicyHelper.GetCustomRetryPolicy().ExecuteAction(() =>
 {
     //divide by zero exception - will be retried
     //as we defined exception types to:
     //DivideByZeroException, IndexOutOfRangeException
     var a = 0;
     var b = 10 / a;
 });

I have included project files below for your tests 🙂

Azure_RetryPolicy

Artykuł Custom RetryPolicy class for Windows Azure transient error handling pochodzi z serwisu Proxmedia.

]]>
Using Windows Azure Service Management REST API in automated tasks https://pxm-software.com/using-windows-azure-service-management-rest-api-in-automated-tasks/ Sat, 02 May 2015 18:29:51 +0000 https://proxmedia.pl:99/en/?p=4026 Windows Azure platform gives us a lot of new possibilities starting from the ability to auto scale instances of the deployed application to performing an on demand automated changes. When handling multiple applications deployed to the cloud there is a need to automate daily processes in order to save the development time. In this article […]

Artykuł Using Windows Azure Service Management REST API in automated tasks pochodzi z serwisu Proxmedia.

]]>
Windows Azure platform gives us a lot of new possibilities starting from the ability to auto scale instances of the deployed application to performing an on demand automated changes. When handling multiple applications deployed to the cloud there is a need to automate daily processes in order to save the development time.

In this article I will show you how to automate process of creating new cloud service using Windows Azure REST API. In our example we will create custom Api helper to instantiate our request object that will be then used to invoke the Azure RestFul API procedure.

In order to access WA Api the Azure subscription password and user name is not required, all you need is the subscription ID and the management certificate. This creates the possibility to give some administrative tasks to other people in the company not necessarily having access to the subscription account.

First thing to do is to create and upload management certificate into WA Management Portal. One of the ways to create certificate is to do it from within Visual Studio. In order to do that, we need to right click on our cloud project and open remote desktop configuration wizard. Next we need to select “create new” from the menu. After our certificate is created we can view it and export it to the .cer file. At this stage we also need to read the certificate’s thumb-print that will be used to find it in the local store.

The image below shows the process of configuring new RDP connection and creating new certificate

cert-config-azure

After we have created and exported certificate to the file, we can upload it to the WA Management Portal as shown below

azure-management-certificate

Please note that certificate thumb-print is the same as our local one.

We also need to make sure that our Api helper will find the certificate in our local store. In order to check it’s location, please open Windows Management Console (mmc) and add snap-in for the current user and local computer certificates. Next you need to copy it as depicted below

certificates

At this stage we can start implementing our Api request helper. Let’s create custom PayLoadSettings class first that we will use to hold the basic request settings.

 public class PayLoadSettings
 {
    public string CloudServiceUrlFormat { get; set; }
    public string SubscriptionId { get; set; }
    public string Thumbprint { get; set; }
    public string ServiceName { get; set; }
    public string Label { get; set; }
    public string Description { get; set; }
    public string Location { get; set; }
    public string AffinityGroup { get; set; }
    public string VersionId { get; set; }
 }

Next let’s create function that retrieves our newly created (and uploaded to the WAM portal) certificate from the local machine store

/// <summary>
/// Get certificate from the local machine by thumbprint
/// </summary>
/// <returns></returns>
private X509Certificate2 GetX509Certificate()
{
    X509Certificate2 x509Certificate = null;
    var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
    try
    {
        certStore.Open(OpenFlags.ReadOnly);

        var x509CertificateCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, this.PayLoadSettings.Thumbprint, false);

        x509Certificate = x509CertificateCollection[0];
    }
    finally
    {
        certStore.Close();
    }

    return x509Certificate;
 }

Next, we want to create function that inserts our cert into new request object to be sent to execute remote action. We also need to set the requested Api version (not required though).

/// <summary>
/// Create http request object with the certificate added
/// </summary>
/// <param name="uri"></param>
/// <param name="httpWebRequestMethod"></param>
/// <returns></returns>
private HttpWebRequest CreateHttpWebRequest(Uri uri, string httpWebRequestMethod)
{
    var x509Certificate = GetX509Certificate();
    var httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(uri);

    httpWebRequest.Method = httpWebRequestMethod;
    httpWebRequest.Headers.Add("x-ms-version", this.PayLoadSettings.VersionId);

    httpWebRequest.ClientCertificates.Add(x509Certificate);
    httpWebRequest.ContentType = "application/xml";

    return httpWebRequest;
}

Next step is to create payload document object containing the operation parameters that we want to execute. The names are self-explanatory.

/// <summary>
/// Create payload document
/// </summary>
/// <returns></returns>
private XDocument CreatePayload()
{
    var base64LabelName = Convert.ToBase64String(Encoding.UTF8.GetBytes(this.PayLoadSettings.Label));

    var xServiceName = new XElement(azureNamespace + "ServiceName", this.PayLoadSettings.ServiceName);
    var xLabel = new XElement(azureNamespace + "Label", base64LabelName);
    var xDescription = new XElement(azureNamespace + "Description", this.PayLoadSettings.Description);
    var xLocation = new XElement(azureNamespace + "Location", this.PayLoadSettings.Location);
    var xAffinityGroup = new XElement(azureNamespace + "AffinityGroup", this.PayLoadSettings.AffinityGroup);
    var createHostedService = new XElement(azureNamespace + "CreateHostedService");

    createHostedService.Add(xServiceName);
    createHostedService.Add(xLabel);
    createHostedService.Add(xDescription);
    createHostedService.Add(xLocation);
    createHostedService.Add(xAffinityGroup);

    var payload = new XDocument();
    payload.Add(createHostedService);

    payload.Declaration = new XDeclaration("1.0", "UTF-8", "no");

    return payload;
}

Having payload document created, we can send our request and retrieve request id if operation is successful.

/// <summary>
/// Invoke Api operation by sending payload object
/// </summary>
/// <param name="uri"></param>
/// <param name="payload"></param>
/// <returns></returns>
private string InvokeAPICreateRequest(string uri, XDocument payload)
{
    string requestId;
    var operationUri = new Uri(uri);

    var httpWebRequest = CreateHttpWebRequest(operationUri, "POST");

    using (var requestStream = httpWebRequest.GetRequestStream())
    {
        using (var streamWriter = new StreamWriter(requestStream, UTF8Encoding.UTF8))
        {
            payload.Save(streamWriter, SaveOptions.DisableFormatting);
        }
    }

    using (var response = (HttpWebResponse)httpWebRequest.GetResponse())
    {
        requestId = response.Headers["x-ms-request-id"];
    }

    return requestId;
}

The final function just puts it all together as follows

/// <summary>
/// Execute create cloud service request
/// </summary>
/// <returns></returns>
public string CreateCloudService()
{
    var cloudServiceUrl = string.Format(this.PayLoadSettings.CloudServiceUrlFormat, this.PayLoadSettings.SubscriptionId);
    
    var payload = CreatePayload();

    var requestId = InvokeAPICreateRequest(cloudServiceUrl, payload);

    return requestId;
}

If we will invoke the code from the console, the code should look as below

 static void Main(string[] args)
 {
    //load this from your configuration file
    var payLoadSettings = new PayLoadSettings()
    {
        CloudServiceUrlFormat = "https://management.core.windows.net/{0}/services/hostedservices",
        SubscriptionId = "92533879-88c9-41fe-b24e-5251bcf49a8f",//fake subscription id - please provide yours
        Thumbprint = "3a f6 67 24 d8 d8 b3 71 b0 c4 d3 00 c2 04 0d 62 e5 30 76 1c", //fake cert thumbprint - please provide yours
        ServiceName = "newService1234567",//name your new service
        Label = "newService1234567", //give it a tracking label
        Description = "My new cloud service", //service description
        Location = "North Europe",//select centre
        AffinityGroup = "", //not created yet
        VersionId = "2011-10-01"//api version
    };

    var api = new RestAPIHelper(payLoadSettings);

    try
    {
        var requestId = api.CreateCloudService();

        Console.WriteLine("Cloud service has been created successfully :)" + Environment.NewLine + "Request id: " + requestId);
        Console.ReadLine();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        Console.ReadLine();
    }
}

Let’s run the console application now

cloud-service-created

After executing above we can check in WA Management Portal if the cloud service is created. This should look like image below

newcloudservice

I have attached project files for your tests. Please note that you need to set your own configuration settings for it to be working. You can also use above example to create your own automated tasks for Windows Azure – simply implement other operations in similar way. You can then use for example TeamCity to run it automatically when needed. This gives you a lot of possibilities and simply saves your precious development time.

AzureRestAPI

Artykuł Using Windows Azure Service Management REST API in automated tasks pochodzi z serwisu Proxmedia.

]]>
Claims based authentication on Windows Azure https://pxm-software.com/claims-based-authentication-on-windows-azure/ Wed, 29 Apr 2015 18:17:56 +0000 https://proxmedia.pl:99/en/?p=4017 Claims based authentication can greatly improve user’s experience by allowing them to login to our site using external trusted providers such as Google, Yahoo etc. In this article I will show you how to integrate claims based authentication with existing membership provider. This is common scenario if you don’t have any on premises applications using […]

Artykuł Claims based authentication on Windows Azure pochodzi z serwisu Proxmedia.

]]>
Claims based authentication can greatly improve user’s experience by allowing them to login to our site using external trusted providers such as Google, Yahoo etc. In this article I will show you how to integrate claims based authentication with existing membership provider. This is common scenario if you don’t have any on premises applications using Active Directory needing to connect to the cloud. If this is the case we would have to use WIF (Windows Identity Foundation) authentication modules and Active Directory Federation Services installed on premises.

In our simple example we will use DotNetOpenAuth to perform claims based authentication along side default membership provider. In order to successfully authenticate the user we will have to correlate user data stored in membership table with the UserID received from external claims callback, in our case we will receive email address as a user-name from Google.

Following diagram presents high level overview of our solution:

claims_authentication

How it works:
User can login to our site as normal using standard login button. If he wishes to login using eg. Google account he will have to click the button below saying ‘Log in with Google’.
After clicking that button, user is redirected to Google’s login page. If the Google login is successful then user is redirected back to our site. Our generic handler validates the claims stored in the response context. If the validation is successful, we are getting email address that we will use to login the user. Before doing that we need to first find the user in our database by email address and get his data.

google_login

Let’s start implementation.

In the Global.asax file we need to attach UserAuthenticated event. We will use it to get callback response from Google containing claimed userID.

 public void RegisterEvents()
 {
    //attach login event from the generic handler
    GoogleLoginHandler.UserAuthenticated += new EventHandler<EventArgs<string>>(GoogleLoginHandler_UserAuthenticated);
 }

 void GoogleLoginHandler_UserAuthenticated(object sender, EventArgs<string> e)
 {
    var accountController = new Controllers.AccountController();
    accountController.LogOnUsingOpenId(e.Data); //pass in email address of the user to be logged in
 }

 protected void Application_Start()
 {
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    RegisterEvents();
 }

Next, lets add following handler GoogleLoginHandler.ashx to our project. In that handler we will redirect to Google login page and read the response after login is successful. See in-line comments:

  public void ProcessRequest(HttpContext context)
 {
	using (var openid = new OpenIdRelyingParty())
	{
		openid.Behaviors.Add(new AXFetchAsSregTransform());

		var response = openid.GetResponse();
		if (response == null)
		{
			// Check if already logged in
			var request = openid.CreateRequest(GoogleOPIdentifier);
			request.AddExtension(new UIRequest { Mode = UIModeDetectSession });
			request.Mode = AuthenticationRequestMode.Immediate;
			request.AddExtension(new ClaimsRequest { Email = DemandLevel.Require });
			request.RedirectToProvider();
		}
		else
		{
			if (response.Status == AuthenticationStatus.Authenticated)
			{
				var claims = response.GetExtension<ClaimsResponse>();
				var userEmail = claims.Email;

				if (UserAuthenticated != null)
				{
					//Log user in
					UserAuthenticated(this, new EventArgs<string>(userEmail));
				}

				context.Response.Redirect(context.Request["ReturnUrl"]);
			}
			else if (response.Status == AuthenticationStatus.SetupRequired)
			{
				var request = openid.CreateRequest(GoogleOPIdentifier);
				request.AddExtension(new ClaimsRequest { Email = DemandLevel.Require });
				request.RedirectToProvider();
			}
			else
			{
				context.Response.Redirect(context.Request["ReturnUrl"]);
			}
		}
	}
 }

We will use following function to redirect to login page and back to destination by reading the ReturnUrl param:

 public static void TryToLogin(string defaultRedirection = "/Home/Index")
{
    //extract return url if exists
    var returnUrl = HttpContext.Current.Request.UrlReferrer != null && HttpContext.Current.Request.UrlReferrer.ToString().Contains("ReturnUrl=") ?
        HttpContext.Current.Request.UrlReferrer.ToString().Split(new string[] { "ReturnUrl=" }, StringSplitOptions.None)[1] : defaultRedirection;
    
    if (returnUrl.Trim().Length == 0) { returnUrl = defaultRedirection; } //enforce default if empty

    HttpContext.Current.Response.Redirect("~/GoogleLoginHandler.ashx?ReturnUrl=" + returnUrl);
}

Our generic handler and declarations will look as follows:

 public class GoogleLoginHandler : IHttpHandler
 {
    public static event EventHandler<EventArgs<string>> UserAuthenticated;

    private const string GoogleOPIdentifier = "https://www.google.com/accounts/o8/id";
    private const string UIModeDetectSession = "x-has-session";

We will also extend EventArgs class to accept generic param that we will use in our callback handler.

 namespace System
 {
    public class EventArgs<T> : EventArgs
    {
        public EventArgs()
        {
        }

        public EventArgs(T data)
        {
            this.Data = data;
        }

        public T Data { get; set; }
    }
}

And finally we call following function to authenticate user containing verified email address that matches email address in our membership table.

/// <summary>
/// Private login method for openId
/// </summary>
/// <param name="emailAddress"></param>
/// <returns></returns>
[Authorize]
internal ActionResult LogOnUsingOpenId(string emailAddress)
{
    var userName = Membership.GetUserNameByEmail(emailAddress);
    if (userName != null)
    {
        FormsAuthentication.SetAuthCookie(userName, true);
    }

    return View();
}

I have included project files below so you can see it working and adjust it to your requirements 🙂

Claims Authentication

Artykuł Claims based authentication on Windows Azure pochodzi z serwisu Proxmedia.

]]>