Jak dodać niestandardowy nagłówek HTTP do każdego połączenia WCF?

Mam usługę WCF, która jest hostowana w usłudze Windows. Klienci korzystający z tej usługi muszą przekazywać identyfikator za każdym razem, gdy wywołują metody usługi (ponieważ ten identyfikator jest ważny dla tego, co powinna zrobić wywołana metoda). Pomyślałem, że dobrym pomysłem jest umieszczenie tego identyfikatora w nagłówku WCF.

Jeśli jest to dobry pomysł, jak Mogę dodać identyfikator automatycznie do informacji nagłówka. Innymi słowy, ilekroć użytkownik wywoła metodę WCF, identyfikator musi być automatycznie dodany do nagłówka.

UPDATE: Klientami korzystającymi z usługi WCF są zarówno aplikacje Windows, jak i aplikacja Windows Mobile (korzystająca z Compact Framework).

 145
wcf
Author: Ian Kemp, 2009-06-08

12 answers

Zaletą tego jest to, że jest stosowany do każdego połączenia.

Utwórz klasę, która implementuje IClientMessageInspector . W metodzie BeforeSendRequest dodaj swój niestandardowy nagłówek do wiadomości wychodzącej. Może to wyglądać mniej więcej tak:

    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,  System.ServiceModel.IClientChannel channel)
{
    HttpRequestMessageProperty httpRequestMessage;
    object httpRequestMessageObject;
    if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
    {
        httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
        if (string.IsNullOrEmpty(httpRequestMessage.Headers[USER_AGENT_HTTP_HEADER]))
        {
            httpRequestMessage.Headers[USER_AGENT_HTTP_HEADER] = this.m_userAgent;
        }
    }
    else
    {
        httpRequestMessage = new HttpRequestMessageProperty();
        httpRequestMessage.Headers.Add(USER_AGENT_HTTP_HEADER, this.m_userAgent);
        request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
    }
    return null;
}

Następnie utwórz zachowanie punktu końcowego, które stosuje Inspektora Wiadomości do środowiska uruchomieniowego klienta. Zachowanie można zastosować za pomocą atrybutu lub konfiguracji za pomocą elementu rozszerzenia zachowania.

Tutaj jest świetnym przykładem Jak dodać nagłówek HTTP user-agent do wszystkich wiadomości żądania. Używam tego u kilku moich klientów. Możesz również zrobić to samo po stronie usługi, implementując IDispatchMessageInspector .

To miałeś na myśli?

Update: znalazłem listę funkcji WCF, które są obsługiwane przez compact framework. Uważam, że komunikaty klasyfikowane są jako "rozszerzalność kanału", która zgodnie z tym post, obsługiwane przez compact framework.

 162
Author: Mark Good,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-26 18:10:53

Dodajesz go do wywołania używając:

using (OperationContextScope scope = new OperationContextScope((IContextChannel)channel))
{
    MessageHeader<string> header = new MessageHeader<string>("secret message");
    var untyped = header.GetUntypedHeader("Identity", "http://www.my-website.com");
    OperationContext.Current.OutgoingMessageHeaders.Add(untyped);

    // now make the WCF call within this using block
}

A potem po stronie serwera chwytasz go używając:

MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders;
string identity = headers.GetHeader<string>("Identity", "http://www.my-website.com");
 75
Author: AgileJon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-08 11:30:51

Jeśli chcesz dodać ten sam nagłówek do wszystkich żądań do serwisu, możesz to zrobić bez żadnego kodowania!
Po prostu Dodaj węzeł nagłówkowy z wymaganymi nagłówkami pod węzłem końcowym w pliku konfiguracyjnym klienta

<client>  
  <endpoint address="http://localhost/..." >  
    <headers>  
      <HeaderName>Value</HeaderName>  
    </headers>   
 </endpoint>  
 32
Author: Nimesh Madhavan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-06 19:45:48

Oto kolejne pomocne rozwiązanie do ręcznego dodawania niestandardowych nagłówków HTTP do żądania WCF klienta za pomocą ChannelFactory jako proxy. To musi być zrobione dla każdego żądania, ale wystarczy jako proste demo, jeśli po prostu trzeba przetestować swój serwer proxy w przygotowaniu do non-.NET perony.

// create channel factory / proxy ...
using (OperationContextScope scope = new OperationContextScope(proxy))
{
    OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = new HttpRequestMessageProperty()
    {
        Headers = 
        { 
            { "MyCustomHeader", Environment.UserName },
            { HttpRequestHeader.UserAgent, "My Custom Agent"}
        }
    };    
    // perform proxy operations... 
}
 11
