Sony Arouje

a programmer's log

Posts Tagged ‘WCF

WCF Duplex Communication with multiple clients

with 8 comments

Recent days I am working on a batch processing system to cater printing of more than 100k documents per day from a queue. To make system scalable I divided the system into two

Producer: who produce the document, it’s time consuming, CPU intensive process.
Consumer: who consumes the document and print/Email/fax it. Fairly simple with different handlers for printing, faxing or emailing and less CPU intensive

Producer and Consumer will communicate through a WCF service using TCPBinding.

One of the functionality of consumer is reporting the status (exception while printing) of the document back to the producer for audting purpose. My first design approach was
    Run these two system as a pair. The producer will call a WCF service hosted in consumer when a document is ready for printing and consumer will call a WCF service in producer to report the status.

If the document volume is high then user can configure and run multiple Producers and one consumer. That means each instance of producer, we need to provide unique endpoints. But producer can communicate to any one Consumer to status reporting thus by adding load to one of the Consumer.

If you think in terms of scalability/deployment you can visualize how complex the design will be. Yes I also realize that my design is ridiculous. To make it more scalable, I have to redesign the communication between the Consumer and the Producer.

This time I thought of trying Duplex communication for the first time. Initially I avoid duplex binding in first place because I don’t know it, second a bit scared of introducing complexity. In my mind duplex binding is complex and my approach I explained above is simple 🙂 (how ignorant I am).

So I decided to try duplex communication. But I need to evaluate it and don’t want to mess with my current implementation. So end up in writing a small tracer to experiment duplex communication. Rest of the post will go through the tracer I created.

Note: My design is surrounded with the proxy less communication approach.

Let’s start with the Service contract and Callback contract.

[ServiceContract (SessionMode=SessionMode.Required,CallbackContract=typeof(ICallbackInterface))]
public interface IServiceContract
{
    [OperationContract (IsOneWay=true)]
    void MessageToProcess(ServiceMessage message);
}

 

As you can see I mentioned the type of callback contract in ServiceContract attribute. The above contract will be implemented in Consumer and Producer will call the consumer using this contract if any thing available for processing.

public interface ICallbackInterface
{
    [OperationContract(IsOneWay=true)]
    void ProcessedMessage(ServiceMessage message);
}

The above callback interface will be implemented in Producer. Consumer will callback the Producer and update the status using this contract.

ServiceMessage is just a value object to transfer data between consumer and producer. It has just one string field called Message.

Let’s implement the Service contract in one of the class in Consumer.

[ServiceBehavior (InstanceContextMode=InstanceContextMode.PerSession)]
public class MessageProcessingService:IServiceContract 
{
    private ICallbackInterface GetCurrentCallback()
    {
        return OperationContext.Current.GetCallbackChannel<ICallbackInterface>();
    }
    public void MessageToProcess(ServiceMessage message)
    {
        ProcessRequest procRequest = new ProcessRequest(this.GetCurrentCallback(), message);
        ProcessQueue.Add(procRequest);
    }
}

 

We need to decorate the MessageProcessingService with ServiceBehavior attribute as shown above, we cannot set that in config file.

GetCurrentCallback function will return the callback instance that is part of the service call.

MessageToProcess function will be called by Producer once it produce some message to process. As you can see I created a new object of ProcessRequest  with callback instance and message then add the ProcessRequest instance to a queue. I will explain why we need queuing system.

Why we need a Queue?

Think of a scenario where there are multiple Producers and single consumer. The single consumer may not able to process all the message received from multiple producers in real time. So all the message will be queued along with the callback instance. Consumer will process the item in the queue one by one and notify the producer once the processing is done. With this implementation we can have n number of producers and one consumer.

Process Request class

public class ProcessRequest
{
    private readonly ICallbackInterface _callbackInterface;
    private readonly ServiceMessage _message;
    public ProcessRequest(ICallbackInterface callbackInterface, ServiceMessage message)
    {
        _callbackInterface = callbackInterface;
        _message = message;
    }

    public ICallbackInterface GetCallback()
    {
        return _callbackInterface;
    }

    public ServiceMessage GetMessage()
    {
        return _message;
    }
}

 

ProcessQueue implementation as follows

