IT박스

모든 WCF 호출에 사용자 지정 HTTP 헤더를 추가하는 방법은 무엇입니까?

itboxs 2020. 6. 7. 10:52
반응형

모든 WCF 호출에 사용자 지정 HTTP 헤더를 추가하는 방법은 무엇입니까?


Windows 서비스에서 호스팅되는 WCF 서비스가 있습니다. 이 서비스를 사용하는 클라이언트는 서비스 메소드를 호출 할 때마다 식별자를 전달해야합니다 (호출 된 메소드가 수행해야하는 작업에 식별자가 중요하기 때문에). 이 식별자를 WCF 헤더 정보에 넣는 것이 좋은 생각이라고 생각했습니다.

좋은 생각이라면 식별자를 자동으로 헤더 정보에 추가하는 방법은 무엇입니까? 즉, 사용자가 WCF 메서드를 호출 할 때마다 식별자가 자동으로 헤더에 추가되어야합니다.

업데이트 : WCF 서비스를 사용하는 클라이언트는 Windows 응용 프로그램과 Windows Mobile 응용 프로그램입니다 (Compact Framework 사용).


이것의 장점은 모든 통화에 적용된다는 것입니다.

IClientMessageInspector 를 구현하는 클래스를 작성하십시오 . BeforeSendRequest 메소드에서 사용자 정의 헤더를 발신 메시지에 추가하십시오. 다음과 같이 보일 수 있습니다.

    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;
}

그런 다음 메시지 관리자를 클라이언트 런타임에 적용하는 엔드 포인트 작동을 작성하십시오. 동작 확장 요소를 사용하여 속성 또는 구성을 통해 동작을 적용 할 수 있습니다.

다음은 모든 요청 메시지에 HTTP 사용자 에이전트 헤더를 추가하는 좋은 입니다. 나는 이것을 내 고객 중 일부에서 사용하고 있습니다. IDispatchMessageInspector 를 구현하여 서비스 측에서도 동일한 작업을 수행 할 수 있습니다 .

이것이 당신이 생각한 것입니까?

업데이트 : 컴팩트 프레임 워크에서 지원하는이 WCF 기능 목록찾았습니다 . 이 게시물에 따르면, '채널 확장'으로 분류 된 메시지 사찰 생각 하는 컴팩트 프레임 워크에서 지원합니다.


다음을 사용하여 통화에 추가합니다.

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
}

그런 다음 서버 측에서 다음을 사용하여 가져옵니다.

MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders;
string identity = headers.GetHeader<string>("Identity", "http://www.my-website.com");

서비스의 모든 요청에 ​​동일한 헤더를 추가하려는 경우 코딩없이 수행 할 수 있습니다!
클라이언트 구성 파일의 엔드 포인트 노드 아래에 필요한 헤더가있는 헤더 노드 만 추가하십시오.

<client>  
  <endpoint address="http://localhost/..." >  
    <headers>  
      <HeaderName>Value</HeaderName>  
    </headers>   
 </endpoint>  

Here is another helpful solution for manually adding custom HTTP Headers to your client WCF request using the ChannelFactory as a proxy. This would have to be done for each request, but suffices as a simple demo if you just need to unit test your proxy in preparation for non-.NET platforms.

// 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... 
}

This is similar to NimsDotNet answer but shows how to do it programmatically.

Simply add the header to the binding

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();

var endpoint = new EndpointAddress(new Uri(RemoteAddress),
               new[] { AddressHeader.CreateAddressHeader(
                       "APIKey", 
                       "",
                       "bda11d91-7ade-4da1-855d-24adfe39d174") 
                     });

Context bindings in .NET 3.5 might be just what you're looking for. There are three out of the box: BasicHttpContextBinding, NetTcpContextBinding, and WSHttpContextBinding. Context protocol basically passes key-value pairs in the message header. Check out Managing State With Durable Services article on MSDN magazine.


If I understand your requirement correctly, the simple answer is: you can't.

That's because the client of the WCF service may be generated by any third party that uses your service.

IF you have control of the clients of your service, you can create a base client class that add the desired header and inherit the behavior on the worker classes.


You can specify custom headers in the MessageContract.

You can also use < endpoint> headers that are stored in the configuration file and will be copied allong in the header of all the messages sent by the client/service. This is usefull to add some static header easily.


This works for me

TestService.ReconstitutionClient _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);
}

This is what worked for me, adapted from Adding HTTP Headers to WCF Calls

// 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)
    {
    }
}

After declaring these classes you can add the new behavior to your WCF client like this:

client.Endpoint.Behaviors.Add(new AddUserAgentEndpointBehavior());

A bit late to the party but Juval Lowy addresses this exact scenario in his book and the associated ServiceModelEx library.

Basically he defines ClientBase and ChannelFactory specialisations that allow specifying type-safe header values. I suggesst downloading the source and looking at the HeaderClientBase and HeaderChannelFactory classes.

John

참고URL : https://stackoverflow.com/questions/964433/how-to-add-a-custom-http-header-to-every-wcf-call

반응형