Bullines
Bullines

Reputation: 5696

Problems Passing Multiple Parameters to Web Service

I have a simple Web Service method defined as:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string MyWebMethod(string foo, string bar)
{
    // DataContractJsonSerializer to deserialize foo and bar to
    //  their respective FooClass and BarClass objects.

    return "{\"Message\":\"Everything is a-ok!\"}";
}

I'll call it from the client via:

var myParams = { "foo":{"name":"Bob Smith", "age":50},"bar":{"color":"blue","size":"large","quantity":2} };

$.ajax({
    type: 'POST',
    url: 'https://mydomain.com/WebServices/TestSvc.asmx/MyWebMethod',
    data: JSON.stringify(myParams),
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function (response, status) {
        alert('Yay!');
    },
    error: function (xhr, err) {
        alert('Boo-urns!');
    }
});

However, this yields the following error (a breakpoint on the first line in MyWebMethod() is never hit):

{"Message":"No parameterless constructor defined for type of \u0027System.String\u0027.","StackTrace":" at System.Web.Script.Serialization.ObjectConverter.ConvertDictionaryToObject(IDictionary2 dictionary, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject)\r\n at System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeInternal(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject)\r\n at System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeMain(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject)\r\n at System.Web.Script.Services.WebServiceMethodData.StrongTypeParameters(IDictionary2 rawParams)\r\n at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary`2 rawParams)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.MissingMethodException"}

I'd like to pass in two string parameters and use DataContractJsonSerializer to write new Foo and Bar objects. Am I missing something?

Upvotes: 3

Views: 4485

Answers (5)

Zhao
Zhao

Reputation: 924

For the code in the service, you need to use object instead of string for "foo" and "bar". And then use Newtonsoft.Json's function to parse convert this object to Json object and then build the strong typed object.

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string MyWebMethod(object foo, object bar)
{
    // DataContractJsonSerializer to deserialize foo and bar to
    //  their respective FooClass and BarClass objects.

    //parse object to JObject using NewtonJson
    JObject jsonFoo = JObject.Parse(JsonConvert.SerializeObject(foo));
    JObject jsonBar = JObject.Parse(JsonConvert.SerializeObject(bar));
    Foo fo = new Foo(jsonFoo);
    Bar ba = new Bar(jsonBar);

    return "{\"Message\":\"Everything is a-ok!\"}";
}
public class Foo{
    public Foo(JObject jsonFoo){
        if (json["prop1"] != null) prop1= json["prop1"].Value<long>();
        if (json["prop2"] != null) prop2= (string)json["prop2"];
        if (json["prop3"] != null) prop3= (string)json["prop3"];
    }
}

Upvotes: 2

Lee
Lee

Reputation: 493

I know this is a some what old thread, but addition comments/insight can be helpful (not only to the OP, but to others who find this thread looking for answers).

The OP states that his server-side webmethod receives two strings, foo and bar. His client-side jquery .ajax(...) call creates his two parameters in an object ( { foo: ..., bar: ... } ) and properly JSON.stringify's that object. The problem seems to be that client side, foo and bar are objects themselves with foo having two properties (name and age) and bar having three properties (color, size and quantity). Yet the server-side webmethod is expecting its foo and bar parameters to be strings, not objects. I believe the correct way to resolve this is to create Foo and Bar classes server side and have the server-side webmethod recieve foo and bar as Foo and Bar objects instead of strings. Something like:

public enum Sizes
{
    Small = 1,
    Medium = 2,
    Large = 3
}

public class Foo
{
    public string name { get; set; }
    public int age { get; set; } 
}

public class Boo
{
    public string color { get; set; }
    public Sizes size { get; set; } 
    public int quantity { get; set; } 
}

...

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string MyWebMethod(Foo foo, Bar bar)
{
    // foo and bar will already BE deserialized as long as their signatures
    // are compatible between their client-side and server-side representations.
    // Bar.size as an enum here server-side should even work with its
    // client-side representation being a string as long the string contains
    // the name of one of the Sizes enum elements.

    return "{\"Message\":\"Everything is a-ok!\"}";
}

Disclaimer: I typed that code from scratch, so there may be some type-o's. :)

Upvotes: 1

khaled
khaled

Reputation: 122

you need to formulate a "request" element in your json string, then just pass it to data element without using JSON.stringify. See code.

var myParams = "{request: \'{\"foo\":{\"name\":\"Bob Smith\", \"age\":50},\"bar\":{\"color\":\"blue\",\"size\":\"large\",\"quantity\":2}}\' }";

$.ajax({
    type: 'POST',
    url: 'https://mydomain.com/WebServices/TestSvc.asmx/MyWebMethod',
    data: myParams,
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function (response, status) {
        alert('Yay!');
    },
    error: function (xhr, err) {
        alert('Boo-urns!');
    }
});

Upvotes: 0

SquidScareMe
SquidScareMe

Reputation: 3218

I know this sounds nuts but try setting your web method's response format to XML (ResponseFormat.Xml). For some reason this worked for me.

Upvotes: 0

VinayC
VinayC

Reputation: 49185

Shouldn't the signature of your service method be something like

public string MyWebMethod(Foo foo, Bar bar)

But of course, as I understand, ASMX service uses JavaScriptSerializer. You should use WCF service with webHttpBinding to use DataContractJsonSerializer.

Upvotes: 0

Related Questions