当前位置:  开发笔记 > 后端 > 正文

将JQGrid与WCF Web服务结合使用

如何解决《将JQGrid与WCFWeb服务结合使用》经验,为你挑选了1个好方法。

我试图从我的ASP.NET 2.0 WebForms应用程序中运行的WCF Web服务获取JQGrid的数据.问题是WCF Web服务期望将数据格式化为JSON字符串,并且JQGrid正在执行HTTP Post并将其作为Content-Type传递:application/x-www-form-urlencoded.

虽然返回到JQGrid的数据格式似乎有几种选择(它接受JSON,XML等),但似乎没有办法改变它将输入传递给Web服务的方式.

所以我试图找出如何调整WCF服务以便它接受

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

而不是

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

当我使用JQuery进行测试以使用url编码发送Ajax请求时(如下所示):

$.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);
    }
});

呼叫失败.使用Fiddler检查流量,我发现服务器返回的错误:

{"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."...

请注意,由于编码的不同,此代码可以正常工作

$.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);
    }
});

在服务器上,该服务看起来像:

[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;
    }
}

我的web.config包含:


  
   
    
     
    
   
  
  
  
   
    
   
  

谢谢你的帮助!



1> bendewey..:

如果你无法控制你的ajax调用,我建议创建和拦截来覆盖内容类型标题.

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;
    }
}

然后,如果您查看.svc文件,您将看到并且AppServiceHostFactory类将其更改为包含拦截器

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;
    }
}

那应该为你做.

更新

如评论中所述,上述方法适用于WCF REST入门工具包.如果您只使用常规WCF服务,则必须创建IOperationBehavior并将其附加到您的服务.这是behavior属性的代码

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);
    }
}

而且你必须修改你的服务合同,看起来像这个

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

链接

正如您在此处所要求的,是一些描述这些WCF扩展的链接

IOperationBehavior接口

IDispatchMessageFormatter接口

如何实现IDispatchMessageFormatter

WCF可扩展性 - 插入自定义消息处理逻辑

推荐阅读
黄晓敏3023
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有