[小菜一碟] 如何在 Web Service 代理類別發送 Http Request 前加入自訂 Http Header?

之前的一篇文章中,說明了我們如何用 WSDL 檔案產生代理類別,現在目標的 Web Service 有一個需求是要加入一個 Http Header,網路上可能會找到覆寫 GetWebRequest() 的解法,但我們會發現,用 dotnet-svcutil 所產生的代理類別無法覆寫 GetWebRequest(),該怎麼辦?

開頭提到的解法,是古早時候 ASP.NET 2.0 時代的 Web Service 代理類別所使用的,後來 WCF 推出之後,Web Service 的發展重心就移到了 WCF 上,並且向下相容 ASP.NET 2.0 的 Web Service,所以我們加入 Http Header 的方法完全不一樣。

解法的方向一樣是在 Http Request 送出去之前,加入 Http Header,需要實作兩個介面。

實作 IClientMessageInspector

BeforeSendRequest() 之中,將我們需要的 Http Header 加到 Http Request。

public class HttpHeadersMessageInspector : IClientMessageInspector
{
    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        var httpRequest = request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out var property)
                              ? (HttpRequestMessageProperty)property
                              : new HttpRequestMessageProperty();

        httpRequest.Headers["My-Header"] = "My-Header-Value";

        request.Properties[HttpRequestMessageProperty.Name] = httpRequest;

        return null;
    }
}

實作 IEndpointBehavior

ApplyClientBehavior() 之中,將 HttpHeadersMessageInspector 加到 ClientMessageInspectors 集合。

public class HttpHeadersBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.ClientMessageInspectors.Add(new HttpHeadersMessageInspector());
    }

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

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

新增 EndpointBehavior

最後,將 HttpHeadersBehavior 新增到 SoapClient Endpoint 的 EndpointBehaviors 集合,這樣就可以了。

...

var client = new WebService1SoapClient(WebService1SoapClient.EndpointConfiguration.WebService1Soap);

client.Endpoint.EndpointBehaviors.Add(new HttpHeadersBehavior());

...

執行結果

遵循 WCF 的架構,順著它的脈絡來,加個 Http Header 不必繞遠路、更不必修改代理類別,只要掌握訊息攔截與端點行為這兩個擴充點,就能在送出 Request 前優雅地塞入所需資訊。以上內容,分享給有遇到類似問題的朋友,希望能夠有一丁點的幫助。

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學

系列文章