Author: SliverNinja - MSFT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-25 16:25:47

Jest to podobne do NimsDotNet answer, ale pokazuje, jak to zrobić programowo.

Po prostu dodaj nagłówek do powiązania

var cl = new MyServiceClient();

var eab = new EndpointAddressBuilder(cl.Endpoint.Address);

eab.Headers.Add( AddressHeader.CreateAddressHeader("ClientIdentification",  // Header Name
                                                    string.Empty,           // Namespace
                                                    "JabberwockyClient"));  // Header Value

cl.Endpoint.Address = eab.ToEndpointAddress();
 8
Author: ΩmegaMan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-25 16:26:15
var endpoint = new EndpointAddress(new Uri(RemoteAddress),
                                               new[]
                                                   {
                                                       AddressHeader.CreateAddressHeader("APIKey", "",
                                                                                         "bda11d91-7ade-4da1-855d-24adfe39d174")
                                                   });
 5
Author: shepcom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-16 05:49:42

Możesz określić własne nagłówki w MessageContract .

Możesz również użyć nagłówków, które są przechowywane w pliku konfiguracyjnym i będą kopiowane allong w nagłówku wszystkich wiadomości wysyłanych przez Klienta/usługę. Jest to przydatne, aby łatwo dodać statyczny nagłówek.

 3
Author: Philippe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-08 12:12:13

Context bindings W.NET 3.5 może być właśnie tym, czego szukasz. Istnieją trzy wyjścia: BasicHttpContextBinding, NetTcpContextBinding i WSHttpContextBinding. Protokół kontekstowy zasadniczo przekazuje pary klucz-wartość w nagłówku wiadomości. Zapoznaj się z artykułem zarządzanie państwem za pomocą trwałych usług W magazynie MSDN.

 2
Author: Mehmet Aras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-08 11:38:54

Jeśli dobrze rozumiem twoje wymagania, prosta odpowiedź brzmi: nie możesz.

Dzieje się tak dlatego, że klient usługi WCF może zostać wygenerowany przez dowolną stronę trzecią, która korzysta z Twojej usługi.

Jeśli masz kontrolę nad klientami swojej usługi, możesz utworzyć bazową klasę klienta, która dodaje żądany nagłówek i dziedziczy zachowanie na klasach worker.

 2
Author: Paulo Santos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-08 11:48:09

To mi się udało, zaadaptowane z Dodawanie nagłówków HTTP do wywołań WCF

// Message inspector used to add the User-Agent HTTP Header to the WCF calls for Server
public class AddUserAgentClientMessageInspector : IClientMessageInspector
{
    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
    {
        HttpRequestMessageProperty property = new HttpRequestMessageProperty();

        var userAgent = "MyUserAgent/1.0.0.0";

        if (request.Properties.Count == 0 || request.Properties[HttpRequestMessageProperty.Name] == null)
        {
            var property = new HttpRequestMessageProperty();
            property.Headers["User-Agent"] = userAgent;
            request.Properties.Add(HttpRequestMessageProperty.Name, property);
        }
        else
        {
            ((HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name]).Headers["User-Agent"] = userAgent;
        }
        return null;
    }

    public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {
    }
}

// Endpoint behavior used to add the User-Agent HTTP Header to WCF calls for Server
public class AddUserAgentEndpointBehavior : IEndpointBehavior
{
    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(new AddUserAgentClientMessageInspector());
    }

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

Po zadeklarowaniu tych klas możesz dodać nowe zachowanie do swojego klienta WCF w następujący sposób:

client.Endpoint.Behaviors.Add(new AddUserAgentEndpointBehavior());
 1
Author: paulwhit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-05 00:55:18

To działa dla mnie

TestService.Recostitionclient _serv = new TestService.TestClient ();
 using (OperationContextScope contextScope = new OperationContextScope(_serv.InnerChannel))
                {
                    HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();

                    requestMessage.Headers["apiKey"] = ConfigurationManager.AppSettings["apikey"]; 
                    OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;
                    _serv.Method(Testarg);
                }
 1
Author: Taran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-25 16:40:42

Trochę za późno na imprezę, ale Juval Lowy omawia ten dokładny scenariusz w swojej książce i związanej z nią bibliotece ServiceModelEx.

Zasadniczo definiuje specjalizacje ClientBase i ChannelFactory, które pozwalają na określenie wartości nagłówków bezpiecznych dla typu. Proponuję pobrać źródło i zajrzeć do klas HeaderClientBase i HeaderChannelFactory.

John

 0
Author: BrizzleOwl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-28 12:04:18