代码之家  ›  专栏  ›  技术社区  ›  Bullines

向Web服务传递多个参数时出现的问题

  •  2
  • Bullines  · 技术社区  · 14 年前

    我有一个简单的Web服务方法定义为:

    [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!\"}";
    }
    

    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!');
        }
    });
    

    但是,这会产生以下错误(永远不会命中MyWebMethod()中第一行的断点):

    为类型定义的构造函数 \u0027System.String\u0027.,“StackTrace”: System.Web.Script.Serialization.ObjectConverter.ConvertDictionaryToObject(IDictionary 2 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(IDictionary rawParams\r\n在 System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext 上下文,WebServiceMethodData rawParams\r\n在 System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext methodData)“,”异常类型“:”System.MissingMethodException“}

    我想传入两个字符串参数,并使用DataContractJsonSerializer来编写新的Foo和Bar对象。我遗漏了什么吗?

    5 回复  |  直到 14 年前
        1
  •  2
  •   Zhao    12 年前

    对于服务中的代码,需要为“foo”和“bar”使用对象而不是字符串。然后使用Newtonsoft.Json的函数解析将此对象转换为Json对象,然后构建强类型对象。

    [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"];
        }
    }
    
        2
  •  1
  •   Lee    13 年前

    我知道这是一个什么样的旧线程,但添加评论/洞察可能会有帮助(不仅对OP,但对其他人谁找到这个线程寻找答案)。

    OP声明他的服务器端webmethod接收两个字符串foo和bar。他的客户端jquery.ajax(…)调用在对象({foo:…,bar:…)中创建他的两个参数。。。})正确的JSON.stringify就是这个对象。问题似乎是客户端、foo和bar本身就是具有两个属性(名称和年龄)的foo和具有三个属性(颜色、大小和数量)的bar的对象。然而,服务器端webmethod希望其foo和bar参数是字符串,而不是对象。我认为解决这个问题的正确方法是创建Foo和Bar类服务器端,让服务器端webmethod接收Foo和Bar作为Foo和Bar对象,而不是字符串。类似于:

    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!\"}";
    }
    

        3
  •  0
  •   VinayC    14 年前

    服务方法的签名不应该是

    public string MyWebMethod(Foo foo, Bar bar)
    

    当然,据我所知,ASMX服务使用JavaScriptSerializer。您应该将WCF服务与webHttpBinding一起使用DataContractJsonSerializer。

        4
  •  0
  •   SquidScareMe    14 年前

    我知道这听起来很疯狂,但是尝试将web方法的响应格式设置为XML(response format.XML)。不知为什么这对我有效。

        5
  •  0
  •   khaled    14 年前

    您需要在json字符串中构造一个“request”元素,然后在不使用json.stringify的情况下将其传递给data元素。参见代码。

    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!');
        }
    });