Using JQGrid with WCF Web Services

I am trying to get data for JQGrid from a WCF web service running from my ASP.NET 2.0 WebForms application. The problem is that the WCF web service expects the data to be formatted as a JSON string, and the JQGrid executes an HTTP message and passes it as Content-Type: application / x-www-form-urlencoded.

Although there are several options for the data format returned by JQGrid (it accepts JSON, XML, and others), there seems to be no way to change the way data is sent to the web service.

So, I'm trying to figure out how to configure the WCF service to accept

Content-Type: application/x-www-form-urlencoded 

but not

 Content-Type:"application/json; charset=utf-8" 

When I ran a test using jQuery to send an Ajax request using url encoding (shown here):

 $.ajax({ type: "POST", url: "../Services/DocLookups.svc/DoWork", data: 'FirstName=Howard&LastName=Pinsley', contentType: "Content-Type: application/x-www-form-urlencoded", dataType: "json", success: function(msg) { alert(msg.d); } }); 

the call fails. Using Fiddler to check traffic, I found the error returned by the server:

 {"ExceptionDetail":{"HelpLink":null,"InnerException":null,"Message": "The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml', 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details."... 

Please note that this code works due to the difference in encoding

 $.ajax({ type: "POST", url: "../Services/DocLookups.svc/DoWork", data: '{"FirstName":"Howard", "LastName":"Pinsley"}', contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { alert(msg.d); } }); 

On the server, the service looks like this:

 [ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] [ServiceBehavior(IncludeExceptionDetailInFaults = true)] public class DocLookups { // Add [WebGet] attribute to use HTTP GET [OperationContract] public string DoWork(string FirstName, string LastName) { return "Your name is " + LastName + ", " + FirstName; } } 

and my web.config contains:

 <system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="DocLookupsAspNetAjaxBehavior"> <enableWebScript /> </behavior> </endpointBehaviors> </behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> <services> <service name="DocLookups"> <endpoint address="" behaviorConfiguration="DocLookupsAspNetAjaxBehavior" binding="webHttpBinding" contract="DocLookups" /> </service> </services> </system.serviceModel> 

Thanks for any help!

+4
source share
1 answer

If you don't have control over your ajax call, I would recommend create and Interceptor override the Content-Type header.

 public class ContentTypeOverrideInterceptor : RequestInterceptor { public string ContentTypeOverride { get; set; } public ContentTypeOverrideInterceptor(string contentTypeOverride) : base(true) { this.ContentTypeOverride = contentTypeOverride; } public override void ProcessRequest(ref RequestContext requestContext) { if (requestContext == null || requestContext.RequestMessage == null) { return; } Message message = requestContext.RequestMessage; HttpRequestMessageProperty reqProp = (HttpRequestMessageProperty)message.Properties[HttpRequestMessageProperty.Name]; reqProp.Headers["Content-Type"] = ContentTypeOverride; } } 

Then, if you view your .svc file, you will see, and the AppServiceHostFactory class will change it to include an interceptor

 class AppServiceHostFactory : ServiceHostFactory { protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { var host = new WebServiceHost2(serviceType, true, baseAddresses); host.Interceptors.Add(new ContentTypeOverrideInterceptor("application/json; charset=utf-8")); return host; } } 

That should do it for you.

Update

As mentioned in the comments, the method described above is intended for use with the WCF REST Starter Kit. If you use only the regular WCF service, you will have to create an IOperationBehavior and bind it to your service. here is the code for the behavior attribute

 public class WebContentTypeAttribute : Attribute, IOperationBehavior, IDispatchMessageFormatter { private IDispatchMessageFormatter innerFormatter; public string ContentTypeOverride { get; set; } public WebContentTypeAttribute(string contentTypeOverride) { this.ContentTypeOverride = contentTypeOverride; } // IOperationBehavior public void Validate(OperationDescription operationDescription) { } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { innerFormatter = dispatchOperation.Formatter; dispatchOperation.Formatter = this; } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { } public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } // IDispatchMessageFormatter public void DeserializeRequest(Message message, object[] parameters) { if (message == null) return; if (string.IsNullOrEmpty(ContentTypeOverride)) return; var httpRequest = (HttpRequestMessageProperty)message.Properties[HttpRequestMessageProperty.Name]; httpRequest.Headers["Content-Type"] = ContentTypeOverride; } public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) { return innerFormatter.SerializeReply(messageVersion, parameters, result); } } 

And you will have to change your service contract to look like this

 [OperationContract] [WebContentType("application/json; charset=utf-8")] public string DoWork(string FirstName, string LastName) { return "Your name is " + LastName + ", " + FirstName; } 

References

As you requested here, some links describing these WCF extensions

+5
source

All Articles