WCF

How to consume WCF service in .NET

May 27, 2013 .NET, WCF No comments

What? I must be kidding. This is not blog for kids trying to play with .NET. Every professional .NET developer knows how to consume WCF. Don’t they? There is nothing more easier than that.

Well, not that long ago I realized that the way I like to consume WCF services is not 100% correct.

What I like to do is use of “using”:

using (var client = new SomeServiceClient())
{
  var response = client.SomeServiceOperation(request);
  //return or do something
}

While this looks nice, here is thing which even kids won’t like: Dispose method for the client is not really implemented correctly by Microsoft! It could throw an exception if there is network problem therefore masking other exceptions that could have happened in between. You can understand the issue better if you have a look at WCF samples (WF_WCF_SamplesWCFBasicClientUsingUsing).

MS proposes their own solution (read it here):

var client = new SomeServiceClient();
try
{
    var response = client.SomeServiceOperation(request);
    // do something
    client.Close();
}
catch (Exception)
{
    client.Abort();
    throw;
}

While this is correct way it is too much code, especially if you put catch blocks for Communication and Timeout exceptions as recommended by MS. Guys over internet propose other solutions, like wrapping the call or extension methods.

Here is my solution, which is nothing new, but just slightly modified version of best proposed answer on SO:

Elegant example of usage with return statements:

return Service<ISomeServiceChannel>.Use(client =>
{
    return client.SomeServiceOperation(request);
});

And the solution itself:

public static class Service<TChannel>
{
    public static ChannelFactory<TChannel> ChannelFactory = new ChannelFactory<TChannel>("*");

    public static TReturn Use<TReturn>(Func<TChannel, TReturn> codeBlock)
    {
        var proxy = (IClientChannel)ChannelFactory.CreateChannel();
        var success = false;
        try
        {
            var result = codeBlock((TChannel)proxy);
            proxy.Close();
            success = true;
            return result;
        }
        finally
        {
            if (!success)
            {
                proxy.Abort();
            }
        }
    }
}

And some bitterness for the end. It doesn’t look like Microsoft is in a hurry to fix Dispose while they should accordingly to their own guidelines. But even knowing this I still like “using” and will probably be stick to it for smaller things. You see, my problem is that I have never-ever experienced inconveniences or issues because of this.

Is it same for you or do you have a story to share with me/others in your comment? :)


No comments


Consuming REST services in .NET

December 17, 2012 .NET, REST, WCF 5 comments

There are few different ways of consuming REST services in .NET

  1. Plain .NET HTTP request
  2. WCF mechanisms
  3. HttpClient
  4. Other libraries

In this post I would like to demonstrate how you can consume REST in C#.

Before we proceed to examples, let’s choose some very simple public REST API to consume. I stopped at this one: http://timezonedb.com/api. It is very simple service providing current local time for requested time zone. After registering you will get some key to access api. In this blog post we will use “YOUR_API_KEY”.

Here is sample response of the service we chose to consume:

<?xml version="1.0" encoding="UTF-8"?>
<result>
    <status>OK</status>
    <message></message>
    <countryCode>AU</countryCode>
    <zoneName>Australia/Melbourne</zoneName>
    <abbreviation>EST</abbreviation>
    <gmtOffset>39600</gmtOffset>
    <dst>1</dst>
    <timestamp>1321217345</timestamp>
</result>

 

Whichever approach we take, we would need some entities corresponding to the API’s response.

For XML response use cases I prepared following entity:

    [XmlRoot("result")]
    public class TimezoneDbInfo
    {
        [XmlElement("status")]
        public string Status { get; set; }
        [XmlElement("message")]
        public string Message { get; set; }
        [XmlElement("countryCode")]
        public string CountryCode { get; set; }
        [XmlElement("zoneName")]
        public string ZoneName { get; set; }
        [XmlElement("abbreviation")]
        public string Abbreviation { get; set; }
        [XmlElement("gmtOffset")]
        public int GmtOffset { get; set; }
        [XmlElement("dst")]
        public int Dst { get; set; }
        [XmlElement("timestamp")]
        public int Timestamp { get; set; }
    }

