开发者

WCF Rest parameters involving complex types

开发者 https://www.devze.com 2022-12-10 21:10 出处:网络
Setting up a WCF service that uses the webHttpBinding... I can return complex types from the method as XML ok.How do I take in a complex type as a parameter?

Setting up a WCF service that uses the webHttpBinding... I can return complex types from the method as XML ok. How do I take in a complex type as a parameter?

[ServiceContract(Name = "TestService", Namespace = "http://www.test.com/2009/11")]
public interface ITestService
{
    [OperationContract]
    [WebInvoke(Method = "POST", 
               BodyStyle = WebMessageBodyStyle.Bare, 
               UriTemplate = "/Person/{customerAccountN开发者_如何转开发umber}, {userName}, {password}, {PersonCriteria}")]
    Person SubmitPersonCriteria(string customerAccountNumber, 
                                string userName, 
                                string password, 
                                PersonCriteria details);
}

Since the UriTemplate only allows strings, what's the best practice? The idea is the client app will post a request to the service like search criteria for a person. The service will respond with the appropriate object containing the data as XML.


You can post complex types using rest.

[ServiceContract]
public interface ICustomerSpecialOrderService
{    
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "deletecso/")]
    bool DeleteCustomerOrder(CustomerSpecialOrder orderToDelete);
}

The implementation looks like this:

public bool DeleteCustomerOrder(CustomerSpecialOrder orderToDelete)
{
    // Do something to delete the order here.
}

You can call a method from a WPF client:

public void DeleteMyOrder(CustomerSpecialOrder toDelete)
{
    Uri address = new Uri(your_uri_here);
    var factory = new WebChannelFactory<ICustomerSpecialOrderService>(address);
    var webHttpBinding = factory.Endpoint.Binding as WebHttpBinding;
    ICustomerSpecialOrderService service = factory.CreateChannel();
    service.DeleteCustomerOrder(toDelete);
}

Or you can call it with a HttpWebRequest as well, writing the complex type to a byte array which we do from a mobile client.

private HttpWebRequest DoInvokeRequest<T>(string uri, string method, T requestBody)
{
    string destinationUrl = _baseUrl + uri;
    var invokeRequest = WebRequest.Create(destinationUrl) as HttpWebRequest;
    if (invokeRequest == null)
        return null;

    // method = "POST" for complex types
    invokeRequest.Method = method;
    invokeRequest.ContentType = "text/xml";

    byte[] requestBodyBytes = ToByteArray(requestBody);
    invokeRequest.ContentLength = requestBodyBytes.Length;


    using (Stream postStream = invokeRequest.GetRequestStream())
        postStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);

    invokeRequest.Timeout = 60000;

    return invokeRequest;
}


Your options:

  1. use POST and accept an XML doc of arbitrary complexity, or
  2. use GET and figure a way to map a URL path to your query criterion.

I'd recommend the former, it feels more RESTful and less hacky. The POST would be to submit a query, and in response you'd get a queryId, something relating to what you've submitted.

According to REST ideas, you can then to a get on that ID to get the results of the query.


You can pass a JSON string or XML format data as input body in the REST service call and mention the same in the service contract definition. Then it will allow you to pass an object as input in the REST service call.

0

精彩评论

暂无评论...
验证码 换一张
取 消