感谢Alex Zeitler's article我让我的WCF Web API服务接受JSONP请求。使用JSONP将复杂对象发送到WCF Web API
这对于简单的请求非常有效,但我遇到了问题。
我需要能够访问的函数之一是一个搜索函数,它通过http post发送一个复杂的对象。很明显,我不能通过JSONP发布,所以我想着如何将其转换为get请求。
现有函数看起来像:
[WebInvoke(UriTemplate = "", Method = "POST")]
public HttpResponseMessage<List<Models.Payload>> FindPayloads(Models.AimiRequest requestValues)
{
// do stuff here
return new HttpResponseMessage<List<searchResult>>(results);
}
其在被定义为被传递的请求对象如下:
public class AimiRequest
{
public MetadataQueryParameter[] Metadata { get; set; }
public string ContentType { get; set; }
public string RuleTypes { get; set; }
}
public class MetadataQueryParameter
{
public string Name { get; set; }
public string Value { get; set; }
}
棘手的部分是有元数据参数和未知数量名称和价值未提前知道。
我试着简单地连载的对象为字符串,并通过这一点,但该服务将抛出一个400错误请求(从客户端(:)检测到有潜在危险的Request的值。)
任何人在有什么好的想法?
编辑:脏黑客警报!
好的,我有一个工作功能,但我不喜欢它。必须有一种方法可以实现这一点,而不必手动将数据从查询字符串中提取出来并自行解码。
的客户端脚本(记住,这是测试代码不生产)
function findPayload() {
var paramName = $("#ddlMetaType option:selected").val();
var paramValue = $("#txtValue").val();
// build query object
var AimiRequest = new Object();
AimiRequest.ContentType = null;
AimiRequest.RuleTypes = null;
var MetadataQueryParameter = new Object();
MetadataQueryParameter.Name = paramName;
MetadataQueryParameter.Value = paramValue;
AimiRequest.Metadata = new Array();
AimiRequest.Metadata.push(MetadataQueryParameter);
// NB. In production there may be multiple params to push into the array.
// send query to service
$.ajax({
cache: false,
contentType: "application/json",
data: {},
dataType: "jsonp",
error: function (xhr, textStatus, errorThrown) {
switch (xhr.status) {
case 404:
displayNotFound();
break;
default:
alert(xhr.status);
break;
}
},
success: function (response) {
var resultsPane = $("#resultsPane");
$(resultsPane).empty();
$("#payloadTemplate").tmpl(response).appendTo(resultsPane);
},
type: "GET",
url: "http://localhost:63908/search/json?data=" + encodeURIComponent(JSON.stringify(AimiRequest))
});
}
和接收它的服务器端功能:
[ServiceContract]
public class SearchResource
{
private IPayloadService _payloadService;
public SearchResource(IPayloadService pService)
{
this._payloadService = pService;
}
[WebGet(UriTemplate = "")]
public HttpResponseMessage<List<Payload>> Search()
{
// find input in querystring
var qString = HttpContext.Current.Request.QueryString["data"];
// Unencode it
var unenc = HttpUtility.UrlDecode(qString);
// deserialise back to the object
var jsSerialiser = new System.Web.Script.Serialization.JavaScriptSerializer();
var myObj = jsSerialiser.Deserialize<AimiRequest>(unenc);
// do search
var metadataParams = new List<KeyValuePair<string, string>>();
foreach (MetadataQueryParameter param in myObj.Metadata)
{
metadataParams.Add(new KeyValuePair<string, string>(param.Name, param.Value));
}
List<Data.Payload> data = _payloadService.FindPayloads(metadataParams, myObj.ContentType, myObj.RuleTypes);
// Map to "viewmodel"
var retVal = AutoMapper.Mapper.Map<List<Data.Payload>, List<Payload>>(data);
// return results
return new HttpResponseMessage<List<Payload>>(retVal);
}
}
你如何序列化AimiRequest对象(我假设发出GET的客户端将是一个普通的浏览器)? XML中的XML将被ASP.NET管道拒绝(如果在ASP.NET上托管而不是自托管)。 –
我在使用JSON2插件中的JSON.stringify()函数进行序列化。是的,进行GET的客户端是浏览器中的jquery ajax调用。 – Nick