Note that there are some explanatory texts on larger screens.

plurals
  1. POCustom Endpoint Behavior not being used in WCF Client with Service Reference
    primarykey
    data
    text
    <p>I have an issue that I am not quite sure how it started. I am fairly certain it was working fine before, but do not remember making any changes.</p> <p>First, please do not focus too much on the setup unless it is directly impacting why it is not working. I am not looking for critiquing as much as I am what is causing it to not work.</p> <p>I am exposing an API that uses HTTP header authentication. I am consuming operations from this API in my solution. In order to avoid boilerplate code, I created a <strong>ClientFactory</strong> which I want to initialize the services, using a <strong>CustomClientMessageInspector</strong> and a <strong>CustomCredentialBehavior</strong> which is responsible for adding the headers to the message.</p> <p>The idea is that when I need to use a service, the code would look similar to this:</p> <pre><code>IClientCredentials credentials = ClientCredentials.FromToken(); var service = ClientFactory.CreateClientInstance&lt;API.Clients.ClientServiceClient&gt;(credentials); </code></pre> <p>The ClientFactory looks like the following(Please don't judge this too much).</p> <pre><code>public class ClientFactory { public static T CreateClientInstance&lt;T&gt;(IClientCredentials clientCredentials) { T t = Activator.CreateInstance&lt;T&gt;(); 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 =&gt; p.GetType() == typeof(CustomCredentialBehavior))) { var behavior = ((ChannelFactory) factory.GetValue((t),null)).Endpoint.Behaviors.FirstOrDefault( p =&gt; p.GetType() == typeof (CustomCredentialBehavior)); ((ChannelFactory) factory.GetValue((t),null)).Endpoint.Behaviors.Remove(behavior); } ((ChannelFactory)factory.GetValue((t),null)).Endpoint.Behaviors.Add(endpointBehavior); return t; } } } </code></pre> <p>The CustomEndpointBehavior:</p> <pre><code>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)); } } </code></pre> <p>The ClientMessageInspector:</p> <pre><code>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) { } } </code></pre> <p>The problem I am facing is that even though I can see the service returned from the ClientFactory with the correct endpoint behavior, the ApplyClientBehavior() is never invoked. For some reason, it doesn't seem to be utilizign the WCF pipeline the way it originally was.</p> <p>How do I get the ClientFactory to create an instance so that the EndpointBehavior I add is used?</p> <p><strong>EDIT</strong> Just to show what I am looking at, here is a screenshot of the watch window right before the service operation is invoked. It shows my CustomCredentialBehavior initialized with all the correct values. </p> <p><img src="https://i.stack.imgur.com/xf0H9.png" alt="enter image description here"></p> <p><strong>EDIT</strong> I took Carlos' advice (in the comments) and simplified the call, and used the following call instead which works. I am happy that it works, however, I would like to figure out where the problem is in my original code so I do not have to call the boilerplate code every time I need to use a service reference.</p> <p>The following code works:</p> <pre><code> 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 }); </code></pre> <p>Any idea why the initial code does not work, and this one does?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload