Search code examples
c#wcfrestwcf-rest

How to create a method in WCF RESTful service in the given scenario?


I have to create a PUT RESTful WCF service which will have URI template something like this:

/rs/close_copy/{user_token}?term={term}&brand={brandname}

The request that comes to us has a JSON body in this format:

“acc”: 
“counters”:[ 
{“format”: 
“ink”: 
“ctr”:
“duplex”: },
{…}]

But the issue is, "counters" parameter of above doesn't always come as an array of JSON Object as expected. When there is only one element in "counter", the request comes as a single JSON object and not as a list of JSON object with one element.

It's the third party who is calling our service and they can't make the changes to their request. I have implemented in WCF something as below:

[WebInvoke(Method = "PUT", ResponseFormat = WebMessageFormat.Json,
           RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare,
           UriTemplate = "/rs/close_copy/{user_token}?term={term}&brand={brandname}")]
JsonResponse EndSession(string user_token, string term, string brandname, EndSessionRequest request);

where EndSessionRequest is :

[DataContract]
public class EndSessionRequest
{
    [DataMember]
    public string acc { get; set; }        

    [DataMember]
    public IEnumerable<PageDetails> counters { get; set; }
}

and PageDetails is:

[DataContract]
public class PageDetails
{
    [DataMember]
    public string format { get; set; }
    [DataMember]
    public string ink { get; set; }
    [DataMember]
    public int ctr { get; set; }
    [DataMember]
    public bool duplex { get; set; }
}

The problem with above implementation is, when the counters has one element, request comes to us like:

{"acc":"ramaccnz","counters":{"ctr":"2","duplex":"false","format":"A4","ink":"bw"}}

But as per our implementation, request is expected as:

{"acc":"ramaccnz","counters":[{"ctr":"2","duplex":"false","format":"A4","ink":"bw"}]} 

In other cases, when request has multiple elements, our service work as expected.

Is there a way to handle this in WCF implementation?


Solution

  • I was able to do it by getting the request string in JSON format using OperationContext, and then handling the request manually by using DataContractJsonSerializer. Below is my code snippet:

    [DataContract]
    public class EndSessionRequestMany
    {
        [DataMember]
        public string acc { get; set; }
        [DataMember]
        public List<PageDetails> counters { get; set; }
    }
    
    public JsonResponse EndSession(string user_token, string term, string brandname)
    {
        string JSONstring = OperationContext.Current.RequestContext.RequestMessage.ToString();
    
        XmlReader reader = XmlReader.Create(new StringReader(JSONstring));
        EndSessionRequestMany objEndSessionMany = (EndSessionRequestMany)new DataContractJsonSerializer(typeof(EndSessionRequestMany)).ReadObject(reader);
    }