For JSON use cases we will use the following:

    [DataContract(Name = "result")]
    public class TimezoneDbInfoJson
    {
        [DataMember(Name = "status")]
        public string Status { get; set; }
        [DataMember(Name = "message")]
        public string Message { get; set; }
        [DataMember(Name = "countryCode")]
        public string CountryCode { get; set; }
        [DataMember(Name = "zoneName")]
        public string ZoneName { get; set; }
        [DataMember(Name = "abbreviation")]
        public string Abbreviation { get; set; }
        [DataMember(Name = "gmtOffset")]
        public int GmtOffset { get; set; }
        [DataMember(Name = "dst")]
        public int Dst { get; set; }
        [DataMember(Name = "timestamp")]
        public int Timestamp { get; set; }
    }

So let’s start!

Option 1: Plain .NET HTTP request

Here is how you can consume REST using WebRequest:

var urlTemplate = "http://api.timezonedb.com/?zone={0}&key={1}";
var url = string.Format(urlTemplate, "Europe/Kiev", "YOUR_API_KEY");

var request = WebRequest.Create(url);
var response = request.GetResponse();
var s = new XmlSerializer(typeof(TimezoneDbInfo));
var timezoneDbInfo = (TimezoneDbInfo)s.Deserialize(response.GetResponseStream());

And if you would need to consume same data but in JSON format, you can come up with following code:

var urlTemplate = "http://api.timezonedb.com/?zone={0}&key={1}&format=json";
var url = string.Format(urlTemplate, "Europe/Kiev", "YOUR_API_KEY");

var webClient = new WebClient();
byte[] downloadedRawResponse = webClient.DownloadData(url);

var stream = new MemoryStream(downloadedRawResponse);
var s = new DataContractJsonSerializer(typeof(TimezoneDbInfoJson));
var timezoneDbInfo = (TimezoneDbInfoJson)s.ReadObject(stream);

Either way, using WebRequest or WebClient allows for some lower level of flexibility like controlling timeouts, headers and many other things. For example:

request.Timeout = 30000;
request.Headers.Add("Accept-Language", "en-US");

Some of the disadvantages of above approach are manual building of a request URL and manual deserialization of a response. Many of you might not like the above code, thus let’s switch to WCF approach, which looks more elegant and robust at the first glance.

Option 2: WCF mechanisms

Not a secret that we can create REST services with WCF. Effectively this means that we can also create client for other REST services. For this all we need is just to create proxy as if it was our own service. Since, we cannot get wsdl with metadata for our service we have to create proxies manually.

To start we put some WCF configuration in place:

<system.serviceModel>
  <bindings>
    <webHttpBinding>
      <binding name="webHttpBindingCustom"
                receiveTimeout="00:01:01" sendTimeout="00:01:01">
        <security mode="None"/>
      </binding>
    </webHttpBinding>
  </bindings>
  <client>
    <endpoint address="http://api.timezonedb.com/"
              binding="webHttpBinding"
              bindingConfiguration="webHttpBindingCustom"
              behaviorConfiguration="tzBehavior"
              contract="ConsumingRestInNet.ITimezoneDb"
              name="TimeZoneDbREST" />
  </client>
  <behaviors>
    <endpointBehaviors>
      <behavior name="tzBehavior">
        <webHttp/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>

We already have some configuration flexibility which comes with WCF. Now, let’s define service contract:

[ServiceContract]
public interface ITimezoneDb
{
    [OperationContract]
    [XmlSerializerFormat]
    [WebGet(UriTemplate = "?zone={zone}&key={key}")]
    TimezoneDbInfo GetTimezoneInfo(string zone, string key);

    [OperationContract]
    [WebGet(UriTemplate = "?zone={zone}&key={key}&format=json")]
    TimezoneDbInfoJson GetTimezoneInfoJson(string zone, string key);
}

(In above method we can avoid having 2 methods by orchestrating our TimezoneDbInfo entity with DataContract in addition to XmlRoot and by having 3rd param).

