使用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接口?
我已经实现了一个简单的自定义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及更低版本).
回复你对我的另一个答案的评论:
您可以在查询字符串的末尾执行通配符参数
[WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "SomeRequest?qs1={*qs1}")] XElement SomeRequest2(string qs1);
这样qs1字符串参数将是qs1 =之后的整个原始查询字符串,然后您可以在代码中手动解析它.
QueryStringConverter依赖于查询字符串的格式,因此如果不重写QueryStringConverter而不是我们在另一个答案中做的一点覆盖,就不可能按照你想要的方式做一些事情.
来自MSDN:
通配符段必须遵循以下规则:
每个模板字符串最多只能有一个命名通配符段.
命名通配符段必须出现在路径中最右侧的段中.
命名通配符段不能与同一模板字符串中的匿名通配符段共存.
命名通配符段的名称必须是唯一的.
命名通配符段不能具有默认值.
命名通配符段不能以"/"结尾.