سؤال

How can I get a web service method to access parameters in the URI and complex POST data?

I have a web service method with some parameters in the URI:

"/api/{something}/{id}"

I also have a class marked with DataContract/Member attributes that I want the webservice method to accept. Note that my class contains a subclass also marked with DataContract/Member attributes.

[DataContract]
public class MoreData{
    [DataMember]
    public string SomeString { get; set; }

    [DataMember]
    public SubClass SubData {get; set;}
}

My method declaration looks like:

[OperationContract]
[WebInvoke( Method = "POST", UriTemplate = "/api/{something}/{id}")]
public MyWebSvcRetObj Update(string something, string id)

How would I get my Update method to also accept the MoreData class? I've been able to write methods like:

[OperationContract]
[WebInvoke( Method = "POST")]
public MyWebSvcRetObj Update(MoreData IncomingData)

but only if the URI did not specify any parameters, and the URI would look like

"api/Update"

Ultimately I want my users to be able to something like:

$.ajax({
    url: 'localhost/site/api/things/12345
    type: 'POST'
    data: {
        SomeString: 'I am a string'
        SubData: {
           //...more data
        }
    }
});

I have tried putting a Stream as the final parameter in the Update method, but that doesn't seem to work for classes that have subclasses like the example I gave. It ends up having key/value pairs like "SubData[SomeSubDataProp]" : "Val". That seems wrong to me. I've also tried adding a MoreData parameter as the final param in the Update method, but I get an error that says it was expecting a stream (because it's expecting raw data). Is what I am trying to do possible? Or perhaps I am going about this the wrong way?

UPDATE

As Faizan Mubasher wrote, my users will be able to send post data if my web method looks like:

[OperationContract]
    [WebInvoke( Method = "POST", 
        UriTemplate = "/v1/{something}/{id}",
        RequestFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare
    )]
    [Description( "Update " )]
    public void Update( MoreData Incoming, string something, string id )

With the client looking like:

$.ajax({
    type: 'POST',
    url: 'http://localhost/app/api/something/12345',
    contentType: 'application/json',                  //need to specify type
    data: JSON.stringify({                            //note the "stringify" call
        SomeString: 'hello, world',
        SubClass: {
            SubStr: 'hello, again',
            SubInt: 98765
        }
    }
});
هل كانت مفيدة؟

المحلول

You want to keep same URI for both, GET and POST.

  1. When a GET method is called with parameters /api/{something}/{id}, then based on the id, it will return data to client that he/she can edit.

  2. When editing is done, send that edited data back to server using POST method with same URI and Id as mentioned in GET request.

If it is so, then here is the solution:

To do so, create two methods with same UriTemplate but with different names.

[ServiceContract]
public interface IMyWebSvc
{

    [OperationContract]
    [WebGet(UriTemplate = "/api/{something}/{id}",
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare)]
    MyWebSvcRetObj GetData(string something, string id);

    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "/api/{something}/{id}",
        RequestFormat = WebMessageFormat.Json,    
        BodyStyle = WebMessageBodyStyle.Bare)]
    string Update(MoreData IncomingData, string something, string id);       
}

Now, what should be the format of JSON. It is easy. In your MoreData class, override the ToString() method.

public override string ToString()
{
    JavaScriptSerializer js = new JavaScriptSerializer();
    return js.Serialize(this);
}

The JavaScriptSerializer is available in System.Web.Script.Serialization. Now, to check which JSON format your service will accept, make a dummy call to your web service method and hit a break point on object.ToString() method.

MoreData md = new MoreData();
string jsonString = md.ToString(); // hit break point here.

When you hit break point, in jsonString variable, you will have json that your service will accept. So, recommend your client to send JSON in that format.

So, you can specify as much as complex types in your MoreData class.

I hope this will help you! Thanks

نصائح أخرى

It looks like you are posting JSON data to your strongly typed webservice method.

This is somewhat tangential to this topic: How to pass strong-typed model as data param to jquery ajax post?

One solution is to accept a Json object (the key-value pairs you mentioned) and deserialize into your MoreData type.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top