Friday, 24 February 2012

Comparing old and new Asynchronous MSMQ Calls using IAsyncResult and the new System.Threading.Tasks.TaskFactory in .Net 4.0.


In this blog entry I thought I would describe the old way of doing Asynchronous Calls and the new way of doing Asynchronous Calls using System.Threading.Tasks.TaskFactory

Recently I have been doing some asynchronous calls using IAsyncResult and MSMQ.
Before I show the code I need to explain how it was done the old fashion way.

In the olden days of .NET 1.0 to 3.5 sp1 you would start by calling a BeginReceive(TimeSpan, Cursor, Object, AsyncCallback) or BeginPeek(TimeSpan, Cursor, Object, AsyncCallback). But because BeginReceive is asynchronous, you can call it to receive a message from the queue without blocking the current thread of execution.
EndPeek is used to read the message that caused the PeekCompleted event to be raised.
Once an asynchronous operation completes, you can call BeginPeek or BeginReceive again in the event handler to keep receiving notifications. The event handler here is the AsyncCallback(void PeekCompleted(IAsyncResult asyncResult)

In that callback of PeekComplete the EndPeek will return the Message from the MSMQ.

Here is the code for .NET 3.5 sp1 or earlier

msgqueueCurrentCursor = queue.CreateCursor();
 
queue.BeginPeek(new TimeSpan(0, 0, 0, 1, 0), msgqueueCurrentCursor, PeekAction.Current, 
0, new AsyncCallback(PeekCompleted));
while (true)
{
     Thread.Sleep(1000);
}
 
 
// Provides an event handler for the PeekCompleted event.
private void PeekCompleted(IAsyncResult asyncResult)
{
   try
   {
      bool bPeeking = false;
 
      // End the asynchronous peek operation.
      Message msg = queue.EndPeek(asyncResult);
 
      lock (queueMessagesToTransmit)
      {
         queueMessagesToTransmit.Add(msg.LookupId, msg);
      }
      bPeeking = true;
      queue.BeginPeek(new TimeSpan(0, 0, 0, 1, 0), msgqueueCurrentCursor, 
PeekAction.Next, 0, new AsyncCallback(PeekCompleted));
   }
   catch (System.Messaging.MessageQueueException msgqueueException)
   {
      if (msgqueueException.MessageQueueErrorCode == 
System.Messaging.MessageQueueErrorCode.IOTimeout)
      {
         queue.BeginPeek(new TimeSpan(0, 0, 0, 1, 0), msgqueueCurrentCursor, 
PeekAction.Next, 0, new AsyncCallback(PeekCompleted));
      }
      else
      {
         Trace.WriteLine(TraceName + string.Format("Message Queue Exception {0}", 
msgqueueException.ToString()));
         return;
      }
   }
   catch (ThreadAbortException thrdExc)
   {
      System.Diagnostics.Trace.WriteLine(TraceName + thrdExc.ToString());
      return;
   }
}

Now with the new Task.Factory in System.Threading.Tasks there is no need for the callback. This is managed with the function Task.Factory.FromAsync as shown below.

public Task<TResult> FromAsync<TResult>(
        IAsyncResult asyncResult,
        Func<IAsyncResult, TResult> endMethod
)

In our case for a BeginReceive from the message queue we could very easily do this without the callback function

Task<Message> ts = Task.Factory.FromAsync<Message>(queue.BeginReceive(), queue.EndReceive);
ts.Wait();
Message msg = ts.Result;

Not there is no typo above the EndReceive is a function parameter.

Now you might be asking this is a blocking call. And the quick answer is yes sort of. The Task.Wait() is actually acts like a Thread.Sleep(). So if you created a thread to do this you wont need to worry about the thread and the code is rather simple as shown above. And other threads can process while you wait for the transfer a message inside the MSMQ.
As with all threads commonly used I have seen they loop with a Thread.Sleep(). This is now no longer needed. This actually gives maximum throughput without blocking therefore getting the best performance for reading from the MSMQ.

Now I include the code in its entirety. This code would be the thread called function running in the background while you do other processing. You would do a Thread.abort() to terminate it.

Here is the code .NET 4.0 or later

try
{
Task<Message> ts = Task.Factory.FromAsync<Message>(queue.BeginPeek(new TimeSpan(1, 0, 0, 1, 0), msgqueueCurrentCursor, PeekAction.Current, 0, null), queue.EndPeek);
ts.Wait();
Message msg = ts.Result;
Console.WriteLine(msg.Id.ToString());
while (true)
{
Task<Message> tsnext = Task.Factory.FromAsync<Message>(queue.BeginPeek(new TimeSpan(1, 0, 0, 1, 0), msgqueueCurrentCursor, PeekAction.Next, 0, null), queue.EndPeek);
      tsnext.Wait();
      Message msg = tsnext.Result;
      Console.WriteLine(msg.Id.ToString());
}
}
catch (ThreadAbortException thrdExc)
{
   System.Diagnostics.Trace.WriteLine(TraceName + thrdExc.ToString());
   return;
}

Please refer to this forum entry where I was unsure of how to accomplish this.


Here is where the new Task.TaskFactory is documented. http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.aspx

P.S. On a side note I have done this for both sockets, sql and streams. If you need me to blog how to do that then post a comment and I will do my best.

As always happy asynchronous programming

Command Script Using Appcmd.exe to configure AutoStart WCF in IIS


In this blog entry I will talk about how to configure auto starting WCF / HTTP exposed services. I will provide a script below that can be executed to enable auto start for the website.

In IIS, you can configure an application pool and all or some of its applications to automatically start when the IIS service starts. This is available in (IIS) 7.5 which is included in Window 7 or Windows Server 2008 R2.

When you enable the auto-start feature for a service, the service is up and running as soon as the application that it belongs to is started and before the service receives the first WCF message from the client. Therefore, the service processes the first message quickly because it is already initialized. For example, suppose a service needs to connect to a database to read hundreds of rows of data to populate a .NET Framework caching data structure when it is first created. The initialization processing takes a long time before the service is ready to begin the actual operation. If you use auto-
start in this case, the service is initialized before it receives the first call.


Lets look at the script below which will create and autostart an application pool.

Firstly we start with creating a new application pool call MyAutoStartAppPool
 
%windir%\system32\inetsrv\APPCMD.exe add apppool /name: MyAutoStartAppPool
 
We then set the properties autoStart:true and startMode: AlwaysRunning
Also I set the .NET framework to v4.0 and Enable 32 bit processing. These can be skipped if not required.
 
%windir%\system32\inetsrv\APPCMD.exe set apppool MyAutoStartAppPool
 /managedRuntimeVersion:v4.0 /autoStart:true /startMode:AlwaysRunning
%windir%\system32\inetsrv\APPCMD.exe set apppool MyAutoStartAppPool
 /enable32BitAppOnWin64:true" 
 
We then set the identity of the app pool
 
%windir%\system32\inetsrv\appcmd.exe set config /section:applicationPools
 /[name='MyAutoStartAppPool'].processModel.identityType:SpecificUser
 /[name='MyAutoStartAppPool'].processModel.userName:user
 /[name='MyAutoStartAppPool'].processModel.password:password 
 
Finally we then set the website in this case “Default WebSite/” to the application pool created. Then we set the website serviceAutoStartEnabled: true serviceAutoStartMode: all and serviceAutoStartProvider: Service
 
%windir%\system32\inetsrv\appcmd.exe set app /app.name:"Default WebSite/"
 /applicationPool: MyAutoStartAppPool 
 
%windir%\system32\inetsrv\appcmd.exe set app /app.name:"Default WebSite/"
 /serviceAutoStartEnabled:True /serviceAutoStartMode:All /serviceAutoStartProvider:Service

Now any hosted WCF service or website is autostarted. I sometimes put processing code and populate memory caches in global.asax.cs in the Application_Start method.

This autostart feature makes the code startup quicker and stay started.



Tuesday, 13 December 2011

Sharepoint Client Object Model Beginners Guide.


Recently I have been playing around with Sharepoint 2010 Client Object Model. To get started you will need to access and reference the client dll. They are
Microsoft.SharePoint.Client                                       
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.SharePoint.Client.dll
Microsoft.SharePoint.Client.Runtime                    
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.SharePoint.Client.Runtime.dll

Then to access the library
using Microsoft.SharePoint.Client;

When using this library to access Sharepoint you first create a ClientContext. Then you use the client context to load the queries. Once you are done doing this you then call the method ExecuteQuery.
Here is an example.

ClientContext clientContext = new ClientContext("http://intranet.contoso.com");
Web website = clientContext.Web;
WebCollection websiteCollections = clientContext.Web.Webs;
           
clientContext.Load(website);
clientContext.Load(websiteCollections);

clientContext.ExecuteQuery();
Console.WriteLine("Title: {0}", website.Title);

To recursive list through each folder we can do the following:

foreach (Web websubsites in websiteCollections)
{
Console.WriteLine("Web Sub Sites Title: {0} {1}", websubsites.Title, websubsites.ServerRelativeUrl);
FolderCollection websubsitesfolderCollection = websubsites.Folders;
clientContext.Load(websubsitesfolderCollection);
clientContext.ExecuteQuery();

webSubFolder(clientContext, websubsitesfolderCollection);
}

public static void webSubFolder(ClientContext clientContext, FolderCollection websubsitesfolderCollection)
{
foreach (Folder websubsitefolder in websubsitesfolderCollection)
{
Console.WriteLine("Web Sub Sites Folder:{0} Url:{1}", websubsitefolder.Name, websubsitefolder.ServerRelativeUrl);

FolderCollection websubsitesubfolderCollection = websubsitefolder.Folders;
clientContext.Load(websubsitesubfolderCollection);
clientContext.ExecuteQuery();
webSubFolder(clientContext, websubsitesubfolderCollection);
}
}

To upload a file to the Sharepoint Document Library we can use the code outlined below. Initially we will need FileCreationInformation. Then we attach the file by webSubsiteFolder.Files.Add

if (websubsitefolder.Name == "Shared Documents")
{
FileCreationInformation flciNewFile = new FileCreationInformation();

flciNewFile.Content = WriteSomeData().ToArray();
flciNewFile.Url = "UploadFile.txt";
flciNewFile.Overwrite = true;

File uploadFile = websubsitefolder.Files.Add(flciNewFile);

clientContext.Load(uploadFile);
clientContext.ExecuteQuery();

ListItem fileUploadedItem = uploadFile.ListItemAllFields;

fileUploadedItem["Title"] = "Breeze Document Upload";
fileUploadedItem.Update();

clientContext.ExecuteQuery();
}

public static System.IO.MemoryStream WriteSomeData()
{
System.IO.MemoryStream ms = new System.IO.MemoryStream();
System.IO.TextWriter txtw = new System.IO.StreamWriter(ms);

for (int i = 1;  i <= 20; i++)
{
txtw.WriteLine(string.Format("This is line {0}", i));
}
txtw.Flush();

ms.Seek(0, IO.SeekOrigin.Begin);
return ms;
}

Monday, 28 November 2011

WCF Proxy External to Internal and Avoid Serialization Overheads


In the past on numerous projects I had to consider application security as part of my overall software design and implementation. All internal systems that are required for the service are located in Internal Network layer protected by a firewall. The external world would not have direct access to the internal systems except via proxy from an designated external server to internal server.
The diagram below is a typical example of what this entails.



The External servers would only have access to the designated Internal Servers and from there the internal servers would do the processing and communicating to backend systems before responding back via the external systems.
The most efficient way I found to do this is to effect create a proxy External WCF service that would then forward that request to the internal systems without any serialization.
Essentially the method here being demonstrated is GetPrices.
Externally it will be exposed as
Message GetPrices(Message value);
Internally it will be the deserialized form of
GetPricesResponse GetPrices(GetPricesRequest request)

The conversion is done automatically by wcf. There are a few gotchas so please read the implementation especially around the message http headers. This is specific for wcf – rest services.
Let me demonstrate
First lets create an Interface called IGetPrices. It will be a REST WCF Service for this demonstration. It will have a method called GetPrices.
    [ServiceContract]
    public interface IGetPrices
    {
        [OperationContract(Action = "*", ReplyAction = "*")]
        [WebInvoke(Method = "POST", UriTemplate="", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        Message GetPrices(Message value);
    }

Then the implementation will be as follows

        public Message GetPrices(Message msgRequest)
        {
     //THE EXTERNAL WCF SERVICE WILL CREATE NOW ACT AS A CLIENT TO CALL INTERNAL GETPRICES     
            InternalGetPricesClient igpcGetPrices = new InternalGetPricesClient();
            HttpRequestMessageProperty reqProperty = (HttpRequestMessageProperty)msgRequest.Properties[HttpRequestMessageProperty.Name];

            string strHeaderValue = "";
            for (int ihKey = 0; ihKey < reqProperty.Headers.Count; ihKey++)
            {
                strHeaderValue += reqProperty.Headers[ihKey];
            }
            System.Diagnostics.Debug.WriteLine("[GetPrices].External.Headers", strHeaderValue);

            //SOMETIMES EXTRA HEADERS CAN CAUSE AN ISSUE
            int ihFoundKey = 0;
            while (ihFoundKey < reqProperty.Headers.Count)
            {
                if ((reqProperty.Headers.GetKey(ihFoundKey).ToUpper() == "CONTENT-LENGTH") || (reqProperty.Headers.GetKey(ihFoundKey).ToUpper() == "CONTENT-TYPE"))
                {
                    ihFoundKey++;
                }
                else
                {
                    reqProperty.Headers.Remove(reqProperty.Headers.GetKey(ihFoundKey));
                    ihFoundKey = 0;
                }
            }

            //PASS CUSTOMISED HEADER TO INTERNAL CLIENT
            //WebOperationContext.Current.IncomingRequest.Headers.Add("AppFabricID", appFabric.ActivityID);

            msgRequest.Headers.To = igpcGetPrices.Endpoint.Address.Uri;
            msgRequest.Properties.Via = igpcGetPrices.Endpoint.Address.Uri;

            Message rspResponse = igpcGetPrices.GetPrices(msgRequest);

            //CAN CHECK RESPONSE HEADER TO SEE IF THERE IS AN ERROR
            HttpResponseMessageProperty respProperty = (HttpResponseMessageProperty)rspResponse.Properties[HttpResponseMessageProperty.Name];
            //if (respProperty.Headers["ERROR"] != null)
            //{
            //    throw new Exception(respProperty.Headers["ERROR"], HttpStatusCode.InternalServerError);
            //}
            rspResponse.Properties[HttpResponseMessageProperty.Name] = null;

            return rspResponse;
        }

Then the implementation for the external to internal client for InternalGetPricesClient igpcGetPrices = new InternalGetPricesClient(); will be.

    public partial class InternalGetPricesClient :  System.ServiceModel.ClientBase<IGetPrices>, IGetPrices
    {
        public InternalGetPricesClient()
        {
        }
        public InternalGetPricesClient(string endpointConfigurationName) :
            base(endpointConfigurationName)
        {
        }

        public InternalGetPricesClient(string endpointConfigurationName, string remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
        {
        }

        public InternalGetPricesClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
        {
        }

        public InternalGetPricesClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
            base(binding, remoteAddress)
        {
        }

        public Message GetPrices(Message request)
        {
            return base.Channel.GetPrices(request);
        }
    }


ALSO 

The Web.Config needs to be configured accordingly to configure the client accordingly.

<?xml version="1.0" encoding="utf-8"?>
<system.serviceModel>
       <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
       <bindings>
              <basicHttpBinding>
                     <binding name="soapBinding">
                           <security mode="None">
                           </security>
                     </binding>
              </basicHttpBinding>
              <webHttpBinding>
                     <binding name="webBinding">
                     </binding>
              </webHttpBinding>
       </bindings>
       <client>
              <endpoint name="Centrebet.PYOF.External.WCF.Interfaces.ExternalGetPricesClient"
                                  address="http://localhost:24984/GetPrices"
                                  binding="webHttpBinding"
                                  bindingConfiguration="webBinding"
                                  behaviorConfiguration="poxBehavior"
                                  contract="Centrebet.PYOF.External.Interfaces.IGetPrices"/>
       </client>
       <behaviors>
              <endpointBehaviors>
                     <!-- plain old XML -->
                     <behavior name="poxBehavior">
                           <webHttp/>
                     </behavior>
                     <!-- JSON -->
                     <behavior name="jsonBehavior">
                           <enableWebScript/>
                     </behavior>
                     <!-- <behavior name="ProtoBufSerializationBehavior">
                                  <ProtoBufSerialization/>
                                  </behavior> -->
              </endpointBehaviors>
              <serviceBehaviors>
                     <behavior>
                           <serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="200" maxConcurrentInstances="200"/>
                           <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                           <serviceMetadata httpGetEnabled="true"/>
                           <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                           <serviceDebug includeExceptionDetailInFaults="false"/>
                     </behavior>
              </serviceBehaviors>
       </behaviors>
</system.serviceModel>

Now for the Internal Server
It will now deserialize the following way
namespace Internal.WCF.Interfaces
{

    [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode=InstanceContextMode.PerCall)]
    [ServiceErrorBehavior(typeof(GetPricesErrorHandler))]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class GetPricesService : IGetPrices
    {
        public GetPricesResponse GetPrices(GetPricesRequest request)
        {
            GetPricesResponse gprResponse = new GetPricesResponse();
            return gprResponse;
        }    
    }
}

Here is the implementation class.
namespace Internal.Interfaces
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract]
    public interface IGetPrices
    {
        [OperationContract(Action = "*", ReplyAction = "*")]
        [WebInvoke(Method = "POST", UriTemplate = "", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        GetPricesResponse GetPrices(GetPricesRequest request);
    }
}

There you have it how to create a WCF Proxy External to Internal and Avoid Serialization Overheads