Используя модель веб-программирования 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);
Мы получаем сообщение об ошибке во время выполнения, когда вызываем метод:
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, которая предоставляет ресурс с массивом параметров, не прибегая к бесполезному интерфейсу?





Я реализовал простой пользовательский 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, который обрабатывает параметры 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 для обработки других типов, которые не используются по умолчанию, например, типов значений, допускающих значение NULL.
ПРИМЕЧАНИЕ. В Microsoft Connect регистрируется ошибка, которая напрямую связана с этим кодом. Код фактически не работает почти во всех случаях, когда вы пытаетесь преобразовать запросы различных типов.
Убедитесь, что вы внимательно прочитали это, прежде чем тратить часы своего времени на создание настраиваемых преобразователей строк запроса REST, которые не могут работать. (Относится к Framework 4.0 и ниже).
Есть идеи, как сделать так, чтобы он выглядел как сервер / служба /…? Мы могли бы, конечно, взломать его, чтобы он возвращал отформатированную строку с именем параметра вместо запятой.
Отлично! Я столкнулся с проблемой, из-за которой мое расширение поведения не загружалось, если я полностью не уточнил имя типа с версией сборки, ключом и т. д. См. nayyeri.net/…
В WCF 4 есть ошибка, из-за которой WebServiceHost не вызывает переопределенный метод GetQueryStringConverter. См. connect.microsoft.com/VisualStudio/feedback/details/616486/…
это действительно работает? Я не смог заставить это работать
Чтобы ответить на ваш комментарий к другому моему ответу:
Вы можете использовать подстановочный знак в конце строки запроса, например
[WebGet(ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "SomeRequest?qs1 = {*qs1}")]
XElement SomeRequest2(string qs1);
Таким образом, строковый параметр qs1 будет всей необработанной строкой запроса после qs1 =, вы можете затем проанализировать это вручную в своем коде.
QueryStringConverter полагается на форматирование строки запроса, поэтому сделать что-то именно так, как вы хотите, невозможно без возможной перезаписи QueryStringConverter вместо небольших переопределений, которые мы сделали в другом ответе.
Из MSDN:
Сегменты с подстановочными знаками должны соответствовать следующим правилам:
Имейте в виду, что в WCF 3.5 вы должны указать полное имя сборки в:
<extensions>
<behaviorExtensions>
<add name = "customWebHttp" type = "NameSpace.CustomHttpBehaviorExtensionElement, MyAssemblyName, NOT SUFFICIENT HERE" />
</behaviorExtensions>
</extensions>
Вот так: SampleService.CustomBehavior, SampleService, Версия = 1.0.0.0, культура = нейтральная, PublicKeyToken = null
В противном случае вы получите исключение:
Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.
Parser Error Message: Invalid element in configuration. The extension name 'CustomWebHttp' is not registered in the collection at system.serviceModel/extensions/behaviorExtensions.
Если вам не нужен
[WebGet], вы можете использовать[WebInvoke(Method = "POST"], в котором разрешены массивы / коллекции. См. этот ответ.