Endpoint user behavior not used in WCF client with service reference

I have a problem that I'm not quite sure how it started. I am pretty sure that it worked fine, but I don’t remember to make any changes.

First, please do not focus too much on tuning unless this directly affects why it is not working. I'm not looking for criticism as much as I do, which makes it not work.

I am showing an API that uses HTTP header authentication. I use this API in my solution. To avoid the template code, I created a ClientFactory that I want to initialize with services using CustomClientMessageInspector and CustomCredentialBehavior , which is responsible for adding headers to the message.

The idea is that when I need to use the service, the code will look something like this:

IClientCredentials credentials = ClientCredentials.FromToken(); var service = ClientFactory.CreateClientInstance<API.Clients.ClientServiceClient>(credentials); 

The Factory client is as follows (please do not judge too much about it).

 public class ClientFactory { public static T CreateClientInstance<T>(IClientCredentials clientCredentials) { T t = Activator.CreateInstance<T>(); var factory = t.GetType().GetProperty("ChannelFactory"); using (var scope = new OperationContextScope((IContextChannel) t.GetType().GetProperty("InnerChannel").GetValue(t,null))) { var endpointBehavior = new CustomCredentialBehavior(clientCredentials); if (((ChannelFactory) factory.GetValue((t),null)).Endpoint.Behaviors.Any(p => p.GetType() == typeof(CustomCredentialBehavior))) { var behavior = ((ChannelFactory) factory.GetValue((t),null)).Endpoint.Behaviors.FirstOrDefault( p => p.GetType() == typeof (CustomCredentialBehavior)); ((ChannelFactory) factory.GetValue((t),null)).Endpoint.Behaviors.Remove(behavior); } ((ChannelFactory)factory.GetValue((t),null)).Endpoint.Behaviors.Add(endpointBehavior); return t; } } } 

CustomEndpointBehavior:

 public class CustomCredentialBehavior:IEndpointBehavior { private IClientCredentials _clientCredentials { get; set; } public CustomCredentialBehavior(IClientCredentials clientCredentials) { _clientCredentials = clientCredentials; } public void Validate(ServiceEndpoint endpoint) { } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(new ClientCredentialMessageInspector(_clientCredentials)); } } 

ClientMessageInspector:

 public class ClientCredentialMessageInspector:IClientMessageInspector { private IClientCredentials _clientCredentials; public ClientCredentialMessageInspector(IClientCredentials clientCredentials) { _clientCredentials = clientCredentials; } public object BeforeSendRequest(ref Message request, IClientChannel channel) { var buffer = request.CreateBufferedCopy(Int32.MaxValue); request = buffer.CreateMessage(); HttpRequestMessageProperty messageProperty = (HttpRequestMessageProperty) request.Properties["httpRequest"]; messageProperty.Headers.Add("AccessKey", _clientCredentials.AccessKey.ToString()); messageProperty.Headers.Add("ClientKey", _clientCredentials.ClientKey.ToString()); messageProperty.Headers.Add("AuthorizationKey", _clientCredentials.AuthorizationKey); return null; } public void AfterReceiveReply(ref Message reply, object correlationState) { } } 

The problem I'm running into is that even if I see a service returned from ClientFactory with the correct endpoint behavior, ApplyClientBehavior () is never called. For some reason, it does not seem to use the WCF utility as it was originally.

How do I get ClientFactory to instantiate to add EndpointBehavior?

EDIT . To show what I'm looking at, here is a screenshot of the clock window right before calling the service. It shows that my CustomCredentialBehavior is initialized with all the correct values.

enter image description here

EDIT I took the advice of Carlos (in the comments) and simplified the call and used the next call instead. I am glad that it works, however, I would like to find out where the problem is in my source code, so I do not need to call the boilerplate code every time I need to use the service link.

The following code works:

  API.Clients.Client client = new API.Clients.Client(); client.Active = true; client.Enabled = true; client.Name = model.ClientName; API.Clients.ClientServiceClient service = new ClientServiceClient(); service.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentialBehavior(ClientCredentials.FromToken())); var response = service.CreateClient(new CreateClientRequest() { Client = client }); 

Any idea why the source code is not working and it does?

+4
source share
1 answer

Maybe something is missing for me, but I don’t understand why you should go with such a difficult route.

If you have a contract with an interface (not a client), simply follow these steps:

 var factory = new ChannelFactory<T>(); //T is the interface of the service 

factory.Endpoint.Behaviors.Add() will provide you with a way to add your behavior. And then to create the actual service, you call factory.CreateChannel() , which returns T

So in short:

 public T Create<T>() { var factory = new ChannelFactory<T>(); factory.Endpoint.Behaviors.Add(<here goes your behavior>); return factory.CreateChannel(); } 

Also remember to dispose of the client channel accordingly. If you use IoC, the container can probably handle this for you (e.g. Autofac).

+3
source

Source: https://habr.com/ru/post/1469141/


All Articles