1

我有以下 Javascript:

 $.ajax({
    url: "/Web/WebServices/Operation.svc/SetScope",
    type: "POST",
    contentType: "application/json; charset=utf-8",
    beforeSend: function () {
    },
    dataType: "json",
    cache: false,
    data: JSON.stringify({
        Id: Id,
        RIds: RIds,
        rScope: rScope 
    }),
    success: function (data) { onSuccess(data); },
    error: function (data) { onError(data); }
    });

如果你看一下数据位——

  • Id 是一个整数
  • RIds 是整数数组
  • rScope 是一个对象数组,每个对象都包含一个 int 和一个字符串

的结果

data: JSON.stringify({
            Id: Id,
            RIds: RIds,
            rScope: rScope 
        })

'{"Id":1,"rIds":[1,2,3,4],"rScope":[{"id":3,"type":"barney"},{"id":2, “类型”:“ted”}]}'

将其传递给$.parseJSON返回预期的对象。

问题是它返回 400 Bad Request。

等待调用的签名在 IIS 中托管的 WCF 中

public OperationResult SetScope(int rId, string rIds, string rScope)

如果我从代码中删除 rScope,一切都很好,但它似乎在填充对象而不是原语的数组时遇到问题。

我在这里想念什么?

我发现了类似的问题,但没有一个能够真正解释我的情况。

4

2 回答 2

1

如果我没记错的话,你的解析结果暗示这rScope是一个对象数组,每个对象都有一个id和一个type属性,而不仅仅是一个简单的字符串。

"rScope":[{"id":3,"type":"barney"},{"id":2,"nodetype":"ted"}]

如果您有类似的课程:

public class ScopeClass{
    public int Id {get; set;}
    public string Type {get; set;}
}

并在您的方法中使用它,如下所示:

public OperationResult SetScope(int rId, string rIds, IList<ScopeClass> rScope)

编辑

实际上,我刚刚注意到您还有第二个对象nodetype,而不是类型。

如果您使用上述方法,您需要确保在您传递的数据中,节点类型也被命名为类型,否则您无法匹配这些值。

此外,Type由于 C# 的Type. 如果您有任何影响,您可以更新Type为更有意义的内容,例如GroupType它所代表的内容,然后在传递的数据中将其命名为相同的名称。然后模型绑定器应该简单地对其进行魔术匹配。

于 2012-11-26T23:48:34.213 回答
1

您的操作需要一个字符串作为rIds参数,但您将一个数组传递给它。有一些转换是自动发生的,但只有非常简单的转换(例如数字到字符串)。此外, rScope 需要一个字符串,但您正在将一个对象传递给它。

您可以做几件事。第一种是将数据作为字符串而不是作为它们的“正常”类型传递——这意味着对RIdsrScope参数进行字符串化:

var data = JSON.stringify({
    Id: Id,
    rIds: JSON.stringify(RIds),
    rScope: JSON.stringify(rScope)
});
$.ajax({
   url: "/Web/WebServices/Operation.svc/SetScope",
   type: "POST",
   contentType: "application/json; charset=utf-8",
   beforeSend: function () { },
   dataType: "json",
   cache: false,
   data: data,
   success: function (data) { onSuccess(data); },
   error: function (data) { onError(data); }
});

另一种选择与 François Wahl 提到的一致,即制作将接收您发送的数据的类型。您需要为rIdsrScope参数执行此操作:

public class StackOverflow_13575100
{
    [ServiceContract]
    public class Service
    {
        [WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped)]
        public string SetScope(int rId, string rIds, string rScope)
        {
            return string.Format("{0} - {1} - {2}", rId, rIds, rScope);
        }
        [WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]
        public string SetScopeTyped(int rId, int[] rIds, ScopeClass[] rScope)
        {
            return string.Format("{0} - {1} - {2}",
                rId,
                "[" + string.Join(", ", rIds) + "]",
                "[" + string.Join(", ", rScope.Select(s => s.ToString())) + "]");
        }
    }
    [DataContract]
    public class ScopeClass
    {
        [DataMember(Name = "id")]
        public int Id { get; set; }
        [DataMember(Name = "type")]
        public string Type { get; set; }

        public override string ToString()
        {
            return string.Format("Scope[Id={0},Type={1}]", Id, Type);
        }
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
        host.Open();
        Console.WriteLine("Host opened");

        WebClient c = new WebClient();
        c.Headers[HttpRequestHeader.ContentType] = "application/json";
        string data = @"{""Id"":1,""rIds"":[1,2,3,4],""rScope"":[{""id"":3,""type"":""barney""},{""id"":2,""type"":""ted""}]}";
        Console.WriteLine(data);
        try
        {
            Console.WriteLine(c.UploadString(baseAddress + "/SetScope", data));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }

        c.Headers[HttpRequestHeader.ContentType] = "application/json";
        Console.WriteLine(c.UploadString(baseAddress + "/SetScopeTyped", data));

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
于 2012-11-27T00:03:40.267 回答