XML consumption:

var channelFactory = new ChannelFactory<ITimezoneDb>("TimeZoneDbREST");
var channel = channelFactory.CreateChannel();
var timezoneDbInfo = channel.GetTimezoneInfo("Europe/Kiev", "YOUR_API_KEY");

JSON consumption:

var channelFactory = new ChannelFactory<ITimezoneDb>("TimeZoneDbREST");
var channel = channelFactory.CreateChannel();
var timezoneDbInfo = channel.GetTimezoneInfoJson("Europe/Kiev", "YOUR_API_KEY");

You can also go further and implement your own Client class:

public class TimezoneDbClient : ClientBase<ITimezoneDb>, ITimezoneDb
{
    public TimezoneDbClient(string endpointConfigurationName)
        : base(endpointConfigurationName)
    {
    }
    public TimezoneDbInfo GetTimezoneInfo(string zone, string key)
    {
        return base.Channel.GetTimezoneInfo(zone, key);
    }
    public TimezoneDbInfoJson GetTimezoneInfoJson(string zone, string key)
    {
        return base.Channel.GetTimezoneInfoJson(zone, key);
    }
}

Now consumptions will look like piece of cake:

var client = new TimezoneDbClient("TimeZoneDbREST");
var timezoneDbInfo = client.GetTimezoneInfoJson("Europe/Kiev", "YOUR_API_KEY");

Well, of course! All nasty code went to other classes and the config.

Option 3: HttpClient

It would be a perfect ending for a blog post. But it is not. On one hand using WCF provides us with great abstraction over service, but on the other hand it is just overhead for doing simple things. Also some people think that coupling generated by WCF defeats the point of REST.

Here is extract of a great answer on SO about what exactly is RESTful programming:

Really, what it’s about is using the true potential of HTTP. The protocol is oriented around verbs and resources. The two verbs in mainstream usage is GET and POST, which I think everyone will recognize. However, the HTTP standard defines several other such as PUT and DELETE. These verbs are then applied to resources.

To leverage all of this potential Microsoft has built System.Net.Http.HttpClient.

HttpClient is inside of namespace System.Net.Http but nuget package is called Microsoft.Net.Http. So don’t get confused. If you add the package it will simply reference System.Net.Http in your project. Nuget page says:

“This package provides a programming interface for modern HTTP applications. This package includes HttpClient for sending requests over HTTP, as well as HttpRequestMessage and HttpResponseMessage for processing HTTP messages.”

Here is how we can use HttpClient:

var urlTemplate = "http://api.timezonedb.com/?zone={0}&key={1}&format=json";
var url = string.Format(urlTemplate, "Europe/Kiev", "YOUR_API_KEY");

var httpClient = new HttpClient();
var streamTask = httpClient.GetStreamAsync(url);

var s = new DataContractJsonSerializer(typeof(TimezoneDbInfoJson));
var timezoneDbInfo = (TimezoneDbInfoJson)s.ReadObject(streamTask.Result);

Code above looks pretty much the same as when we used plain WebRequest. But HttpClient is much more advanced and adopted for consuming REST services. For example, it has methods: GetAsync and PostAsync. Reading and sending custom headers is much more simplified. Here is great post with many examples of using HttpClient: http://www.bizcoder.com/index.php/2012/01/09/httpclient-it-lives-and-it-is-glorious/

Option 4: Other libraries

So, are there any other possibilities to consume REST in .NET?

Yes. There are dozen of libraries out there implemented exactly for that, though I’m sure that a lot of them cannot be considered as good candidates.

[Edit 2015-Sep-2016] People often mention Restsharp and Hammock libraries.

Links

 

Hope this post comes handy for you!


5 comments


Book Review: Programming WCF Services

July 22, 2012 Book Reviews, WCF 2 comments

To be honest, for me this was the most exhausted reading since years. I started reading this book probably year or even more ago. Always coming back to it in hope that at some point of time it will grasp me into normal pace of reading, so I will be able to finish it. But it was not the case.