public static class ProcessQueue
{
    private static Queue<ProcessRequest> _processQueue;
    private static ManualResetEvent _enqueuedEvent;

    static ProcessQueue()
    {
        _processQueue = new Queue<ProcessRequest>();
        _enqueuedEvent = new ManualResetEvent(false);
    }

    public static void Add(ProcessRequest request)
    {
        lock (_processQueue)
        {
            _processQueue.Enqueue(request);
            _enqueuedEvent.Set();
        }
        ProcessQueuedItem();
    }

    private static ProcessRequest _currentRequest;
    public static bool Dequeue()
    {
        lock (_processQueue)
        {
            if (_processQueue.Count > 0)
            {
                _enqueuedEvent.Reset();
                _currentRequest = _processQueue.Dequeue();
                return true;
            }
            else
                return false;
        }
    }

    private static void ProcessQueuedItem()
    {
        while (Dequeue())
        {
            ServiceMessage message = _currentRequest.GetMessage();
            message.Message += " {Processed}";
            _currentRequest.GetCallback().ProcessedMessage(message);
        }
    }
}

 

ProcessedQueuedItem function process the message, for my tracer I just appended ‘{Processed}’ at the  message.

We are done with the Consumer implementation. Let’s go through the Producer.

public partial class frmProducer : Form
{
    public frmProducer()
    {
        InitializeComponent();
        this.Text = this.Text+ RandomGenerator.GetRandom().ToString();
    }

    private void btnSend_Click(object sender, EventArgs e)
    {
        ServiceMessage message = new ServiceMessage();
        message.Message = txtMessage.Text;
        InstanceContext instanceContext = new InstanceContext(new CallbackHandler());
        IServiceContract service = ServiceFactory.CreateInstance<IServiceContract>(instanceContext);
        service.MessageToProcess(message);
    }
}

 

As you can see in btnSend_click we need to create instance of InstanceContext with an instance of class that implemented ICallbackInterface I created earlier. Then I call a factory class to get the channel to Consumer. In the factory I used DuplexChannelFactory instead of ChannelFactory.

CallbackHandler implementation

public class CallbackHandler:ICallbackInterface
{
    public void ProcessedMessage(ServiceMessage message)
    {
        //do the status reporting here.
    }
}
 

We are done with our Producer and consumer implementation. We can test it by running different instance of Producer and one instance of consumer and see how the communication works.

Once my tracer is successful I redesigned the communication of Producer and Consumer in my projects with few changes of code. With new design user can add any number of Producer just by creating an instance of Producer without any difficulty.

Hope this little post will help some one who is new to duplex communication in WCF.

Download tracer source code (WCF.TCPIP.Duplex.Service) here

Advertisements

Written by Sony Arouje

September 29, 2011 at 1:56 am

Hosting Pipe/TCP based WCF service in Windows Activation Service

with 8 comments

In this post I will give a brief idea of how to host pipe/TCP based WCF service using WAS. Before WAS, we host TCP/pipe based service using custom hosting. That means we need to write an application ourself to host our services. Including me most of the deves wrote applications to host WCF services, so am not going in detail of custom hosting.

What’s WAS or Windows Process Activation services? WAS is part of IIS that enable us to host non http based services. I am not going much details of WAS. Here I am more concentrating on how to configure WAS and run a small test application.

Configure WAS in our System

By default WAS will be disabled. We need to enable it our self, let’s see how we can do that.

1. Goto control panels –> Programs and Features. Click on ‘Turn Windows Feature on or off’ link. It will open a window as shown below. From the list select Windows Process Activation Service and make sure all the child elements also selected.

image

2. Also scroll up and Select ‘Microsoft .NET Framework 3.xxx’ as shown below. Make sure all the child elements also selected, if not select it.

image

We enabled Windows Activation Service in our system. Let’s go ahead and create a WCF service.

For testing purpose I created a WCF service to add two numbers. Let’s see the service configuration

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>          
        </behavior>
        <behavior name="calcServiceBehaviour">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>    
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <services>
      <service name="ServiceLayer.CalculatorService" behaviorConfiguration ="calcServiceBehaviour">
        <endpoint name="CalculatorService" address="" binding="netTcpBinding"
                  contract="ServiceLayer.ICalc" />
        <endpoint name="CalculatorService" address="" binding="basicHttpBinding"
          contract="ServiceLayer.ICalc" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>

