使用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);
the query string must have ‘name=value’ pairs with unique names. Note that the names are case-insensitive. See the documentation for UriTemplate for more details.
如何定义使用参数数组暴露资源的HTTP服务,而不使用loosey-goosey接口?
解决方法
我实现了一个简单的自定义QueryStringConverter,以便您可以使qs1为字符串[],然后将查询字符串变量用逗号分隔(例如
http://server/service/SomeRequest?qs1=val1,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,我们使用该扩展名,而不是< webHttp />在我们的行为:
<system.serviceModel> <services> <service name="NameSpace.ServiceClass"> <endpoint address="" behaviorConfiguration="MyServiceBehavior" binding="webHttpBinding" contract="NameSpace.ServiceClass" /> </service> </services> <behaviors> <endpointBehaviors> <behavior name="MyServiceBehavior"> <customWebHttp/> </behavior> </endpointBehaviors> </behaviors> <extensions> <behaviorExtensions> <add name="customWebHttp" type="NameSpace.CustomHttpBehaviorExtensionElement,MyAssemblyName" /> </behaviorExtensions> </extensions> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> </system.serviceModel>
您现在还可以扩展您的CustomQueryStringConverter来处理其他类型的默认值,例如可空值类型.
注意:microsoft connect中存在与该代码直接相关的错误.在几乎所有情况下,您尝试查询转换不同类型的代码实际上不起作用.
请确保您仔细阅读,浪费您的时间创建自定义REST查询字符串转换器的时间,无法工作. (适用于Framework 4.0及以下).