В модели WCF веб-программирования, как можно написать контракт операции с массивом параметров строки запроса (то есть с тем же именем)?

голоса
13

Использование модели веб-программирования WCF можно указать контракт операции следующим образом:

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

Получаем сообщение об ошибке во время выполнения, когда мы делаем вызов к методу:

строка запроса должна иметь «имя = значение» пару с уникальными именами. Обратите внимание, что имена чувствительны к регистру. Обратитесь к документации по UriTemplate для более подробной информации.

Как один определить службы HTTP, который предоставляет ресурс с массивом параметров, не прибегая к интерфейсу loosey-балды?

Задан 10/12/2008 в 01:24
источник пользователем
На других языках...                            


3 ответов

голоса
28

Я реализовал простой пользовательский QueryStringConverter , так что вы можете сделать qs1 строкой [] , то есть переменная строка запроса будет разделителями - запятыми (например , HTTP: // сервер / сервис / 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, который обрабатывает строки [] параметры:

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, что непосредственно относится к этому коду. Код не на самом деле работает почти во всех обстоятельствах, когда вы пытаетесь создать запрос преобразования различных типов.

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

Пожалуйста, убедитесь, что вы читаете это тщательно, прежде чем тратить часы вашего времени создания пользовательского REST струнных преобразователей запросов, не может работать. (Относится к Framework 4.0 и ниже).

Ответил 10/12/2008 в 02:21
источник пользователем

голоса
5

Чтобы ответить на ваш комментарий на мой другой ответ:

Вы можете сделать параметр подстановки в конце строки запроса, как

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

Таким образом, параметр строка qs1 будет вся сырая QueryString после Qs1 =, вы могли бы разобрать, что вручную в коде.

QueryStringConverter зависит от форматирования строки запроса так делать что-то, как именно вы хотите, не представляется возможным без возможности перезаписи QueryStringConverter вместо маленьких переопределениях мы сделали в другой ответ.

Из MSDN:

Wildcard сегменты должны следовать следующим правилам:

  • Там может быть не более одного имени подстановочные сегмента для каждой строки шаблона.
  • Именованные сегмент подстановочных должны появиться в крайнем правом сегменте в пути.
  • Именованные сегмент подстановочные не могут сосуществовать с анонимным сегментом подстановочного в той же самой строке шаблона.
  • Имя именованного сегмента группового символа должно быть уникальным.
  • Именованные сегменты подстановочные не могут иметь значения по умолчанию.
  • Именованные сегменты подстановочные не может заканчиваться на «/».
Ответил 11/12/2008 в 00:12
источник пользователем

голоса
2

Имейте в виду, что в WCF 3.5 необходимо указать полное имя сборки в:

   <extensions>
    <behaviorExtensions>
      <add name="customWebHttp" type="NameSpace.CustomHttpBehaviorExtensionElement, MyAssemblyName, NOT SUFFICIENT HERE" />
    </behaviorExtensions>
  </extensions>

Так же , как это: SampleService.CustomBehavior, SampleService, Version = 1.0.0.0, культура = нейтральной, PublicKeyToken = нуль

В противном случае вы получите исключение:

Ошибка конфигурации
Описание: Произошла ошибка при обработке файла конфигурации , необходимые для обслуживания этого запроса. Пожалуйста , ознакомьтесь с конкретной ошибке ниже и изменить файл конфигурации соответствующим образом .

Parser Сообщение об ошибке: Invalid элемент в конфигурации. Имя расширения «CustomWebHttp» не зарегистрирован в коллекции на system.serviceModel / расширения / behaviorExtensions.

Ответил 24/12/2009 в 11:02
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more