Posts Tagged ‘WCF’

REST/HTTP Services in WCF is nothing new, it’s been there since 2008, version 3.5 of the framework. Yesterday I came across a question that whether a particular operation can support both XML/JSON format and return response in the suitable format as demanded by the client program. To my knowledge the answer was a both Yes & No. Because I did quite extensive study of the System.ServiceModel.Web.WebHttpBehavior and System.ServiceModel.Web.WebGetAttribute back in 2008 as given in the post below:

https://sankarsan.wordpress.com/2008/10/28/wcf-web-model-poxjson-support/

This limitation drew my attention. However there was a solution to the problem.We can always extend the WebHttpBehavior and override the WebHttpBehavior.GetReplyDispatchFormatter method to return our own custom implementation of System.ServiceModel.Dispatcher.IDispatchFormatter. A similar implementation can be found in the post below:

http://damianblog.com/2008/10/31/wcf-rest-dynamic-response/

Wait …..

This kind of an implementation is actually now part of the .NET 4.0. This is controlled by the automaticFormatSelectionEnabled property of the WebHttpBehavior. This property when set to true then the response format of the operation is governed by the Accept , Content-Type header of the request. This feature is called Automatic Format Selection. This is what we will discuss in this post.

I have a simple service with a Add operation as shown below:

[OperationContract] 
[WebGet] 
public int  Add(int i , int j) 
{ 
   // Add your operation implementation here 
   return i+j; 
} 

The client code is a .NET program sending a HTTP request as shown below:

HttpWebRequest request = HttpWebRequest.Create("http://localhost:5072/TestService.svc/Add?i=1&j=1") as HttpWebRequest; 
request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.None; 
request.Method = "GET"; 
request.ContentType = "text/xml"; 
request.Accept = "text/xml"; 
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
using (StreamReader rdr = new StreamReader(response.GetResponseStream())) 
{ 
    Console.WriteLine(rdr.ReadToEnd()); 
}

The response is in JSON format as shown below:

{"d":2}

Now I will turn on auto format selection as shown below using config.

wcfauto

Now the output is XML as shown below:

<AddResponse xmlns="http://sankarsanbose.com/test"><AddResult>2</AddResult></Add 
Response>

Now I will change the Accept header to JSON.

request.ContentType = "text/xml"; 
request.Accept = "text/json";

The response is now again in JSON format as shown below:

{"d":2}

NOTE: If both Accept and Content-Type are specified then Accept takes the higher priority.

What happens if I set the response format in WebGetAttribute? Say I make it Json as shown below:

[OperationContract] 
        [WebGet(ResponseFormat=WebMessageFormat.Json)] 
        public int  Add(int i , int j) 
        { 
            // Add your operation implementation here 
            return i+j; 
        }

The output is driven by Accept Header and is in XML format

<AddResponse xmlns="http://sankarsanbose.com/test"><AddResult>2</AddResult></Add 
Response> 

If I change the headers to JSON obviously the output is JSON.

Now I am changing the ResponseFormat to XML as shown below:

[WebGet(ResponseFormat=WebMessageFormat.Xml)] 

The request headers are set as shown below:

request.ContentType = "text/json"; 
request.Accept = "text/json"; 

The output surprisingly is just 2 neither JSON nor XML.

The request headers are changed back to XML

request.ContentType = "text/xml";
request.Accept = "text/xml";

Now the output is XML is as shown below:

 
<int xmlns="http://schemas.microsoft.com/2003/10/Serialization/">2</int>

This is clearly different from structure of the XML generated earlier. Seems to be using the different serializer.

I was not able to articulate the reason for the above two anomalies very clearly. But I think when auto format selection is enabled then providing the ResponseFormat does not make much sense.

Serialization in WCF–Part I

Posted: September 10, 2011 in .NET, WCF
Tags: ,

In general, when we work with WCF services Serialization/Deserialization is taken care by the framework under the hood.We rarely bother about what serializer is used and how it works.But it’s important to understand this as the message payload generated is fully controlled by serializer you use. So a better understanding of the serialization process /techniques and it’s limitations will help us to design the services better.

WCF uses the System.Runtime.Serialization.DataContractSerializer class for this purpose.The code snippet below uses DataContractSerializer to serialize Plain CLR Object.

class Program 
    { 
        static void Main(string[] args) 
        { 
            Customer c = new Customer() { FirstName = "Sankarsan", LastName = "Bose", Address = "404/6 NSC BOSE ROAD" }; 
            DataContractSerializer ds = new DataContractSerializer(typeof(Customer)); 
            using(var m = new MemoryStream()) 
            { 
                ds.WriteObject(m,c); 
                m.Seek(0,SeekOrigin.Begin); 
                using (var sr = new StreamReader(m)) 
                { 
                    Console.WriteLine(sr.ReadToEnd()); 
                } 
                
            } 
                   Console.Read(); 
        } 
    } 
    public class Customer 
    { 
        public String FirstName { get; set; } 
        public String LastName { get; set; } 
        public String Address { get; set; }

    }


The output will be the following XML string.

<Customer xmlns="http://schemas.datacontract.org/2004/07/SerializationDemo" xmlns:i="'>http://www.w3.org/2001/XMLSchema-instance">