Though I finished the “Programming WCF Services”, I’m bit disappointed. I thought that the book will serve me with deep insight into advanced topics in easy to consume manner. Instead it jumped from extreme basics to intermediate and to advanced, but always with chunks of code, which were either boring or repeating or difficult to understand by simple reading. When I was about to try something out articles from internet were more helpful for me then code from book.

The book is good in what it does, but now I think about it more like about cookbook and not like about book you read from beginning to the end. It was my mistake to read it like that.

I feel myself comfortable with WCF. Reading this book was to strengthen my knowledge in WCF and to open tough things I didn’t know. I’m afraid that I did not met what I expected. Of course no one can remember all innumerous extension points or tricky security configuration or other wide range of stuff possible with WCF. Probably author of the book knows everything he wrote by heart. I wish I have super memory, but I often forget a lot of things I read about. Pity! If you know basics and understand core principles it should not be a problem to figure out what you need with couple of MSDN pages and some googling. I hope I will manage my further assignments even without knowing all possible combinations of configurations of WCF, even I look stupid not being able to shot people with immediate WCF solutions/answers/ideas.

One more lesson learned: It is better to play more with things you what to learn about than to obdurately read comprehensive book about those things.


2 comments


ODATA

May 20, 2012 C#, OData, WCF, Web 3 comments

Let’s talk about OData.

At first glance

I would propose to start our OData journey with the best thing about it. Which is openness of data, easy of accessing and working with it. Client applications no longer need to depend on some specific service methods or formats if there is OData feed available. Consuming OData is simple and enjoyable.

For example, I want to know how many users with name ‘Andriy’ are there on StackOverflow with reputation higher than 500. No one at StackOverflow would develop special method in API which would allow me to request exactly this data.

But as StackOverflow exposes OData feed we can connect to it with LinqPad (get it here) and simply write normal C# linq query, like this one:

Users.Where(x=>x.DisplayName.Contains("Andriy") && x.Reputation > 500).OrderBy(x=>x.Reputation)

image

You can see same data if you use URL below. This URL was built by LinqPad to request data:

http://data.stackexchange.com/stackoverflow/atom/Users()?$filter=substringof(‘Andriy’,DisplayName) and (Reputation gt 500)&$orderby=Reputation

(View page source if you don’t like how your browser rendered that feed).

So, no magic. You just build special URL and get your data of interest in preferred format. You can use wide set of libraries both for client and server to implement and use OData.

Whenever you see this icon Datafeeds16 it is good indication that there is OData feed available. There are many applications/web sites that already utilize this protocol. Do you use Nuget? It works through OData. Know ebay? They expose its catalog via OData. Need more examples? Go to ecosystem page of OData.

So what is OData?

The Open Data Protocol (OData) is a Web protocol for querying and updating data that provides a way to unlock your data and free it from silos that exist in applications today. OData does this by applying and building upon Web technologies such as HTTP, Atom Publishing Protocol (AtomPub) and JSON to provide access to information from a variety of applications, services, and stores. The protocol emerged from experiences implementing AtomPub clients and servers in a variety of products over the past several years.  OData is being used to expose and access information from a variety of sources including, but not limited to, relational databases, file systems, content management systems and traditional Web sites.

…from http://www.odata.org/

Continue your reading about OData on its documentation page here.

If you have time, I would recommend to watch this “OData: There’s Feed for That” MIX10 video.

Let’s build our first OData service

As OData was initially introduced by Microsoft no wonder it is extremely easy to put it in place when you are on MS stack of technologies. If you are using EF there is almost nothing you have to do to make it happen.

Add “WCF Data Service” to your project.

image

You will get following code:

public class WcfDataService1 : DataService< /* TODO: put your data source class name here */ >
{
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(DataServiceConfiguration config)
    {
        // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
        // Examples:
        // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead);
        // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }
}

Assuming that you have your data model generated on Northwind db. All you would need is something like this:

public class WcfDataService1 : DataService<NorthwindContext>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.All);
        config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }

    protected override NorthwindContext CreateDataSource()
    {
        return new NorthwindContext(ConfigurationManager.ConnectionStrings["NorthwindContext.EF.MsSql"].ConnectionString);
    }
}

