.net - pricing - service bus microsoft




Como adicionar o cabeçalho da mensagem à solicitação ao usar o cliente padrão da malha de serviço do Azure? (2)

Eu estou querendo saber que é possível injetar cabeçalho de mensagem personalizada para solicitação de saída para transportar informações adicionais sem desserializar a carga para preencher a funcionalidade como autenticação, validação ou correlação de solicitação como wcf fornecido por meio de messagesinspector?


Eu fiz a mesma pergunta no fórum do MSDN há algumas semanas, no entanto, não obtive uma resposta lá.

Analisei o código-fonte da biblioteca do cliente e não encontrei uma maneira de adicionar cabeçalhos. Eu tenho medo que a única maneira é adicioná-los como parte da chamada do método. Isso pode ser feito usando classes de solicitação como parâmetros de método e usando herança para eles. (por exemplo, classe RequestBase com cabeçalhos [Authorization, ClientInfo, ...]). Então, você precisa garantir que esses cabeçalhos sejam definidos para cada solicitação, agrupando todas as chamadas ou definindo-as manualmente.

Mais esclarecimentos da equipe do Service Fabric seriam muito apreciados.


Atualizar

Com o SDK v2, você pode modificar (relativamente) facilmente os cabeçalhos dos Serviços e Atores Confiáveis. Observe nos exemplos abaixo alguns membros do wrapper foram omitidos por brevidade.

Cliente

Usamos ServiceProxyFactory para criar proxies em vez do ServiceProxy estático. Em seguida, podemos incluir IServiceRemotingClientFactory e IServiceRemotingClient e interceptar as chamadas de serviço. O mesmo pode ser feito com o ActorProxyFactory . Observe que isso substitui o comportamento de atributos como o WcfServiceRemotingProviderAttribute , pois especificamos explicitamente a fábrica do cliente.

_proxyFactory = new ServiceProxyFactory(c => new ServiceRemotingClientFactoryWrapper(
 // we can use any factory here
 new WcfServiceRemotingClientFactory(callbackClient: c)));

    private class ServiceRemotingClientFactoryWrapper : IServiceRemotingClientFactory
    {
        private readonly IServiceRemotingClientFactory _inner;

        public ServiceRemotingClientFactoryWrapper(IServiceRemotingClientFactory inner)
        {
            _inner = inner;
        }

        public async Task<IServiceRemotingClient> GetClientAsync(Uri serviceUri, ServicePartitionKey partitionKey, TargetReplicaSelector targetReplicaSelector,
            string listenerName, OperationRetrySettings retrySettings, CancellationToken cancellationToken)
        {
            var client = await _inner.GetClientAsync(serviceUri, partitionKey, targetReplicaSelector, listenerName, retrySettings, cancellationToken).ConfigureAwait(false);
            return new ServiceRemotingClientWrapper(client);
        }
    }

    private class ServiceRemotingClientWrapper : IServiceRemotingClient
    {
        private readonly IServiceRemotingClient _inner;

        public ServiceRemotingClientWrapper(IServiceRemotingClient inner)
        {
            _inner = inner;
        }

        public Task<byte[]> RequestResponseAsync(ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody)
        {
            // use messageHeaders.AddHeader() here
            return _inner.RequestResponseAsync(messageHeaders, requestBody);
        }

        public void SendOneWay(ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody)
        {
            // use messageHeaders.AddHeader() here
            _inner.SendOneWay(messageHeaders, requestBody);
        }
    }

Servidor

Herdar de ActorServiceRemotingDispatcher e ActorServiceRemotingDispatcher para examinar os cabeçalhos.

class CustomServiceRemotingDispatcher : ServiceRemotingDispatcher
{
    public override async Task<byte[]> RequestResponseAsync(IServiceRemotingRequestContext requestContext, ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody)
    {
        // read messageHeaders here
        // or alternatively put them in an AsyncLocal<T> scope
        // so they can be accessed down the call chain
        return base.RequestResponseAsync(requestContext, messageHeaders, requestBody);
    }
}

Para usar essa classe, precisamos novamente substituir o ServiceRemotingProviderAttribute criando diretamente o listener de comunicação:

class MyService : StatelessService
{
     protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
     {
          yield return new ServiceInstanceListener(context => new WcfServiceRemotingListener(context, new CustomServiceRemotingDispatcher());
     }
}