当前位置:  开发笔记 > 编程语言 > 正文

在WCF Web编程模型中,如何使用查询字符串参数数组(即具有相同名称)编写操作契约?

如何解决《在WCFWeb编程模型中,如何使用查询字符串参数数组(即具有相同名称)编写操作契约?》经验,为你挑选了2个好方法。

使用WCF Web编程模型可以指定操作合同,如下所示:

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "SomeRequest?qs1={qs1}&qs2={qs2}")]
XElement SomeRequest1(string qs1, string qs2);

现在,如果我们必须签订一个接受具有相同名称的参数数组(在这种情况下为qs1)的合同,那么......

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "SomeRequest?qs1={qs1}&qs1={qs2}")]
 XElement SomeRequest2(string qs1, string qs2);

当我们调用方法时,我们在运行时收到错误消息:

查询字符串必须具有唯一名称的"name = value"对.请注意,名称不区分大小写.有关更多详细信息,请参阅UriTemplate的文档.

如何定义一个HTTP服务,该服务使用参数数组公开资源,而不需要使用loosey-goosey接口?



1> joshperry..:

我已经实现了一个简单的自定义QueryStringConverter,这样你就可以使qs1成为一个字符串[]然后让查询字符串变量以逗号分隔(例如http:// server/service/SomeRequest?qs1 = val1,val2,val3,val4)

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml,
        UriTemplate = "SomeRequest?qs1={qs1}")]
XElement SomeRequest2(string[] qs1);

首先,您需要一个继承自WebHttpBehavior的类,以便我们可以注入自定义QueryStringConverter:

public class CustomHttpBehavior : System.ServiceModel.Description.WebHttpBehavior
{
    protected override System.ServiceModel.Dispatcher.QueryStringConverter GetQueryStringConverter(System.ServiceModel.Description.OperationDescription operationDescription)
    {
        return new CustomQueryStringConverter();
    }
}

然后我们的CustomQueryStringConverter处理string []参数:

public class CustomQueryStringConverter : System.ServiceModel.Dispatcher.QueryStringConverter
{
    public override bool CanConvert(Type type)
    {
        if (type == typeof(string[]))
        {
            return true;
        }

        return base.CanConvert(type);
    }

    public override object ConvertStringToValue(string parameter, Type parameterType)
    {
        if (parameterType == typeof(string[]))
        {
            string[] parms = parameter.Split(',');
            return parms;
        }

        return base.ConvertStringToValue(parameter, parameterType);
    }

    public override string ConvertValueToString(object parameter, Type parameterType)
    {
        if (parameterType == typeof(string[]))
        {
            string valstring = string.Join(",", parameter as string[]);
            return valstring;
        }

        return base.ConvertValueToString(parameter, parameterType);
    }
}

您需要做的最后一件事是创建行为配置扩展,以便运行时可以获取CustomWebHttpBehavior的实例:

public class CustomHttpBehaviorExtensionElement : System.ServiceModel.Configuration.BehaviorExtensionElement
{
    protected override object CreateBehavior()
    {
        return new CustomHttpBehavior();
    }

    public override Type BehaviorType
    {
        get { return typeof(CustomHttpBehavior); }
    }
}

现在我们将元素添加到配置扩展中,以便使用我们的CustomWebHttpBehavior,我们使用该扩展名而不是我们的行为:

 
   
     
       
     
   
  
   
    
      
    
   
  
  
    
      
    
  
  
 

您现在还可以扩展CustomQueryStringConverter以处理默认值不存在的其他类型,例如可为空的值类型.

注意:microsoft connect上记录的错误与此代码直接相关.在您尝试查询转换不同类型的几乎所有情况下,代码实际上都不起作用.

http://connect.microsoft.com/VisualStudio/feedback/details/616486/bug-with-getquerystringconverter-not-being-called-by-webservicehost#tabs

请务必仔细阅读本文,然后再浪费时间创建无法工作的自定义REST查询字符串转换器.(适用于Framework 4.0及更低版本).


WCF 4中存在一个错误,WebServiceHost没有调用重写的GetQueryStringConverter方法.请参阅https://connect.microsoft.com/VisualStudio/feedback/details/616486/bug-with-getquerystringconverter-not-being-called-by-webservicehost?wa=wsignin1.0

2> joshperry..:

回复你对我的另一个答案的评论:

您可以在查询字符串的末尾执行通配符参数

[WebGet(ResponseFormat = WebMessageFormat.Xml,
        UriTemplate = "SomeRequest?qs1={*qs1}")]
XElement SomeRequest2(string qs1);

这样qs1字符串参数将是qs1 =之后的整个原始查询字符串,然后您可以在代码中手动解析它.

QueryStringConverter依赖于查询字符串的格式,因此如果不重写QueryStringConverter而不是我们在另一个答案中做的一点覆盖,就不可能按照你想要的方式做一些事情.

来自MSDN:

通配符段必须遵循以下规则:

每个模板字符串最多只能有一个命名通配符段.

命名通配符段必须出现在路径中最右侧的段中.

命名通配符段不能与同一模板字符串中的匿名通配符段共存.

命名通配符段的名称必须是唯一的.

命名通配符段不能具有默认值.

命名通配符段不能以"/"结尾.

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