我有以下的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,"type":"ted"}]}'
将其传递到$.parseJSON
将返回预期的对象。
问题是它返回 400 错误请求。
等待调用的签名位于 IIS 中承载的 WCF 中
public OperationResult SetScope(int rId, string rIds, string rScope)
如果我从代码中删除 rScope,一切都很好,但它似乎在填充对象而不仅仅是基元的数组中遇到了问题。
我在这里错过了什么?
我发现了类似的问题,但没有一个能真正解释我的情况。
没记错的话,您的解析结果意味着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
的对象而不是类型。
如果你使用上面的aproach,你需要确保在你的数据中传递的nodetype也被命名为type,否则你无法匹配这些值。
此外,由于 C# 的Type
类型,使用属性名称 Type
可能不是一个好主意。如果你有任何影响力,你可以Type
更新为更有意义的东西,比如GroupType
或它所代表的东西,然后在传递的数据中将其命名为相同。然后,模型活页夹应该简单地魔术匹配它。
您的操作需要 rIds
参数的字符串,但您正在向其传递一个数组。有一些转换会自动发生,但只是非常简单的转换(例如数字到字符串)。此外,rScope 需要一个字符串,但您正在向其传递一个对象。
您可以做一些事情。第一种是将数据作为字符串传递,而不是作为它们的"正常"类型 - 这意味着将RIds
和rScope
参数字符串化:
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提到的一致,即制作接收您发送的数据的类型。您需要为rIds
和rScope
参数执行此操作:
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();
}
}