WCF REST: What is it expecting my XML to look like in requests?
Asked Answered
B

2

6

I have the following method in my WCF service:

[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)]
public int GetOne(string param1, string param2)
{
    return 1;
}

I am sending xml from a Flex application, and it takes an object that looks like this: { param1: "test", param2: "test2" } and turns it into the following request:

POST http://localhost:8012/MyService.svc/GetOne HTTP/1.1
Accept: application/xml
Accept-Language: en-US
x-flash-version: 10,1,53,64
Content-Type: application/xml
Content-Length: 52
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Host: localhost:8012
Connection: Keep-Alive
Pragma: no-cache
Cookie: ASP.NET_SessionId=drsynacw0ignepk4ya4pou23

<param1>something</param1><param2>something</param2>

I get the error The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml', 'Json'.. Everything I've read indicates that I just need the content-type to be application/xml, but it still thinks it's Raw for some reason. Given my method signature, I'm confused as to what it's expecting and how I need to form the request so it will accept it as XML.

Am I missing something obvious here? Why does it think it's RAW when it's specifying XML and providing XML?

Edit - Here's the Flex side in case I'm missing something here.

var getOneService:HttpService = new HttpService("myURL");

getOneService.method = "POST";
getOneService.resultFormat = "e4x";
getOneService.contentType = HTTPService.CONTENT_TYPE_XML;
getOneService.headers = { Accept: "application/xml" };

getOneService.send({ param1: "test", param2: "test2" });
Boson answered 11/7, 2012 at 18:46 Comment(6)
you set the response format to xml and you are taking input in JSON format as { param1: "test", param2: "test2" } ? is this oKPerez
I was also going to point out that this '{ param1: "test", param2: "test2" ' was not XML format that you claim to be sending your data in. Providing your Flex code that you use to call the service may help here.Battles
@WaqarJanjua: That's the Flex object notation. It gets serialized to the XML you see in the request I posted.Boson
ok, 1 question, the method GetOne returns an integer but you set Method="POST" in the webinvoke attribute ? It should not be Get ?Perez
@www.Flextras.com: Posted the service call, but even when messing with the request in Fiddler I'm unable to get it to recognize it as XML.Boson
Is it possible to change the definition of the REST WCF Service or do you need to get it working with the existing def.Dalton
D
4

I don't think you can pass 2 parameters with a POST operation for the framework to deserialize it automatically. You have try some of the below approaches:

  1. Define your WCF method to be as below:

    [OperationContract]
    [WebInvoke(Method = "POST", 
        BodyStyle = WebMessageBodyStyle.Bare, 
        ResponseFormat = WebMessageFormat.Xml, 
        RequestFormat = WebMessageFormat.Xml, 
        URITemplate="/GetOne/{param1}")]
    public int GetOne(string param1, string param2)
    {
        return 1;
    }
    

    Your raw POST request would looks like as below:

    POST http://localhost/SampleService/RestService/ValidateUser/myparam1 HTTP/1.1
    User-Agent: Fiddler
    Content-Type: application/xml
    Host: localhost
    Content-Length: 86
    
    <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">my param2</string>
    
  2. Change your WCF REST method to be as below:

    [OperationContract]
    [WebInvoke(Method = "POST", 
        BodyStyle = WebMessageBodyStyle.WrappedRequest, 
        ResponseFormat = WebMessageFormat.Json, 
        RequestFormat = WebMessageFormat.Json)]
    public int GetOne(string param1, string param2)
    {
        return 1;
    }
    

    Now your raw request should looks something like below:

    POST http://localhost/SampleService/RestService/ValidateUser HTTP/1.1
    User-Agent: Fiddler
    Content-Type: application/json
    Host: localhost
    Content-Length: 86
    
    {"param1":"my param1","param2":"my param 2"}
    
  3. Change your WCF REST method to be as below:

    [OperationContract]
    [WebInvoke(Method="POST", 
        BodyStyle=WebMessageBodyStyle.WrappedRequest, 
        ResponseFormat=WebMessageFormat.Xml, 
        RequestFormat= WebMessageFormat.Xml)]
    public int GetOne(string param1, string param2)
    {
       return 1;
    }
    

    Now your raw request would look like something below:

    POST http://localhost/SampleService/RestService/ValidateUser HTTP/1.1
    User-Agent: Fiddler
    Content-Type: application/xml
    Host: localhost
    Content-Length: 116
    
    <ValidateUser xmlns="http://tempuri.org/"><Username>my param1</Username><Password>myparam2</Password></ValidateUser>
    
Dalton answered 12/7, 2012 at 8:48 Comment(1)
Your last suggestion ended up being what I went with. I just had to write something on the Flex side to always wrap the parameters with the method name before doing the final request. Thanks!Boson
S
1

Valid XML must have a single root element. Also there's no magic in WCF REST that maps XML elements to string parameters. You could take an XElement as your operation parameter.

[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)]
public int GetOne(XElement content)
{
    string param1 = content.Elements().First(element => element.Name == "param1").Value;
    string param2 = content.Elements().First(element => element.Name == "param2").Value;

    return 1;
}

The data you send would be something like:

<parameters>
    <param1>something</param1>
    <param2>something</param2>
</parameters>
Spunky answered 11/7, 2012 at 22:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.