No modelo de programação WCF web, como se pode escrever um contrato de operação com um conjunto de parâmetros de string de consulta (ou seja, com o mesmo nome)?

votos
13

Usando o modelo de programação web WCF pode-se especificar um contrato de operação assim:

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

Agora, se nós tivemos que fazer um contrato que aceita uma matriz de parâmetros com o mesmo nome (neste caso qs1 ) contrato como assim ...

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

Recebemos a mensagem de erro em tempo de execução quando fazemos a invocação ao método:

a string de consulta deve ter 'name = value' pares com nomes exclusivos. Note-se que os nomes são case-insensitive. Consulte a documentação para UriTemplate para mais detalhes.

Como se define um serviço HTTP que expõe um recurso com uma série de parâmetros, sem recorrer a uma interface plácida?

Publicado 10/12/2008 em 01:24
fonte usuário
Em outras línguas...                            


3 respostas

votos
28

Eu tenho implementado um simples QueryStringConverter personalizado para que você pode fazer qs1 uma string [], então, a variável de string de consulta ser delimitado por vírgulas (por exemplo, http: // servidor / serviço / SomeRequest qs1 = val1, val2, val3, val4 )

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

Primeiro você precisa de uma classe que herda de WebHttpBehavior para que possamos injetar nosso QueryStringConverter personalizado:

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

Então, o nosso CustomQueryStringConverter que manipula string [] parâmetros:

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

A última coisa que você precisa fazer é criar uma extensão de configuração de comportamento para que o tempo de execução pode obter uma instância da CustomWebHttpBehavior:

public class CustomHttpBehaviorExtensionElement : System.ServiceModel.Configuration.BehaviorExtensionElement
{
    protected override object CreateBehavior()
    {
        return new CustomHttpBehavior();
    }

    public override Type BehaviorType
    {
        get { return typeof(CustomHttpBehavior); }
    }
}

Agora vamos adicionar o elemento a nossas extensões de configuração para que o nosso CustomWebHttpBehavior é usado, usamos o nome dessa extensão em vez de <webHttp />em nosso comportamento:

 <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>

Agora também é possível estender sua CustomQueryStringConverter para lidar com outros tipos que o padrão não, como tipos de valor nulo.

NOTA: Há um bug registrado no Microsoft Connect que se relaciona diretamente a este código. O código na verdade não funciona em quase todas as circunstâncias em que você tenta consultar Converter tipos diferentes.

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

Por favor, certifique-se de ler este cuidadosamente antes de perder horas de seu tempo criando conversores de cadeia de consulta personalizada REST que não pode funcionar. (Aplica-se a Framework 4.0 e abaixo).

Respondeu 10/12/2008 em 02:21
fonte usuário

votos
5

Para responder ao seu comentário sobre minha outra resposta:

Você pode fazer um parâmetro curinga no final da querystring como

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

Desta forma, o parâmetro da sequência qs1 será toda a querystring cru após a qs1 =, você poderia então analisar esse manualmente no seu código.

O QueryStringConverter conta com a formatação do querystring assim fazendo algo exatamente como você quer não é possível sem possivelmente reescrever QueryStringConverter em vez das pequenas substituições que fizemos na outra resposta.

De MSDN:

segmentos curinga deve seguir as seguintes regras:

  • Não pode haver no máximo um segmento de curinga nomeado para cada corda modelo.
  • Um segmento de curinga nomeado deve aparecer na parte mais à direita do segmento no caminho.
  • Um segmento de curinga nomeado não pode coexistir com um segmento de curinga anônimo dentro do mesmo modelo de cadeia.
  • O nome de um segmento de curinga nomeado deverá ser exclusivo.
  • segmentos curinga nomeados não podem ter valores padrão.
  • segmentos curinga nomeado não pode terminar com “/”.
Respondeu 11/12/2008 em 00:12
fonte usuário

votos
2

Esteja ciente de que no WCF 3,5 você deve especificar o nome de assembly totalmente qualificado em:

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

Assim como este: SampleService.CustomBehavior, SampleService, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null

Caso contrário, você vai ficar exceção:

Erro de configuração
Descrição: Ocorreu um erro durante o processamento de um arquivo de configuração necessário para atender esta solicitação. Consulte os detalhes específicos do erro e modifique o seu arquivo de configuração apropriadamente.

Mensagem de erro do analisador: Elemento inválido na configuração. O nome da extensão 'CustomWebHttp' não está registrado na coleção no system.serviceModel / extensões / behaviorExtensions.

Respondeu 24/12/2009 em 11:02
fonte usuário

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