<Address>404/6 NSC BOSE ROAD</Address>

<FirstName>Sankarsan</FirstName>

<LastName>Bose</LastName>

</Customer>

We need to note the following points:

a) The output is XML format

b) A Plain CLR object(POCO) without any additional decoration(attributes) is serialized with Type Name and Properties as XML Elements (This is called inferred data contracts)

c) The xmlns attribute by default is http://schemas.datacontract.org/2004/07/<<CLR Namespace Name>>

d) The ordering of the properties/fields is alphabetically sorted.

e) The XML output does not contain any additional information CLR Datatypes.This is the reason we need to provide the type information while we instantiate the Serializer.

Now if we need to have more fine grained over the serialization output we need to have some mechanism to provide additional inputs to the serializer regarding how we can want to customize our output. The System.Runtime.Serialization.DataContractAttribute and System.Runtime.Serialization.DataMemberAttribute provides the same.

We have used these attributes in the Customer class as shown below:

[DataContract(Name="customer",Namespace="http://sankarsanbose.com/Customer")] 
    public class Customer 
    { 
        [DataMember(Name="firstname",Order=1)] 
        public String FirstName { get; set; } 
        [DataMember(Name = "lastname", Order = 2)] 
        public String LastName { get; set; } 
        [DataMember(Name = "address", Order = 3)] 
        public String Address { get; set; }

    }


The XML output produced is as shown below:

<customer xmlns="http://sankarsanbose.com/Customer" xmlns:i="'>http://www.w3.org/2001/XMLSchema-instance">

<firstname>Sankarsan</firstname>

<lastname>Bose</lastname>

<address>404/6 NSC BOSE ROAD</address>

</customer>

Here we have altered the name of the XML Elements, Namespace and ordering of the elements.

We will play around a little bit with this attributes and let’s remove DataMemberAttribute from one of the properties and make another one private.

[DataContract(Name="customer",Namespace="http://sankarsanbose.com/Customer")] 
public class Customer 
{ 
    [DataMember(Name="firstname",Order=1)] 
    public String FirstName { get; set; } 
    [DataMember(Name = "lastname", Order = 2)] 
    private String LastName { get; set; } 
    public String Address { get; set; }

} 

As the xml output below shows the property(Address) without the DataMemberAttribute is not serialized and the private attribute is serialized with a default NULL value.

<customer xmlns="http://sankarsanbose.com/Customer" xmlns:i="'>http://www.w3.org/2001/XMLSchema-instance">
<firstname>Sankarsan</firstname>
<lastname i:nil="true"/>
</customer>

The default value can be controlled through the EmitDefaultValue parameter of the DataMember attribute.This is true by default and can be turned off as shown below:

[DataContract(Name="customer",Namespace="http://sankarsanbose.com/Customer")]
public class Customer
{
    [DataMember(Name="firstname",Order=1)]
    public String FirstName { get; set; }
    [DataMember(Name = "lastname", Order = 2,EmitDefaultValue=false)]
    private String LastName { get; set; }
    public String Address { get; set; }

}

So the serialized data now no longer emits the lastname with Null value:

<customer xmlns="http://sankarsanbose.com/Customer" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<firstname>Sankarsan</firstname>
</customer>

This post covers the basics and in the next post we will take a deeper look into the DataContractSerializer class.

In an Windows environment every process(or code) executes under some valid user identity which is nothing but a authenticated Windows account.In .NET Framework we have the interface System.Security.Principal.IIdentity which provides the basic definition of identity.

(more…)

Every WCF service needs to have a host process.It can be a windows service,IIS or any other .NET program.This host process will create an instance of the System.ServiceModel.ServiceHost class or any custom class deriving from System.ServiceModel.ServiceHostBase.This host class will manage the service configurations, behaviors, channels and make it accessible to the outside world.When a service is hosted in IIS it behaves a little bit differently.Here we need to create a physical file with .svc extension in the virtual directory of the web server.This file actually points to the service class implementing the ServiceContract and System.ServiceModel.Activation.ServiceHostFactory or a derived class System.ServiceModel.Activation.ServiceHostFactoryBase.When IIS receives a request with that .svc file in URI the corresponding ServiceHostFactory creates an instance of the ServiceHost.The markup contained in a .svc file is shown below:

(more…)

The RIA Services provides a mechanism of exposing data and business logic for consumption by the Rich Internet Applications like Silverlight.These are basically WCF services with some additional plumbing which makes it very easy to develop and consume service from Silverlight applications.Since these are basically WCF services they can be  consumed from other types of applications like ASP.NET/WinForms/WPF as well.
(more…)

In my last post I had started writing about Instance Pooling in WCF and we ended up developing a simple class providing object pooling functionality.In this post we will see what needs to be done step by step to incorporate this instance pool into the WCF framework.

Implementing IInstanceProvider

The class System.Runtime.Dispatcher.DispatchRuntime exposes the property InstanceProvider of type IInstanceProvider.DispatchRuntime uses this instance to acquire and release instances of service objects.IInstanceProvider defines the following methods:

  • GetInstance – Returns an service object instance
  • ReleaseInstance – Releases a service object instance

(more…)