As you can see I have two endpoints HTTP and TCP. If we host this in IIS and try to browse it will throw error. Still some configuration is left behind. Let’s finish that config too.

Goto IIS configuration file. You can find that in C:\Windows\System32\inetsrv\config. Open applicationHost.config in notepad. You can see the screen shot below.

image

Search for bindings, and you can see the marked section as shown above. By default you could only see HTTP binding and rest of the binding you can add it. If other binding exist then we are good. If not copy paste the below bindings to the config file under Bindings section.

<binding protocol="net.tcp" bindingInformation="808:*" />

<binding protocol="net.pipe" bindingInformation="*" />

<binding protocol="net.msmq" bindingInformation="localhost" />

<binding protocol="msmq.formatname" bindingInformation="localhost" />

Next step is create an application in IIS. I named the application as Calculator. Right click on the newly created Application and select Manage Application –> Advanced Settings…, you will get a popup as shown below

image

In the above popup you need to enable the protocol this application going to support. As you can see the marked section, I added http, pipe and tcp protocols for my Calculator service. We can enter the protocols like http,net.pipe,net.tcp (separated by comma).

Once again go back to applicationHost.config file and verify the Sites section. You can see the newly created site with protocols it supports. See the screen shot below

image

We are done with our configuration and the service is ready. Lets go ahead and browse our svc file. If it’s not throwing any error then we are good to go.

Note: If we install IIS after the installation of Visual studio then it will throw some an error like Error 500.21 Handler "svc-Integrated" has a bad module "ManagedPipelineHandler" in its module list". If you are getting this error then run aspnet_regiis.exe –i  in VS command prompt.

Create an application to test our service, I created a winform app to test it. Also we need to create a proxy to access the service. We can create the proxy using svcutil. The util will create a config file as well as shown below.

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="CalculatorService1" closeTimeout="00:01:00" openTimeout="00:01:00"
            receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
            bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
            maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
            messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
            useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
      <netTcpBinding>
        <binding name="CalculatorService" closeTimeout="00:01:00" openTimeout="00:01:00"
            receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false"
            transferMode="Buffered" transactionProtocol="OleTransactions"
            hostNameComparisonMode="StrongWildcard" listenBacklog="10"
            maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
            maxReceivedMessageSize="65536">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00"
              enabled="false" />
          <security mode="Transport">
            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
            <message clientCredentialType="Windows" />
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="net.tcp://sonyarouje/Calculator/CalculatorService.svc"
          binding="netTcpBinding" bindingConfiguration="CalculatorService"
          contract="ICalc" name="CalculatorService">
        <identity>
          <servicePrincipalName value="host/sonyarouje" />
        </identity>
      </endpoint>
      <endpoint address="http://localhost/Calculator/CalculatorService.svc"
          binding="basicHttpBinding" bindingConfiguration="CalculatorService1"
          contract="ICalc" name="CalculatorService1" />
    </client>
  </system.serviceModel>

 

Add an app.config to our test app and copy paste the config generated by svcutil. As you can see we have two endpoint http and tcp and we can use any of those. I called the service in button click and the code is as follows

CalcClient calc = new CalcClient("CalculatorService");
int x = Convert.ToInt32(txtX.Text);
int y = Convert.ToInt32(txtY.Text);
MessageBox.Show (string.Format("Sum is {0}", calc.Sum(x,y )));
calc.Close();

While creating the object of service proxy we can pass the endpoint name. Here I am passing CalculatorService and it is the name of tcp endpoint. So the communication will establish through TCP. If we pass CalculatorService1 it will use the http end point.

Hope my post will be helpful for some one. if any Comments or Suggestion, pls post it in the comment section.

Download Test Projects

Written by Sony Arouje

April 3, 2011 at 3:19 pm

Posted in .NET, WCF

Tagged with , , , ,

Photo Album using Silverlight,Caliburn Micro and MongoDB–Part 2

with one comment

