.net - tutorial - ¿Cómo agregar un encabezado de mensaje a la solicitud cuando se usa el cliente predeterminado de la estructura de servicio de Azure?
service fabric tutorial (2)
Hice la misma pregunta en el foro de MSDN hace unas semanas, sin embargo, no obtuve respuesta allí.
Miré el código fuente de la biblioteca del cliente y no encontré una manera de agregar encabezados. Me temo que la única forma es agregarlos como parte de la llamada al método. Esto podría hacerse usando clases de solicitud como parámetros de método y usando herencia para ellos. (p. ej., clase RequestBase con encabezados [Authorization, ClientInfo, ...]). Luego debe asegurarse de que estos encabezados estén configurados para cada solicitud ajustando todas las invocaciones o configurándolas manualmente.
Se agradecería mucho más aclaraciones del equipo de Service Fabric.
Me pregunto si es posible inyectar un encabezado de mensaje personalizado en la solicitud saliente para llevar información adicional sin deserializar la carga útil para completar la funcionalidad como autenticación, validación o correlación de solicitud como wcf proporcionada por medio de messagesinspector.
Actualizar
Con SDK v2, ahora puede (relativamente) modificar fácilmente los encabezados de los servicios y actores confiables. Tenga en cuenta que en los ejemplos a continuación se omitieron algunos miembros del contenedor por brevedad.
Cliente
Utilizamos
ServiceProxyFactory
para crear proxies en lugar del
ServiceProxy
estático.
Luego podemos envolver
IServiceRemotingClientFactory
e
IServiceRemotingClient
e interceptar las llamadas de servicio.
Lo mismo se puede hacer con
ActorProxyFactory
.
Tenga en cuenta que esto anula el comportamiento de atributos como
WcfServiceRemotingProviderAttribute
, ya que especificamos explícitamente la fábrica del cliente nosotros mismos.
_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
Herede de
ServiceRemotingDispatcher
y
ActorServiceRemotingDispatcher
para examinar los encabezados.
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 esta clase, nuevamente necesitamos anular el
ServiceRemotingProviderAttribute
creando directamente el escucha de comunicación:
class MyService : StatelessService
{
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
yield return new ServiceInstanceListener(context => new WcfServiceRemotingListener(context, new CustomServiceRemotingDispatcher());
}
}