And now clients can do whatever they like with your data. Of course, you can restrict them as you wish. OData is not about putting your database into web, you can control what you expose and to which extent. Also you can play with your service by adding caching, intercepting queries, changing behaviors and much-much more.

In next post I will show how we can build OData service for custom data you keep in memory.

In meantime you can checkout another video from NDC2011 by Vagif Abilov. Video is called “Practical OData with and without Entity Framework”. Follow this link to direct mp4 video file.


3 comments


WCF Session, Service Instance and Threads Allocation

April 16, 2012 WCF 2 comments

I would like to quickly mention how threads are used while running instance of WCF service. Don’t bother if you are WCF guru!

So quick and deep into WCF

When using PerSession, once client did first call, instance of service implementation will be kept on server. Every client has it’s own session executed only on one thread at one point of time (thread is taken from ThreadPool). So, one client cannot run concurrent calls within one session. But you can change ConcurrencyMode to make this happen. In case of PerCall service instance will be disposed immediately after call is done.

ThreadPool uses available thread to run your service code. But if you start 1000 concurrent clients ThreadPool will allocate many threads, which involves resources, such as memory. So keep this in mind when designing scalable applications. PerCall is best choice for highly scalable services.

Calculator example, one we all like

I created simple Calculator service to show how treads are used by WCF service.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorService
{
  private int _threadIdOnCreating = Thread.CurrentThread.ManagedThreadId;
  public int AccumulatedValue { get; private set; }
  public int Accumulate(int valueToAdd)
  {
    AccumulatedValue += valueToAdd;

    Console.WriteLine(string.Format(
    "Accumulated: {0}. ThreadIdOnServiceCreating:{1} CurrentThreadId:{2}",
   AccumulatedValue, _threadIdOnCreating, Thread.CurrentThread.ManagedThreadId));

    return AccumulatedValue;
  }
}

Calculator is very simple it allows to accumulate some value within session and also it logs some interesting threading information – id of service instance creator thread and id of current thread within method.

Output

I ran Accumulate method with parameter 2 for five times and then created new client proxy and did the same. Below is output, which proves that server keeps instance of service implementation (proof is threadId on creation), but methods are ran on different threads, taken from ThreadPool (proof is threadId on run).

I'm calculator
Accumulated: 2. ThreadIdOnServiceCreating:6 CurrentThreadId:6
Accumulated: 4. ThreadIdOnServiceCreating:6 CurrentThreadId:7
Accumulated: 6. ThreadIdOnServiceCreating:6 CurrentThreadId:6
Accumulated: 8. ThreadIdOnServiceCreating:6 CurrentThreadId:7
Accumulated: 10. ThreadIdOnServiceCreating:6 CurrentThreadId:6
Accumulated: 2. ThreadIdOnServiceCreating:9 CurrentThreadId:9
Accumulated: 4. ThreadIdOnServiceCreating:9 CurrentThreadId:6
Accumulated: 6. ThreadIdOnServiceCreating:9 CurrentThreadId:9
Accumulated: 8. ThreadIdOnServiceCreating:9 CurrentThreadId:6
Accumulated: 10. ThreadIdOnServiceCreating:9 CurrentThreadId:8

Hope this was interesting. Also continue your reading on instance/session management of WCF at msdn pages here if you would like to. Or read another short blog post my me.

BTW, this is just reposting of one of my answers at stackoverflow, but I thought it worth to have it here.


2 comments


WCF Configuration caused memory ‘leaks’

August 17, 2011 Performance, WCF 9 comments

If you are lazy to read whole post, jump to “Summary”.

Have you been in situation when a project was designed for low performance needs and in the end of the day customers want it to be 100 times faster? You have to be ready for such time and be ready to scale.

We changed the configuration of our application for more aggressive processing but it did not meet customer needs, so we had to do much more other tweaks to make our service performing better. Unfortunately along with with improvements we started to get memory leaks.

