在 WCF Web 编程模型中,如何使用一组查询字符串参数(即具有相同名称)编写操作合同? [英] In the WCF web programming model, how can one write an operation contract with an array of query string parameters (i.e. with the same name)?

查看:12
本文介绍了在 WCF Web 编程模型中,如何使用一组查询字符串参数(即具有相同名称)编写操作合同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 WCF web 编程模型可以指定一个操作契约,如下所示:

Using the WCF web programming model one can specify an operation contract like so:

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

现在,如果我们必须制定一个接受具有相同名称的参数数组(在本例中为 qs1)的合约,就像这样...

Now if we had to make a contract that accepts an array of parameters with the same name (in this case qs1) contract like so...

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

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

We get the error message at run time when we make the invocation to the method:

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

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 服务,该服务公开具有一组参数的资源,而无需求助于松散的接口?

How does one define an HTTP service that exposes a resource with an array of parameters without resorting to a loosey-goosey interface?

推荐答案

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

I've implemented a simple custom QueryStringConverter so that you can make qs1 an string[] then have the query string variable be comma delimited (e.g. http://server/service/SomeRequest?qs1=val1,val2,val3,val4)

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

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

First you need a class that inherits from WebHttpBehavior so that we can inject our custom QueryStringConverter:

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

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

Then our CustomQueryStringConverter that handles string[] parameters:

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 的实例:

The last thing you need to do is create a behavior configuration extension so that the runtime can get an instance of the 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/>:

Now we add the element to our configuration extensions so that our CustomWebHttpBehavior is used, we use the Name of that extension instead of <webHttp /> in our behavior:

 <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 以处理默认类型不处理的其他类型,例如可空值类型.

You can now also extend your CustomQueryStringConverter to handle other types that the default one doesn't, such as nullable value types.

注意:在 microsoft connect 上记录了一个与此代码直接相关的错误.该代码实际上并不适用于您尝试查询转换不同类型的几乎所有情况.

NOTE: There is a bug logged at microsoft connect that directly relates to this code. The code does not actually work in almost all circumstances where you attempt to Query Convert different types.

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

在浪费您数小时的时间来创建不可能工作的自定义 REST 查询字符串转换器之前,请确保您仔细阅读此内容.(适用于 Framework 4.0 及以下版本).

Please make sure you read this carefully before wasting hours of your time creating custom REST query string converters that cannot possibly work. (Applies to Framework 4.0 and below).

这篇关于在 WCF Web 编程模型中,如何使用一组查询字符串参数(即具有相同名称)编写操作合同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