Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing Expect: 100-continue from basicHttpBinding

Tags:

.net

http

wcf

I'd like to remove the Expect: 100-continue header that is added by the underlying HttpWebRequest used in basicHttpBinding. I am aware of the option to simply set ServicePointManager.Expect100Continue to false. However, the problem with this approach is that it is global, i.e. it applies to all web requests initiated in the process. I would like to limit the scope of this to a specific WCF proxy. With an ASMX proxy this used to be easy - I would simply subclass the generated proxy which is a subclass of SoapHttpClientProtocol and override GetWebRequest. I would then call the base implementation and set the Expect100Continue on the returned web request object.

I am trying to apply a similar approach with WCF but can't quite find a method to "intercept" the HttpWebRequest created by the transport channel. Is this possible?

like image 565
Dandan Avatar asked Nov 02 '22 04:11

Dandan


1 Answers

For System.ServiceModel.Http 4.5, we can create a custom BasicHttpBinding injecting a HttpMessageHandler in the HttpClient pipeline:

class CustomHttpBinding: BasicHttpBinding
{
    public override BindingElementCollection CreateBindingElements()
    {
        var elements =  base.CreateBindingElements();
        var transport = elements.Find<HttpsTransportBindingElement>();
        if (transport != null)
        {
            elements.Remove(transport);
            elements.Add(CustomHttpsTransportBindingElement.CreateFromHttpsTransportBindingElement(transport));
        }
        return elements;
    }       
}

class CustomHttpsTransportBindingElement: HttpsTransportBindingElement
{
    private Func<HttpClientHandler, HttpMessageHandler> _createDelegatingHandler = client => new CustomHttpMessageHandler(client);
    public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
    {            
        context.BindingParameters.Add(_createDelegatingHandler);
        return base.BuildChannelFactory<TChannel>(context);
    }        

    public override BindingElement Clone()
    {
        return CreateFromHttpsTransportBindingElement(this);
    }

    public static CustomHttpsTransportBindingElement CreateFromHttpsTransportBindingElement(HttpsTransportBindingElement from)
    {
        return new CustomHttpsTransportBindingElement
        {
            AllowCookies = from.AllowCookies,
            AuthenticationScheme = from.AuthenticationScheme,
            BypassProxyOnLocal = from.BypassProxyOnLocal,
            ManualAddressing = from.ManualAddressing,
            MaxBufferSize = from.MaxBufferSize,
            MaxReceivedMessageSize = from.MaxReceivedMessageSize,
            ProxyAddress = from.ProxyAddress,
            ProxyAuthenticationScheme = from.ProxyAuthenticationScheme,
            RequireClientCertificate = from.RequireClientCertificate,
            TransferMode = from.TransferMode,
            UseDefaultWebProxy = from.UseDefaultWebProxy,
            WebSocketSettings = from.WebSocketSettings
        };
    }
}

class CustomHttpMessageHandler: DelegatingHandler
{
    public CustomHttpMessageHandler(HttpMessageHandler innerHandler): base(innerHandler)
    {            
    }
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Headers.ExpectContinue = false;
        return base.SendAsync(request, cancellationToken);
    }
}

If you are not on HTTPS, override HttpTransportBindingElement instead of HttpsTransportBindingElement

like image 194
agua from mars Avatar answered Nov 15 '22 12:11

agua from mars