wsHttpBinding workarounds in .NET Core

2020-05-01 09:12发布

问题:

I am looking for a dotnet core WCF wsHttpBinding workaround.

I am aware that .net core WCF implementation currently does not support wsHttpBinding (see support matrix here https://github.com/dotnet/wcf/blob/master/release-notes/SupportedFeatures-v2.1.0.md)

I'm integrating with a legacy third party service that appears to only support wsHttpBinding. Our tech stack is .net core, so I cannot revert to the full version of .net framework or mono variant.

The question is whether it's possible to use the service via custom bindings? I am hoping that there is a workaround that maybe isn't fully functional, but at least allows me to consume the service.

var cBinding = new CustomBinding();
        var textBindingElement = new TextMessageEncodingBindingElement()
        {
            MessageVersion = MessageVersion.Soap12WSAddressing10
        };
        cBinding.Elements.Add(textBindingElement);
        var httpBindingElement =
            new HttpsTransportBindingElement
            {
                AllowCookies = true, MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue, 
            };
        cBinding.Elements.Add(httpBindingElement);


        var myEndpoint = new EndpointAddress("https://..../Service.svc/wss");
        using (var myChannelFactory = new ChannelFactory<ISearch>(cBinding, myEndpoint))
        {
            myChannelFactory.Credentials.UserName.UserName = "...";
            myChannelFactory.Credentials.UserName.Password = "...";

            ISearch client = null;

            try
            {
                client = myChannelFactory.CreateChannel();

                var result = client.Find(new Search("Criteria")).Result;

                ((ICommunicationObject)client).Close();
                myChannelFactory.Close();
            }
            catch (Exception ex)
            {
                (client as ICommunicationObject)?.Abort();
            }
        }

Client gets created and a call is made to the service, but it fails because:

Message = "The message could not be processed. This is most likely because the action '' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between binding

回答1:

Forget it, they are not completely compatible with Core. Under some specified case, there may be a basic call to WsHttpBinding. You could refer to the following example.
Server.

   Uri uri = new Uri("http://localhost:11011");
    WSHttpBinding binding = new WSHttpBinding();
    binding.Security.Mode = SecurityMode.None;
    using (ServiceHost sh=new ServiceHost(typeof(MyService),uri))
    {
        sh.AddServiceEndpoint(typeof(IService), binding, "");
        ServiceMetadataBehavior smb;
        smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
        if (smb==null)
        {
            smb = new ServiceMetadataBehavior()
            {
            };
            sh.Description.Behaviors.Add(smb);
        }
        Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
        sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
        sh.Opened += delegate
        {
            Console.WriteLine("Service is ready");
        };
        sh.Closed += delegate
        {
            Console.WriteLine("Service is clsoed");
        };                
        sh.Open();

Client(auto-generated)

private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
    {
        if ((endpointConfiguration == EndpointConfiguration.WSHttpBinding_IService))
        {
            System.ServiceModel.Channels.CustomBinding result = new System.ServiceModel.Channels.CustomBinding();
            System.ServiceModel.Channels.TextMessageEncodingBindingElement textBindingElement = new System.ServiceModel.Channels.TextMessageEncodingBindingElement();
            result.Elements.Add(textBindingElement);
            System.ServiceModel.Channels.HttpTransportBindingElement httpBindingElement = new System.ServiceModel.Channels.HttpTransportBindingElement();
            httpBindingElement.AllowCookies = true;
            httpBindingElement.MaxBufferSize = int.MaxValue;
            httpBindingElement.MaxReceivedMessageSize = int.MaxValue;
            result.Elements.Add(httpBindingElement);
            return result;
        }  

Invocation.

ServiceReference1.ServiceClient client2 = new ServiceReference1.ServiceClient();
try
{
    var res = client2.SayHelloAsync();
    Console.WriteLine(res.Result);

}
catch (Exception)
{
    throw;
}

While in most cases it is impossible to call WCF service created by WsHttpBinding. Officials also have no intention of continuing to support plan for wshttpbinding. Here are related discussions. https://github.com/dotnet/wcf/issues/31
https://github.com/dotnet/wcf/issues/1370