Omu*_*Omu 3 asp.net wcf jquery asp.net-ajax
我的js代码:
var a = ["asdfa", "asdfa", "aaa"];
var data = [];
for (var i in a) data.push({ name: 'keys', value: a[i] });
$.post('<%=ResolveUrl("~/svc/aja.svc/GetMultiple") %>', $.param(data), function(d) {
//do stuff
});
Run Code Online (Sandbox Code Playgroud)
我的ajax启用了wcf
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Aja
{
[WebInvoke(Method="POST")]
[OperationContract]
public IEnumerable<IdContent> GetMultiple(string[] keys)
{
return keys.Select(o => new IdContent { Id = o, Content = o + o });
}
Run Code Online (Sandbox Code Playgroud)
我试过调试,方法GetMultiple
没有被击中,(我得到错误500)
如果我这样做是通过发送一个简单的字符串而不是数组,而不是它的作用
这是我在firebug中得到的消息:
{"ExceptionDetail":{"HELPLINK":空"的InnerException":空,"消息":"传入消息具有意想不到的消息格式的'原始’用于操作的期望的消息格式是'XML’;'的Json’. .这可能是因为一个WebContentTypeMapper尚未在所述结合构造,请参阅WebContentTypeMapper的文档了解更多信息""堆栈跟踪.":"在System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(消息信息,对象[]参数) \在System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest u000d\u000a(消息信息,对象[]参数)\ u000d\u000a在System.ServiceModel.Dispatcher.CompositeDispatchFormatter.DeserializeRequest(消息信息,对象[]参数)\ u000d\u000a在System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc&RPC)\ u000d\u000a在System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&RPC)\ u000d\u000a在System.ServiceModel.Dispatch 在System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)的System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&rpc)\ u000d\u000a中的er.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&rpc)\ u000d\u000a","Type" :"System.InvalidOperationException"},"ExceptionType":"System.InvalidOperationException","Message":"传入的消息具有意外的消息格式'Raw'.该操作的预期消息格式是'Xml'; 'Json的'.这可能是因为尚未在绑定上配置WebContentTypeMapper.有关更多详细信息,请参阅WebContentTypeMapper的文档.","StackTrace":"在System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(消息消息,Object []参数)\ u000d\u000a at System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(消息的消息,对象[]参数)\ u000d\u000a在System.ServiceModel.Dispatcher.CompositeDispatchFormatter.DeserializeRequest(消息信息,对象[]参数)\ u000d\u000a在System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc&RPC)\ u000d\u000a at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&rpc)\ u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&rpc)\ u000d\u000a at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4( MessageRpc&rpc)\ u000d\u000a at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)"}
您遇到的问题:$ .post发送以application/x-www-form-urlencoded编码的数据,WCF本身不支持此格式.这就是问题所在.
现在寻求解决方案:与WCF一样,您可以做很多事情:
1)更改客户端以发送服务可以理解的格式.WCF理解JSON,因此您可以使用JSON字符串(即来自Crockford实现的 json2.js中的JSON.stringify).有了这个,您需要更改代码以使用$ .ajax而不是"快捷方式"$ .post:
$.ajax({
type: "POST",
url: '<%=ResolveUrl("~/svc/aja.svc/GetMultiple") %>',
contentType: "application/json",
data: JSON.stringify({ keys: a }),
success: function (result) {
alert(result);
}
});
Run Code Online (Sandbox Code Playgroud)
2) "教" WCF如何理解为$ .params(或$ .post的)调用本机格式.有两种方法可以做到这一点:
2.1) "手工"做.这不是很微不足道,但可以做到.您需要一个IDispatchMessageFormatter
可以从表单/编码转换string[]
为您的操作的参数.然后,您需要一种行为来挂接这种新格式,以及新服务主机工厂(通过代码挂钩行为)或行为配置扩展(如果您想在配置中执行此操作).以下链接用于更详细地解释消息格式化程序,端点行为,服务主机工厂和行为配置扩展的帖子.下面的代码显示了调度格式化程序的一种可能实现,它知道如何处理字符串数组.
public class AjaServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new AjaServiceHost(serviceType, baseAddresses);
}
public class AjaServiceHost : ServiceHost
{
public AjaServiceHost(Type serviceType, Uri[] baseAddresses)
: base(serviceType, baseAddresses) { }
protected override void OnOpening()
{
base.OnOpening();
ServiceEndpoint endpoint = this.AddServiceEndpoint(typeof(Aja), new WebHttpBinding(), "");
endpoint.Behaviors.Add(new WebScriptEnablingBehavior());
endpoint.Behaviors.Add(new MyFormsUrlEncodedAwareBehavior());
}
}
}
class MyFormsUrlEncodedAwareBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
foreach (var operation in endpoint.Contract.Operations)
{
var dispatchOperation = endpointDispatcher.DispatchRuntime.Operations[operation.Name];
dispatchOperation.Formatter = new MyFormsUrlEncodedAwareFormatter(operation, dispatchOperation.Formatter);
}
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
class MyFormsUrlEncodedAwareFormatter : IDispatchMessageFormatter
{
private OperationDescription operationDescription;
private IDispatchMessageFormatter originalFormatter;
public MyFormsUrlEncodedAwareFormatter(OperationDescription operationDescription, IDispatchMessageFormatter originalFormatter)
{
this.operationDescription = operationDescription;
this.originalFormatter = originalFormatter;
}
public void DeserializeRequest(Message message, object[] parameters)
{
if (message.Properties.ContainsKey(WebBodyFormatMessageProperty.Name))
{
var bodyFormat = (WebBodyFormatMessageProperty)message.Properties[WebBodyFormatMessageProperty.Name];
if (bodyFormat.Format == WebContentFormat.Raw)
{
if (message.Properties.ContainsKey(HttpRequestMessageProperty.Name))
{
var httpReq = (HttpRequestMessageProperty)message.Properties[HttpRequestMessageProperty.Name];
if (httpReq.Headers[HttpRequestHeader.ContentType] == "application/x-www-form-urlencoded")
{
var requestBodyParts = operationDescription.Messages[0].Body.Parts;
if (requestBodyParts.Count == 1 && requestBodyParts[0].Type == typeof(string[]))
{
string body = GetRawMessageBodyAsString(message);
NameValueCollection pairs = HttpUtility.ParseQueryString(body);
parameters[0] = pairs.GetValues(requestBodyParts[0].Name);
return;
}
}
}
}
}
this.originalFormatter.DeserializeRequest(message, parameters);
}
private string GetRawMessageBodyAsString(Message message)
{
XmlDictionaryReader reader = message.GetReaderAtBodyContents();
reader.ReadStartElement("Binary");
byte[] bytes = reader.ReadContentAsBase64();
return Encoding.UTF8.GetString(bytes);
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
return this.originalFormatter.SerializeReply(messageVersion, parameters, result);
}
}
Run Code Online (Sandbox Code Playgroud)
2.2)使用http://wcf.codeplex.com上发布的新的"jQuery支持WCF" .这些是一些行为/格式化程序,它们增加了对表单/ urlencoded请求的支持.但是您需要更改操作以无类型方式接收数据(即,作为a JsonArray
),并且在代码中您自己枚举项目.
归档时间: |
|
查看次数: |
5803 次 |
最近记录: |