Saturday, August 28, 2010

Wrapped BodyStyle in WCF Rest

I m going to explain the difference between BodyStyle = WebMessageBodyStyle.Bare and BodyStyle = WebMessageBodyStyle.Wrapped in WCF Rest Services.
Bare can only support one parameter that is not included in the TemplateUri but Wrapped can support multiple parameters and have some extra XML tags in the body.
I m going to show you an example:



using System.ServiceModel.Web;
using System.ServiceModel;
 
namespace MyWcfServiceLibrary
{
    //POCO Entity
    public class Tag
    {
        public int ID { get; set; }
        public string TagName { get; set; }
    }
 
    [ServiceContract(Namespace = "http://mytagservice")]
    public interface ITagService
    {
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "tags/bare/{id}",
        BodyStyle = WebMessageBodyStyle.Bare)]
        int DoSomethingBare(string id, Tag tag1);
 
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "tags/wrapped/{id}",
        BodyStyle = WebMessageBodyStyle.Wrapped)]
        int DoSomethingWrapped(string id, Tag tag1, Tag tag2);
 
    }
 
    public class TagService : ITagService
    {
        public int DoSomethingBare(string id, Tag tag1)
        {
            return 1;
        }
        public int DoSomethingWrapped(string id, Tag tag1, Tag tag2)
        {
            return 2;
        }
    }
}

BodyStyle = WebMessageBodyStyle.Bare
-----------------------------------------------------------
Request Body:
<Tag xmlns='http://schemas.datacontract.org/2004/07/MyWcfServiceLibrary'>
<ID>1<ID>
<TagName>test</TagName>
</Tag>


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


BodyStyle = WebMessageBodyStyle.Wrapped
-----------------------------------------------------------
Request Body:
<DoSomethingWrapped xmlns='http://mytagservice'>
<tag1 xmlns:a="http://schemas.datacontract.org/2004/07/MyWcfServiceLibrary" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:ID>1</a:ID>
<a:TagName>test1</a:TagName>
</tag1>
<tag2 xmlns:a="http://schemas.datacontract.org/2004/07/MyWcfServiceLibrary" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:ID>2</a:ID>
<a:TagName>test2</a:TagName>
</tag2>
</DoSomethingWrapped>


Response Body:
<DoSomethingWrappedResponse xmlns="http://mytagservice">
<DoSomethingWrappedResult>4</DoSomethingWrappedResult>
</DoSomethingWrappedResponse>


as you can see, if the message is wrapped, then the root xml element is the method name and the children are the parameter names (be careful it is case sensitive).

There are different ways we can consume .Net WCF Rest, to get some idea, you can have a look at this post Consuming .Net WCF Rest in different ways

How to Generate Wrapped message when consuming WCF Rest:
---------------------------------------------------------------------------------
using System;
using System.ServiceModel.Web;
using System.ServiceModel;
using System.Net;
 
namespace MyWcfServiceLibrary
{
    public class Consumer
    {
        private void ConsumeWcfRest()
        {
            string url = "http://something/MyWebsite/tagservice";
 
            Tag tag1 = new Tag() { ID = 1, TagName = "test1" };
            Tag tag2 = new Tag() { ID = 2, TagName = "test2" };
 
            HttpWebRequest req = HttpWebRequest.Create(url + "/tags/wrapped/1") as HttpWebRequest;
            req.Method = "POST";
            string content = "<DoSomethingWrapped xmlns='http://mytagservice'>";
            content = content + DoSerialize(tag1, "tag1");
            content = content + DoSerialize(tag2, "tag2");
            content = content + "</DoSomethingWrapped>";
 
            System.Text.UTF8Encoding en = new System.Text.UTF8Encoding();
            byte[] bArray = en.GetBytes(content);
            req.ContentLength = bArray.Length;
            req.ContentType = "text/xml";
            System.IO.Stream requestStream = req.GetRequestStream();
            requestStream.Write(bArray, 0, bArray.Length);
            requestStream.Close();
 
            System.Net.HttpWebResponse res = req.GetResponse() as System.Net.HttpWebResponse;
 
            System.IO.Stream stream = res.GetResponseStream();
            System.IO.StreamReader sr = new System.IO.StreamReader(stream);
            string str = sr.ReadToEnd();
            sr.Close();
        }
 
        private string DoSerialize(object obj, string rootName)
        {
            System.Runtime.Serialization.DataContractSerializer se;
            if (string.IsNullOrEmpty(rootName))
                se = new System.Runtime.Serialization.DataContractSerializer(obj.GetType());
            else
                se = new System.Runtime.Serialization.DataContractSerializer(obj.GetType(), rootName, "");
 
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            se.WriteObject(ms, obj);
            ms.Position = 0;
            byte[] arr = new byte[ms.Length];
            ms.Read(arr, 0, Convert.ToInt32(ms.Length));
            return new System.Text.UTF8Encoding().GetString(arr);
        }
    }
}


cheers!

4 comments:

lauren said...

Thanks for sharing this information. i was eager to know the difference between Web Message Body Style Bare and wrapped. I searched for example but your blog helps me in understanding both.Thanks a lot.
digital signature

Jose Luis said...

Thanks for the article, there is not so much info like this in the web. It will help me a lot

San said...

Can you please explain why is the (WebMessageBodyStyle.Bare) option resulting in a response without user specified namespace (Namespace = "http://mytagservice")

Paresh Dehadray Blog said...

Hi, This post was very useful for me. Can you please me know how we can create same data in JSON format. I have tried all possible combination but nothing is wokring. In my case my client is using JSON format but we are not sure how to create wrap data in JSON.

Post a Comment