Search code examples
wcfputwcf-restinternal-server-error

Restful WCF with PUT operation when using JSON (server error 400)


Have created a Restful WCF service with webHTTPBinding

While consuming the service in my client application, am facing with this error

The remote server returned an error: (400) Bad Request. (Have already tried solution like setting maxReceivedMessageSize and others mentioned online)

Scenario :

2 methods in client side

1) Working fine ** GET request**

private static void GenerateGETRequest()
{
            HttpWebRequest GETRequest = (HttpWebRequest)WebRequest.Create(url);
            GETRequest.Method = "GET";
            GETRequest.ContentType = "application/json"; 

            Console.WriteLine("Sending GET Request");

            HttpWebResponse GETResponse = (HttpWebResponse)GETRequest.GetResponse();
            Stream GETResponseStream = GETResponse.GetResponseStream();
            StreamReader sr = new StreamReader(GETResponseStream);

            Console.WriteLine("Response from Restful Service");
            Console.WriteLine(sr.ReadToEnd());
}

2) Exception ****** (PUT request with response)**

private static void GeneratePUTRequest()
{

            byte[] dataByte = CreateJSONObject(Object); //this custom method converts object that I pass to JSON serialized object

            HttpWebRequest PUTRequest = (HttpWebRequest)HttpWebRequest.Create(Url);
            PUTRequest.Method = "PUT";
            **//PUTRequest.ContentType = "application/json"; //error 400 when un-commenting this**
            PUTRequest.ContentLength = dataByte.Length;

            Stream PUTRequestStream = PUTRequest.GetRequestStream();
            PUTRequestStream.Write(dataByte, 0, dataByte.Length);

            **HttpWebResponse PUTResponse = (HttpWebResponse)PUTRequest.GetResponse(); // this is where i get the exception when un-commenting above line**

            Stream PUTResponseStream = PUTResponse.GetResponseStream();
            StreamReader sr = new StreamReader(PUTResponseStream);

            Console.WriteLine("Response from Restful Service");
            Console.WriteLine(sr.ReadToEnd());
}

2 method throws the xception when i un-comment the line mentioned in the comment (in code). The place where exception is thrown is also mentioned in the comment (in code above).

The second method works fine with desired output (if i comment the mentioned line).

Additional resource

[OperationContract]
[WebInvoke(Method = "PUT",
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.Wrapped,
    UriTemplate = "Controller")]

Solution

  • In order to send data through a POST or PUT, you need to construct your data correctly according to the WCF service. Here is basically what you need (Just change the POST to PUT for your application)

    1) WCF Service Interface

    [OperationContract]
    [WebInvoke(Method = "POST",
        UriTemplate = "GetData",
        RequestFormat = WebMessageFormat.Xml,
        BodyStyle = WebMessageBodyStyle.Bare)]
    string GetData(DataRequest parameter);
    

    2) WCF Service Implementation

    public string GetData(DataRequest parameter)
    {
        //Do stuff
        return "your data here";
    }
    

    3) Data Contract in your WCF service (In this case it's DataRequest)

    [DataContract(Namespace = "YourNamespaceHere")]
    public class DataRequest
    {
        [DataMember]
        public string ID{ get; set; }
        [DataMember]
        public string Data{ get; set; }
    }
    

    4) Client sending the data must have the data constructed properly! (C# console app in this case)

    static void Main(string[] args)
    {
        ASCIIEncoding encoding = new ASCIIEncoding();
        string SampleXml = "<DataRequest xmlns=\"YourNamespaceHere\">" +
                                        "<ID>" +
                                        yourIDVariable +
                                        "</ID>" +
                                        "<Data>" +
                                        yourDataVariable +
                                        "</Data>" +
                                    "</DataRequest>";
    
        string postData = SampleXml.ToString();
        byte[] data = encoding.GetBytes(postData);
    
        string url = "http://localhost:62810/MyService.svc/GetData";
    
        string strResult = string.Empty;
    
        // declare httpwebrequet wrt url defined above
        HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(url);
        // set method as post
        webrequest.Method = "POST";
        // set content type
        webrequest.ContentType = "application/xml";
        // set content length
        webrequest.ContentLength = data.Length;
        // get stream data out of webrequest object
        Stream newStream = webrequest.GetRequestStream();
        newStream.Write(data, 0, data.Length);
        newStream.Close();
    
        //Gets the response
        WebResponse response = webrequest.GetResponse();
        //Writes the Response
        Stream responseStream = response.GetResponseStream();
    
        StreamReader sr = new StreamReader(responseStream);
        string s = sr.ReadToEnd();
    
        return s;
    }