添加WCF Core服务引用时遇CoreWCF.ProtocolException异常求助
环境与代码实现
服务契约与实现
[ServiceContract] public interface IServiceAPI { [OperationContract(IsOneWay = true)] void DoWork(); } public class ServiceAPI : IServiceAPI { IServiceAPICallBack Callback { get { return OperationContext.Current.GetCallbackChannel<IServiceAPICallBack>(); } } public void DoWork() { Callback.Result(2); } }
Program.cs配置
using CoreWCF; using CoreWCF.Channels; using CoreWCF.Configuration; using CoreWCF.Description; using System.Web.Services.Description; using TestApp; var builder = WebApplication.CreateBuilder(args); builder.WebHost.ConfigureKestrel((context, options) => { options.AllowSynchronousIO = true; }); // 添加WSDL支持 builder.Services.AddServiceModelServices().AddServiceModelMetadata(); builder.Services.AddSingleton<IServiceBehavior, UseRequestHeadersForMetadataAddressBehavior>(); var app = builder.Build(); var myWSHttpBinding = new WSHttpBinding(SecurityMode.Transport); myWSHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; app.UseServiceModel(builder => { builder.AddService<ServiceAPI>(); builder.AddServiceEndpoint<ServiceAPI, IServiceAPI>(new BasicHttpBinding(), "/ServiceAPI/basichttp"); builder.AddServiceEndpoint<ServiceAPI, IServiceAPI>(myWSHttpBinding, "/cowork"); }); var serviceMetadataBehavior = app.Services.GetRequiredService<ServiceMetadataBehavior>(); serviceMetadataBehavior.HttpGetEnabled = true; app.Run();
appsettings.json配置
{ "Urls": "http://localhost:5000;https://localhost:5001", "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
错误信息
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
CoreWCF.ProtocolException: Content Type application/soap+xml; charset=utf-8 was sent to a service expecting text/xml; charset=utf-8. The client and service bindings may be mismatched.
at CoreWCF.Channels.HttpInput.ThrowHttpProtocolException(String message, HttpStatusCode statusCode, String statusDescription)
at CoreWCF.Channels.HttpInput.ValidateContentType()
at CoreWCF.Channels.HttpInput.ParseIncomingMessageAsync()
at CoreWCF.Channels.AspNetCoreReplyChannel.HandleRequest(HttpContext context)
at CoreWCF.Channels.RequestDelegateHandler.HandleRequest(HttpContext context)
at CoreWCF.Channels.ServiceModelHttpMiddleware.InvokeAsync(HttpContext context)
at CoreWCF.Channels.MetadataMiddleware.InvokeAsync(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
错误核心是客户端请求的SOAP版本与服务端绑定期望的SOAP版本不匹配:
BasicHttpBinding默认使用SOAP 1.1,对应Content-Type为text/xmlWSHttpBinding默认使用SOAP 1.2,对应Content-Type为application/soap+xml
提供两种解决思路:
思路1:调整服务端元配置与端点选择
为HTTPS端点启用元数据获取
你的WSHttpBinding使用HTTPS传输模式,但当前仅开启了HTTP元数据获取,需补充启用HTTPS元数据:var serviceMetadataBehavior = app.Services.GetRequiredService<ServiceMetadataBehavior>(); serviceMetadataBehavior.HttpGetEnabled = true; serviceMetadataBehavior.HttpsGetEnabled = true; // 新增该行添加服务引用时指定对应端点的WSDL地址
- 若使用
BasicHttpBinding,引用地址填:http://localhost:5000/ServiceAPI/basichttp?wsdl - 若使用
WSHttpBinding,引用地址填:https://localhost:5001/cowork?wsdl
- 若使用
思路2:统一服务端SOAP版本(可选)
如果希望所有端点使用同一SOAP版本,可修改绑定配置:
- 让
BasicHttpBinding支持SOAP 1.2:var basicBindingElements = new BasicHttpBinding().CreateBindingElements(); basicBindingElements.Find<TextMessageEncodingBindingElement>().MessageVersion = MessageVersion.Soap12WSAddressing10; var customBasicBinding = new CustomBinding(basicBindingElements); // 用自定义绑定替换原BasicHttpBinding添加端点 builder.AddServiceEndpoint<ServiceAPI, IServiceAPI>(customBasicBinding, "/ServiceAPI/basichttp"); - 或者让
WSHttpBinding使用SOAP 1.1:var myWSHttpBinding = new WSHttpBinding(SecurityMode.Transport); myWSHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; myWSHttpBinding.MessageVersion = MessageVersion.Soap11WSAddressing10; // 修改该行
额外修复点
当前代码未定义回调契约IServiceAPICallBack,需补充完整:
[ServiceContract] public interface IServiceAPICallBack { [OperationContract(IsOneWay = true)] void Result(int value); } // 服务契约需指定回调契约 [ServiceContract(CallbackContract = typeof(IServiceAPICallBack))] public interface IServiceAPI { [OperationContract(IsOneWay = true)] void DoWork(); }
内容的提问来源于stack exchange,提问作者Md. Zakir Hossain