So our app started to eat memory dramatically. Within 5-15 minutes it was already hitting 2Gb score. Why the hell? Most of the changes were configuration and performance tweaks.

I decided to profile the application with ANTS Memory Profiler. (by the way it is simply amazing profiler). After I learned what means what in the profiler, I was able to analyze what I see. Turns out our application produces huge memory fragmentation with large objects. (see screenshots below)

Here are some recommendations for fixing such issues from profiler website:

Solving large object heap fragmentation

Large object heap fragmentation can be one of the most difficult types of memory problem to solve, because it often involves changes to the architecture of the application. The best approach to use will depend on the exact nature of your program:

•Split arrays into smaller units so that they remain below 85kB (and so are never allocated on the large object heap).

•Alternatively, you can allocate the largest and longest-living objects first (if your objects are files which are queued for processing, for example).

•In some cases, it may be that periodically stopping and restarting the program is the only option.

So what are these large objects? My initial thought was that out app simply was not keeping up with processing and we overloaded memory with many large collections that were not garbage collected.

clip_image002

But what was interesting was this funny  Byte[] array keeping 134Mb of memory… I drilled deeper and found the following:

image

Oh, System.ServiceModel.Channels.BufferManager! This made me thinks that large objects are actually allocated by WCF and never disposed, so in the end of the day it was causing our memory leaks.

So I knew that it is something related to WCF BufferManager. I started looking at what was changed in WCF configuration in order to process bigger messages. Here is what I found:

<binding name=”Allscripts.Homecare.WSHTTPBinding.Configuration” closeTimeout=”00:05:00″ openTimeout=”00:05:00″ receiveTimeout=”00:10:00″ sendTimeout=”00:05:00″ maxBufferPoolSize=”2147483647″ maxReceivedMessageSize=”2147483647″>
<readerQuotas maxDepth=”2147483647″ maxStringContentLength=”2147483647″ maxArrayLength=”2147483647″ maxBytesPerRead=”2147483647″ maxNameTableCharCount=”2147483647″/>

Do you see anything interesting about the configuration above? Yes, all values are set to max. What are chances that someone really evaluated their impact on performance before setting everything to max? Max is always better. Isn’t it? maxBufferPoolSize property is related to BufferManager. A bit of a search and I found this:

From http://kennyw.com/work/indigo/51 :

“On the built-in WCF Bindings and Transport Binding Elements, we expose MaxBufferPoolSize as a property for you to control our cache footprint. If you are sending small (< 64K) messages, then the default value of 512K is likely acceptable. For larger messages, it’s often best to avoid pooling altogether, which you can accomplish by setting MaxBufferPoolSize=0. You should of course profile your code under different values to determine the settings that will be optimal for your application.”

So with changing maxBufferPoolSize to 0 I was able to witness stability in the work of our service. Of course, it was still consuming some memory because of hard time we gave it, but it was not leaking.

From the picture below you can see that there is no problem with Large Objects Heap. It was nicely bumping up and down (blue line).

image

 

Summary

If you have performance problems, and try to fix them by changing all configuration parameters (timeouts, buffer sizes, other stuff) do this carefully. Always evaluate the performance impact. If you already have problems, use advanced profilers.

Surprisingly, increasing WCF maxBufferPoolSize doesn’t always mean increase in performance, rather it can result in huge memory leaks if the size of your messages is larger than 64K. For larger messages it is better to set MaxBufferPoolSize=0. For me it sounds like GC is not so keen on disposing large objects from heap and this caused our issues.

Hope this helps someone.


9 comments


WCF and versioning – my adventures (or “The resource MultipleIdDefinition was not found”)

May 14, 2011 Errors, WCF No comments

Hey, I believe that everyone of us have ever dealt with versioning. Versioning inside of WCF doesn’t exist if so to say, but it is very easy to keep all your stuff running until you actually have to validate schema of the messages.

In recent time me with my team had to make our Phone client of version 1.0 and 1.1 work with either version of server 1.0 or 1.1. In other words we had 4 cases. Two of them are obviously non-problematic and two are not that clear. Accordingly to MSDN there is no direct support for versioning in WCF, except of that each data elements are optional by default. This means that if you haven’t specified opposite all of your DataMembers are going to be null if they are missed in incoming XML.

