asp.net - send array via jQuery to Ajax-enabled WCF -
my js code:
var = ["asdfa", "asdfa", "aaa"]; var data = []; (var in a) data.push({ name: 'keys', value: a[i] }); $.post('<%=resolveurl("~/svc/aja.svc/getmultiple") %>', $.param(data), function(d) { //do stuff });
my ajax enabled 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 }); }
i tried debugging , method getmultiple
doesn't hit,(i error 500)
if sending simple string not array, works
this message result in firebug :
{"exceptiondetail":{"helplink":null,"innerexception":null,"message":"the incoming message has unexpected message format 'raw'. expected message formats operation 'xml'; 'json'. can because webcontenttypemapper has not been configured on binding. see documentation of webcontenttypemapper more details.","stacktrace":" @ system.servicemodel.dispatcher.demultiplexingdispatchmessageformatter.deserializerequest(message message, object[] parameters)\u000d\u000a @ system.servicemodel.dispatcher.uritemplatedispatchformatter.deserializerequest(message message, object[] parameters)\u000d\u000a @ system.servicemodel.dispatcher.compositedispatchformatter.deserializerequest(message message, object[] parameters)\u000d\u000a @ system.servicemodel.dispatcher.dispatchoperationruntime.deserializeinputs(messagerpc& rpc)\u000d\u000a @ system.servicemodel.dispatcher.dispatchoperationruntime.invokebegin(messagerpc& rpc)\u000d\u000a @ system.servicemodel.dispatcher.immutabledispatchruntime.processmessage5(messagerpc& rpc)\u000d\u000a @ system.servicemodel.dispatcher.immutabledispatchruntime.processmessage4(messagerpc& rpc)\u000d\u000a @ system.servicemodel.dispatcher.messagerpc.process(boolean isoperationcontextset)","type":"system.invalidoperationexception"},"exceptiontype":"system.invalidoperationexception","message":"the incoming message has unexpected message format 'raw'. expected message formats operation 'xml'; 'json'. can because webcontenttypemapper has not been configured on binding. see documentation of webcontenttypemapper more details.","stacktrace":" @ system.servicemodel.dispatcher.demultiplexingdispatchmessageformatter.deserializerequest(message message, object[] parameters)\u000d\u000a @ system.servicemodel.dispatcher.uritemplatedispatchformatter.deserializerequest(message message, object[] parameters)\u000d\u000a @ system.servicemodel.dispatcher.compositedispatchformatter.deserializerequest(message message, object[] parameters)\u000d\u000a @ system.servicemodel.dispatcher.dispatchoperationruntime.deserializeinputs(messagerpc& rpc)\u000d\u000a @ system.servicemodel.dispatcher.dispatchoperationruntime.invokebegin(messagerpc& rpc)\u000d\u000a @ system.servicemodel.dispatcher.immutabledispatchruntime.processmessage5(messagerpc& rpc)\u000d\u000a @ system.servicemodel.dispatcher.immutabledispatchruntime.processmessage4(messagerpc& rpc)\u000d\u000a @ system.servicemodel.dispatcher.messagerpc.process(boolean isoperationcontextset)"}
the problem you're having: $.post sends data encoded in application/x-www-form-urlencoded, , format not supported natively wcf. that's issue.
now solutions: case wcf, there quite few things can do:
1) change client side send format service can understand. wcf understands json, can use json stringifier (i.e., json.stringify json2.js crockford's implementation). this, you'd need change code use $.ajax instead of "shortcut" $.post:
$.ajax({ type: "post", url: '<%=resolveurl("~/svc/aja.svc/getmultiple") %>', contenttype: "application/json", data: json.stringify({ keys: }), success: function (result) { alert(result); } });
2) "teach" wcf how understand native format $.params (or $.post) calls. there 2 ways that:
2.1) "by hand". it's not trivial, can done. you'll need idispatchmessageformatter
can convert forms/encoded string[]
parameter operation. you'd need behavior hook new format , either new service host factory (to hook behavior via code) or behavior config extension (if want in config). following links posts explaining in more details message formatters, endpoint behaviors, service host factory , behavior config extensions. code below shows 1 possible implementation dispatch formatter knows how deal string arrays.
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); } }
2.2) use new "jquery support wcf" published on http://wcf.codeplex.com. behaviors / formatters add support forms/urlencoded requests. you'll need change operation receive data in untyped way (i.e., jsonarray
), , in code you'd enumerate items yourself.
Comments
Post a Comment