This post is a continuation to my another post about a photostream application in Silverlight 4. You all can read more about the post here. I publish the code to codeplex with some more updates. The functionalities added to application is as below

  • Add/Delete Categories
  • Public commenting for Photos
  • Delete Photo
  • Filter photo’s based on Category

Below are some of the functionality in the app.

Home Page

Home

The home page will display the thumbnails of all your photos. In the right hand pane you can see the list of categories I created. User can see the photos in a particular category by clicking the category. You can add category by clicking on the Add/Edit category in the right hand side.

Photo Preview

PreviewPhoto

Nothing much to say it just show a preview of your photo. As you can see there are some icons at the bottom of the preview window. One for adding/viewing comments and another for deleting the photo. You might wonder how a public user can delete a photo. No they can’t am working on the admin part once it’s added only the admin user can do the delete and other admin related functionalities.

Public Comment(s)

PhotoComments

Clicking on the small icon next to the delete button will show the comments as well as user can add comments.

Upload Photos

UploadPhoto 

You can upload multiple photos at a time. Currently assigning a photo to category can be done at the time of uploading.

Hope this app will be helpful for some one.

Download Source code.

Written by Sony Arouje

November 28, 2010 at 12:56 am

Photo Album using Silverlight, Caliburn Micro and Mongo DB

with 14 comments

In this post I am going to explain a small Photo Album I created using Silverlight. With this app I also joined the band wagon of NoSQL movement. I used MongoDB as my backend for this application. This application is still in the development mode. I will add more functionality to this application like Public comments, admin module, etc. Currently this app shows the functionality of admin module, like upload photo, delete photo, etc. The application uses MVVM pattern and as usual I used Caliburn Micro here. I used several framework in the app as shown below

  • Silverlight
  • Caliburn Micro
  • Reactive Extension
  • MongoDB
  • WCF

In this application I used Reactive Extension (Rx) to perform Async service calls. I felt the Rx is a very powerful tool to perform Async calls. The one good advantage of Rx is you can place Async calls in Thread Pool and push it to dispatcher once the call completed. All these can be done in one or two lines of code. This way the UI will always responsive.

This is my first experiment with Mongo db, I can say it’s very easy to use and fast. There are several Mongo drivers for .NET available in the market and is free. I used the one from here. The advantage of Mongodb is, I don’t want to write code to map my POCO to tables. You can directly persist your entity to Mongodb. You can find a lot of article about Mongo db in internet

I don’t think I need to explain Caliburn Micro in detail here. I wrote a post that gives a brief introduction to Caliburn Micro.

Running MongoDB

Below are the steps to run MongoDB

  1. Download the latest version of Mongo db from Mongodb.org
  2. Extract the zip file to C:\Mongodb
  3. Create a Folder called data in C drive
  4. Create a subfolder called db inside data
  5. Goto command prompt and change directory to C:\Mongodb
  6. Type Mongod in the command prompt and hit enter

Now the Mongodb will listen to the default port and our app can make request. There are different ways of hosting Mongodb, you can get more details from Mongodb site.

The App

Below is the screen shot of my application.

image

This page will display the thumbnails of uploaded images. We can see the bigger image by clicking on the thumbnail as show below.

image 

The preview will display in a Windowless popup. We can delete the photo by clicking the Trash icon bottom right side of the image. We can upload images by clicking on the upload icon at the top right of the window. The upload page will get displayed as shown below.

image

When the user upload the image, the application will create a thumbnail version of the image and store along with the original image in the server. This helps to transfer and load the thumbnail page.

Let’s see the entity used in this application.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
namespace PicturePortfolio.Domain
{
    [DataContract]
    public class Photo
    {
        private const int THUMBWIDTH = 100;
        private const int THUMBHEIGHT = 100;
        public Photo()
        {
 
        }
        public Photo(PhotoPersistanceObject persistanceObject)
        {
            this.Name = persistanceObject.Name;
            this.Description = persistanceObject.Description;
            this.ID = persistanceObject.ID;
            this.PublicComments = persistanceObject.PublicComments;
            this.GUID = persistanceObject.GUID;
            
            this.LoadThumbNail();
        }

        [DataMember]
        public int ID { get; set; }

        [DataMember]
        public string GUID { get; set; }

        [DataMember]
        public byte[] ImageFile { get; set; }