So having this in mind I expected that all of our versioning scenarios will go smoothly, but this did not happen. We were getting ugly exception looking like this: “The resource MultipleIdDefinition was not found”. Honestly it was very surprisingly since google search did not give me any good answer for this.

So here are steps that I took to figure out where the problem is:

  • Made the way up to the deserialization code.
  • Debugged to the point where I can see actual payload.
  • For same data request I copied payloads as is from two server versions.
  • Did text comparison and found what I was looking for.

Added properties could not brake serialization, so I found other differences, which were additional z:Id=”i7” right after one of the data contracts. Some of you might know that this is cause of IsReference=true of the DataContract. So I did research if this really has been changed between version 1.0 and 1.1 and found out that it was.

So, long story short, if you having some issues with serialization inside of WCF when dealing with versioning think less about new or even deleted elements of you contract, but think more what can cause mismatch in messages. And dong forget to see source control logs.


No comments


Resolving WCF object graph cycles and CustomMessageInspector

December 16, 2010 WCF 5 comments

Today I played a little bit with WCF services. Currently in system we have extremely cumbersome and large object graphs.
Long story short we have Order data contract that always has Customer property in it. From other side Customer did not have reference to Order, so today I added property IList<Order> Orders to my customer and to test just called wcftestclient. Of course if you are not new to WCF, you know that it showed me that I probably have cyclic dependencies.

Reason is that if you have cyclic dependencies XmlSerializer anyway tries to serialize whole graph till it reaches stackoverflow.
[EDITED because of complains]  Actual error is something like “SerializationException: Customer contains cycles and cannot be serialized if reference tracking is disabled…

To avoid this problem you would need to mark you data contract with [DataContract(IsReference = true)]. So I did:

 [ServiceContract]
 public interface IDataContractCycles
 {
  [OperationContract]
  CustomerModel GetCustomer();
 }

 [DataContract(IsReference = true)]
 public class CustomerModel
 {
  [DataMember]
  public string Name { get; set; }

  [DataMember]
  public IList Orders { get; set; }
 }

 [DataContract(IsReference = true)]
 public class OrderModel
 {
  [DataMember]
  public string Name { get; set; }

  [DataMember]
  public CustomerModel Customer { get; set; }
 }

And to test I again fired up wcftestclient and it crashed!!! wtf? I had to commit some code to keep guys working so I commented Customer property of my Order. I thought that it would crash in our client the same way.

image

And now meaning of this story: TRUST NO ONE!

I cannot give up that easily, so I wrote ever simple wcf server and client, then added custom message inspector to see actual payload.

For this you would need something like below:

 class Program
 {
  static void Main(string[] args)
  {
   var client = new DataContractCyclesClient();

   client.Endpoint.Behaviors.Add(new CustomEndpointBehavior());

   client.Open();

   CustomerModel customerModel = client.GetCustomer();
  }
 }

 internal class CustomEndpointBehavior : IEndpointBehavior
 {
  public void Validate(ServiceEndpoint endpoint){}
  public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters){}
  public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher){}

  public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
  {
   clientRuntime.MessageInspectors.Add(new CustomMessageInspector());
  }
 }

 internal class CustomMessageInspector : IClientMessageInspector
 {
  public object BeforeSendRequest(ref Message request, IClientChannel channel)
  {
   return null;
  }

  public void AfterReceiveReply(ref Message reply, object correlationState)
  {
   reply.ToString(); // THIS IS ACTUAL PAYLOAD OF THE MESSAGE
  }
 }

I got correct object graph and payload with reference Id-s. See message below. It has Customer marked with z:Ref=”i1″ and then the same Id is used in two orders. This is cool stuff.