        [DataMember]
        public byte[] ImageThumbNail { get; set; }

        [DataMember]
        public string Description { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public List<PublicComment> PublicComments { get; set; }

        public PhotoPersistanceObject GetDataForPersistance()
        {
            PhotoPersistanceObject photoPersistance = new PhotoPersistanceObject();
            photoPersistance.ID = this.ID;
            photoPersistance.Name = this.Name;
            photoPersistance.ImagePath = "/test/" + this.Name;
            photoPersistance.Description = this.Description;
            photoPersistance.PublicComments = this.PublicComments;
            if (string.IsNullOrEmpty(this.GUID) == true)
                photoPersistance.GUID = Guid.NewGuid().ToString();
            else
                photoPersistance.GUID = this.GUID;
            return photoPersistance;
        }


        public void SaveImage()
        {
            if (this.ImageFile == null)
                throw new ArgumentNullException();
            try
            {
                byte[] buffer = this.ImageFile.ToArray();
                MemoryStream memStream = new MemoryStream();
                memStream.Write(buffer, 0, buffer.Length);

                this.SaveOrginalImage(memStream);
                this.SaveImageThumbNail(memStream);
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        public void LoadImage()
        {
            string fullFileName = this.GetFileFullPath();
            this.ImageFile = this.GetImageAsByteArray(fullFileName);
        }

        public void LoadThumbNail()
        {
            string fullFileName = this.GetFilePath() + this.ThumbNailImageName;
            this.ImageThumbNail = this.GetImageAsByteArray(fullFileName);
        }

        #region Private Methods
        private void SaveOrginalImage(MemoryStream memStream)
        {
            System.Drawing.Image imgToSave = System.Drawing.Image.FromStream(memStream);
            imgToSave.Save(this.GetFileFullPath(), ImageFormat.Jpeg);
        }
        private void SaveImageThumbNail(MemoryStream memStream)
        {
            Image img = Image.FromStream(memStream);
            Image.GetThumbnailImageAbort myCallback = new Image.GetThumbnailImageAbort(ThumbnailCallback);
            Image imageToSave = img.GetThumbnailImage (THUMBWIDTH, THUMBHEIGHT, myCallback, IntPtr.Zero);
            imageToSave.Save(this.GetFilePath() + ThumbNailImageName, System.Drawing.Imaging.ImageFormat.Jpeg);
        }

        private static bool ThumbnailCallback() { return false; }

        private byte[] GetImageAsByteArray(string fullFileName)
        {
            FileInfo fil = new FileInfo(fullFileName);
            if (fil.Exists == true)
            {
                FileStream fileStream = new FileStream(fullFileName, FileMode.Open, FileAccess.Read);
                byte[] buffer = new byte[fileStream.Length];
                fileStream.Read(buffer, 0, (int)fileStream.Length);
                fileStream.Close();
                return buffer;
            }
            else
                return null;
        }

        private string GetFilePath()
        {
            string filePath = AppDomain.CurrentDomain.BaseDirectory + "Images\\";
            return filePath;
        }
        private string GetFileFullPath()
        {
            string fullPath = this.GetFilePath() + this.Name;
            return fullPath;
        }
        private string ThumbNailImageName
        {
            get
            {
                string fileName = this.Name.Substring(0, Name.LastIndexOf("."));
                return fileName + "_thumb.jpg";
            }
        }
        #endregion
    }
}

 

The entity class is very simple. I may need to give a brief explanation about PhotoPersistanceObject used in the entity class. The PhotoPersistanceObject is used for persisting meta data of the image like Name, description etc. You might think that why cant we save Photo object directly, yes I also thought the same way but their is some issue with Mongodb driver I used here. It’s not supporting byte array neither binary, It allows to store binary in Mongodb but throws error while retrieving. So I used a trimmed down version of Photo entity to persist the data.

Async Calls using Thread Pool

As I told before one of the cool feature of Reactive Extension is it’s advantage of making async calls in thread pool. Even if we place async calls in separate thread in Silverlight still it will block the UI to load if we do it in page load. Because the our thread will work in UI. We can achieve the placing calls in thread pool using Rx. See the below code.

private void GetAllThumbnails()
{
    var func=Observable.FromEvent<GetAllPhotosCompletedEventArgs>(_service,"GetAllPhotosCompleted")
        .ObserveOn(Scheduler.ThreadPool);
    _service.GetAllPhotosAsync();
    func.ObserveOn(Scheduler.Dispatcher)
        .Select(result => result.EventArgs.Result)
        .Subscribe(s => this.ParseThumbnails(s.ToList()));
}

As you can see the service calls are doing in ThreadPool. Once the call is done we will change the ObserveOn to Dispatcher, other wise cross thread expection will throw. I call the GetAllThumbnails in the constructor of a ViewModel. As we are doing the call in Threadpool my UI will loaded without any delay, once the call is completed the thumbnails will start display in the listbox.

Mongodb Repository

I wrote a Generic repository similar to the one I wrote for EF. You can find the generic repository for EF in one of my post. Below is the Generic repository class for Mongodb.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MongoDB;
using MongoDB.Linq;
using MongoDB.Connections;
namespace PicturePortfolio.Persistance
{
    public class GenericRepository:IRepository
    {
        public GenericRepository()
        {
 
        }

        Mongo _mongoDb=null;
        public IMongoCollection<TEntity> GetQuery<TEntity>() where TEntity : class
        {
            if (_mongoDb == null)
            {
                _mongoDb = new Mongo();
                _mongoDb.Connect();
            }
            return DataBase.GetCollection<TEntity>(typeof(TEntity).Name + "s");
        }

        IMongoDatabase db = null;
        private IMongoDatabase DataBase
        {
            get
            {
                if (db == null)
                {
                    db = _mongoDb.GetDatabase("Protfolio");
                }
                return db;
            }
        }

        public IList<TEntity> GetAll<TEntity>() where TEntity : class
        {
            try
            {
                return GetQuery<TEntity>().Linq().ToList<TEntity>();
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        public IList<TEntity> Find<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> criteria) where TEntity : class
        {
            return this.GetQuery<TEntity>().Linq<TEntity>().Where(criteria).ToList<TEntity>();
        }

        public TEntity Single<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> criteria) where TEntity : class
        {
            return this.GetQuery<TEntity>().Linq<TEntity>().Single(criteria);
        }

        public TEntity First<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> criteria) where TEntity : class
        {
            return this.GetQuery<TEntity>().Linq<TEntity>().First(criteria);
        }

        public void Add<TEntity>(TEntity entity) where TEntity : class
        {
            this.GetQuery<TEntity>().Save(entity);
        }

        public void Delete<TEntity>(TEntity entity) where TEntity : class
        {
            this.GetQuery<TEntity>().Remove(entity);
            
        }

        public void Delete<TEntity>(IEnumerable<TEntity> entites) where TEntity : class
        {
            throw new NotImplementedException();
        }

        public void Update<TEntity>(TEntity entity, TEntity old) where TEntity : class
        {
            this.GetQuery<TEntity>().Update(entity, old, UpdateFlags.None, true);
        }
    }
}

 

This app is in very primitive stage. you may need to do lot of refactoring to make use in real scenario. I will work on this app and upload it to codeplex some times later.

Download the current source here.

Image uploading & Retrieving – Silverlight and WCF

with 9 comments

In several forums I saw people asking about how we can upload Images or files to server using silverlight. So I thought of writing one to demonstrate how we can achieve it. I become a big fan of caliburn micro and I used it in this app as well.

In this demo app I demonstrating both approach of accessing WCF service – Proxy less and Proxy approach. I personally like Proxy less approach so I cannot avoid it here also.

Let’s go through my solution structure

image

Repository: This project contains entities and persistence classes. I made it as simple as possible in this demo, so all the persistence related stuff is in the same project.

WCFService: Project contains the service implementation

WCFService.Interfaces: project contains the service contracts.

WCFHost: Project host the WCF service.

In Silverlight folder I have a Project called ServiceLinkProject, that is a project that has link to entity files. It is used for Proxy less WCF communication. In this demo I used my generic repository mentioned in my previous post.

There is nothing much to explain here except the valueconverter I used in the xaml page. I save and retrieve images as byte arrays. But silverlight’s Image control will not be able to render byte arrays. So wrote a Converter inherited from IValueConverter. Let’s see how am using it.

First I created an instance of the converter.

    <navigation:Page.Resources>
        <converter:ByteToImageConverter x:Name="binaryConverter"/>
    </navigation:Page.Resources>

 

Now use this converter while binding the byte[] to image.

<Image x:Name="thumbNail"  Width="100" Height="100" VerticalAlignment="Center" Source="{Binding ImageInBytes,Converter={StaticResource binaryConverter}}"></Image>


I think this project doesn’t requires much explanation. If any one has any questions then am happy to help you out.

Download Source code

Written by Sony Arouje

October 16, 2010 at 4:04 am

Proxy less Silverlight – WCF Async communication

with 12 comments

In this post I am going to explain how a silverlight application can communicate with WCF service without any proxy. I wanted to establish this communication without any autogenerated code because am not a fan of proxies generated by VS. If you want VS to create good autogenerated code then probably invest some time in learning T4 templates. Anyway I haven’t done any research in T4 templates, so let’s do every thing by hand.

Here is my requirement, I have to show a list of customer in my Silverlight app. Keep in mind it just an experiment, so no db involved in this app. For simplicity I hosted my wcf service in IIS.

Let’s straight to the code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using DataModel;
namespace ServiceContracts
{
    [ServiceContract]
    public interface ICustomerService
    {
        [OperationContract]
        ICollection<Customer> GetCustomerList();
    }

}

I only have one function in the service contract, a function return a collection of Customer class. Customer class is a just a C# class that has only two properties as shown below

using System.Runtime.Serialization;
namespace DataModel
{
    [DataContract]
    public class Customer
    {
        [DataMember]
        public int CustomerId { get; set; }