<s:Body u:Id=”_0″>

  <GetCustomerResponse xmlns=”http://tempuri.org/”>

    <GetCustomerResult z:Id=”i1″ xmlns:a=”http://schemas.datacontract.org/2004/07/WcfLearningCycles” xmlns:i=”http://www.w3.org/2001/XMLSchema-instance” xmlns:z=”http://schemas.microsoft.com/2003/10/Serialization/”>

      <a:Name>Andriy Buday</a:Name>

      <a:Orders>

        <a:OrderModel z:Id=”i2″>

          <a:Customer z:Ref=”i1″ />

          <a:Name>Kindle</a:Name>

        </a:OrderModel>

        <a:OrderModel z:Id=”i3″>

          <a:Customer z:Ref=”i1″ />

          <a:Name>HTC Cable</a:Name>

        </a:OrderModel>

      </a:Orders>

    </GetCustomerResult>

  </GetCustomerResponse>

</s:Body>

Liked it? Yes? No?


5 comments


Exam 73-503: TS: Windows Communication Foundation – PASSED

November 27, 2010 Certification, Success, WCF 3 comments

I recent posts I mentioned that I read training kit for ms WCF exam. Of course I did this for some reason. I had this exam scheduled for yesterday as well as presentation on WCF for Thursday, which went extremely well. All that was scheduled because I decided to throw myself out of comfort zone. I now can ensure you that this approach indeed works. So, if you want to achieve something don’t hesitate – just go ahead and put some deadlines for yourself, and make them visible to others so this will be controlling your activity.

How did I prepare?

So I’m completely sure that positive result of this exam was guaranteed by my experience working with WCF. But anyway I read training kit, which brought many interesting aspects and some kind of hints for the exam. Third learning source (after experience and training kit) was MSDN and writing simple applications by my own. I do not like to use examples from training kit, also I found few mistakes in kit. Thursday’s presentation on WCF helped me as well, I strengthen my knowledge in transactions and instancing. Just before exam I tried MeasureUp demo test and got 6 out 6 – never got this at MeasureUp for other exams.

Passing Exam

Exam has 45 questions for 120 min. And I liked answering for them, since I faced dozen of questions related to what I do in my everyday work.

I PASSED EXAM with score 918, this means that I answered correctly on 41 questions. Woo hoo!

You can see my transcript using this information:
https://mcp.microsoft.com/authenticate/validatemcp.aspx
Transcript ID: 904316
Access Code: andriybuday


3 comments


DevMeeting: WCF–Advanced-1

November 25, 2010 DevMeeting, Presentation, PublicTalks, WCF 2 comments

 

Today I performed meeting on WCF. It was continuation of this thread of meetings.

Couple of interesting facts about this presentation:

1) I started preparing at 3AM and continued doing this till actual presentation at 1 PM. (Yeah I of course responded to some of e-mails at work and did some other stuff, but anyway most time spent on preparation)

2) Also I want to my English teacher to forgive my absence on today’s English Lesson. Additional 1,5 hour really helped me. Guys, could you please ensure her that presentation cost all the money?

3) I took to much stuff to talk during 1 hour. Initially I prepared following list:

  • Basics overview
  • Sessions and Instances
  • Transactional Services
  • Concurrency
  • Security
  • Instrumentation
  • Most often troubles you might face using WCF

So I crossed some items, but it turned about that we had time only for two first items in bold.

Regardless of that many people, I’m sure, liked it very much.

4) I did a lot of coding during presentation, I hope guys liked this. Right?

5) I was forgetting about zooming and colors on projector. My bad.

6) There was not enough sit places for guys, many of them simply stand near the wall. Sorry for that. I hope managers will resolve this issue soon. He-he.

7) I kept them all interested in further presentation, since Security was not mentioned at all :-P

8) Main Links from this presentation:

9) You can go and download my presentation (I removed transactions to have something to show next time) using this link.

10) So mainly I talked on Sessions and Instances.

11) But, then I also talked on items listed below:

  • Throttling
  • Quotas
    • MaxReceivedMessageSize
    • ReaderQuotas
  • Demarcating
  • Instance Deactivation

12) Thank you!

Guys, I will appreciate your comments/suggestions/thoughts here!


2 comments