        [DataMember]
        public string CustomerName { get; set; }
    }
}
Let’s give some implementation to our Service Contract
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ServiceContracts; //assembly consist service contracts
using DataModel; //assembly contains data contracts
namespace ServiceLayer
{
    public class CustomerService:ICustomerService
    {
        public ICollection<Customer> GetCustomerList()
        {
            List<Customer> customers = new List<Customer>();
            Customer cust = new Customer();
            cust.CustomerId = 1;
            cust.CustomerName = "sony";

            customers.Add(cust);
            return customers;
        }

        }

}

 

Now our service is ready to host, here I use IIS to host it. But how does Silverlight can utilize the Function we implemented, because I haven’t implemented Async methods. You might know that Silverlight can only work in Async mode. There are several ways of calling the above implemented service in Silverlight. One way is adding Service reference and leave it to VS to create the proxy with Async code generation. Another approach is use Castle Windsor to host the service in Async mode. Some how I didn’t like both the approach so I was trying for a better approach. My search ended up in a blog to achieve the Async communication without much modification to my Service code.

Here is the approach I was looking at. Create a new Service contract with Async functions and make it an alias to my original ICustomerSerivce

[ServiceContract(Name = "ICustomerService")]
public interface ICustomerServiceAsync
{
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginGetCustomerList(AsyncCallback callback, object state);

    ICollection<Customer> EndGetCustomerList(IAsyncResult result);
}

 

And use the above ICustomerServiceAsync to communicate to ICustomerService. This approach is pretty clean and we don’t want to add any Async methodology to our core service.

Below is my web.config of WCFService host.

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="CustomerService">
        <endpoint address="" contract="ServiceContracts.ICustomerService" binding="basicHttpBinding"></endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- 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="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>  
</configuration>

 

As you see my service end point configuration I have not mentioned ICustomerServiceAsync. Let’s go through the silverlight client how we can communicate to our service.

private void button1_Click(object sender, RoutedEventArgs e)
{
    EndpointAddress endPoint = new EndpointAddress("http://localhost:63301/CustomerService.svc");
    BasicHttpBinding binding = new BasicHttpBinding();
    ICustomerServiceAsync customerService = new ChannelFactory<ICustomerServiceAsync>(binding, endPoint).CreateChannel();

    customerService.BeginGetCustomerList(a => 
    {
        try
        {
            ICollection<Customer> person = customerService.EndGetCustomerList(a);
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }, customerService);

}

In a button click am calling the service.  Here I used the ICustomerAsync to create the channel. Ayende’s blog will give you more details.

You might think how I could able to reference ICustomerServiceAsync and Customer classes in my Silverlight client. What I did here is I created a Silverlight class library and add ICustomerAsync and Customer class as a link. In VS we can do it by selecting add existing item and rather than clicking on the Add button, click on the arrow on the right side of the Add and select as link from the option.

In the above client code I used lambda expression to call the service. You can also use a anonymous delegate or Callback method to achieve the same.

One important thing you need to add to our WCFService host project is clientaccesspolicy.xml, other wise Silverlight client will not be able to communicate and throws Security exception. Below is the policy file

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

 

To test my connection and exceptions I used a Winform application. Silverlight wont give proper error details.

Download the code here

 

 

Written by Sony Arouje

October 1, 2010 at 7:14 pm

WCF Hosting an easy method

with 2 comments

My current project is based on WCF service. One of my responsibility is to find a method to host the WCF service. I googled a lot and failed to find one. Every site mentioned about creating ServiceHost instance one by one and call the open method on all service. The disadvantage of this method is we need to add a ServiceHost instance when ever we add a new service to the hosting application. Thus by modifying the service host application

So I come across with an idea of a method to read the Service configuration and host each service. Following is the method I created.

using System.Xml.Linq;

private static List<Type> ServiceHostHelper()
{
    XDocument configXML = XDocument.Load(“ServiceHost.exe.config“); //load the app config file to read using LINQ.
    var configs = (from config in configXML.Descendants(“service”)
                       select new AssemblyDetails
                       {
                           ActivatorClass = config.Attribute(“name”).Value
                       }
                   );

    Assembly assembly;
    assembly = Assembly.LoadFrom(“AddressMngr.dll”);
    List<Type> assmTypes = new List<Type>();
    foreach (AssemblyDetails assm in configs)
    {

//reflection to get the type of the service.         
        Type type = assembly.GetType(assm.ActivatorClass);         assmTypes.Add(type);
    }
    return assmTypes;
}

AssemblyDetails is my class to store the name of the service class. Below is the class

public class AssemblyDetails
{
    string _activatorClass;
    string _fullPath;
    public string ActivatorClass
    {
        get { return _activatorClass; }
        set { _activatorClass = value; }
    }
    public string FullPath
    {
        get { return _fullPath; }
        set { _fullPath = value; }
    }
}

Now lets see how I host the service. Here I host service using a console application

static void Main(string[] args)
{
    List<Type> services = ServiceHostHelper(); // services object will have all the services we defined in the app.config

    ServiceHost[] hostApp = new ServiceHost[services.Count];
    Console.WriteLine(“Following Services are Started”);
    for (int i=0;i<services.Count;i++)
    {

            Type service = services[i];
            hostApp[i] = new ServiceHost(service);
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine(service.ToString());

            hostApp[i].Open();
    }
    Console.ForegroundColor = ConsoleColor.Gray;
    string key=string.Empty ;
    do
    {
        Console.Write(“Type exit to terminate the host>”);
        key = Console.ReadLine();
        if (key == “exit”)
        {
            for (int i = 0; i < services.Count; i++)
            {
                hostApp[i].Close();
            }
        }
    } while (key != “exit”);
}

We also need to see how I configured the service. Here is my app.config configuration

<services>
  <service name=”AddressMngr.UserManager“>
    <endpoint address=”net.tcp://localhost:8001/UserManager”
              binding=”netTcpBinding”
              bindingConfiguration=”TransactionalTCP”
              contract=”AddressMngr.IUser”/>
  </service>
  <service name=”AddressMngr.Address” behaviorConfiguration=”ThrottledBehaviour”>
    <endpoint address=”net.tcp://localhost:8001/Address”
      binding=”netTcpBinding”
      bindingConfiguration=”TransactionalTCP”
      contract=”AddressMngr.IAddress”/>
  </service>
</services>

One thing we need to take care is the service name (marked in red) should be same as the class we implemented the Service contract with full name space. I am giving the fully qualified name is to load the class using reflection.

If you have any question then let me know, am happy to help you.

Technorati Tags: ,

Written by Sony Arouje

August 25, 2010 at 4:17 pm

Posted in WCF

Tagged with ,

%d bloggers like this: