You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WCF服务mex及服务端点访问返回400错误排查求助

问题描述

我参考微软官方文档创建了一个简单的WCF服务,暴露两个端点:

  1. 服务端点(/CalculationService);
  2. 元数据端点(/mex)。

该服务已在控制台应用中成功托管,可通过浏览器访问服务baseAddress及baseAddress?wsdl,但访问/mex和/CalculationService端点时均返回400错误,请问问题出在哪里?

托管应用代码

static void Main(string[] args) {
 // Step 1 of the address configuration procedure: Create a URI to serve as the base address.
 Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service/");
 // Step 2 of the hosting procedure: Create ServiceHost
 ServiceHost selfHost = new ServiceHost(typeof(Service1), baseAddress);
 try {
 // Step 3 of the hosting procedure: Add a service endpoint.
 // Step 4 of the hosting procedure: Enable metadata exchange.
 ServiceMetadataBehavior smb = selfHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
 if (smb == null)
 smb = new ServiceMetadataBehavior();
 //ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
 smb.HttpGetEnabled = true;
 smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
 selfHost.Description.Behaviors.Add(smb);
 selfHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, new BasicHttpBinding(), "mex");
 // Step 5 of the hosting procedure: Start (and then stop) the service.
 selfHost.AddServiceEndpoint(typeof(IService1), new WSHttpBinding(), "CalculatorService");
 selfHost.Open();
 Console.WriteLine("The service is ready.");
 Console.WriteLine("Press <ENTER> to terminate service.");
 Console.WriteLine();
 Console.ReadLine();
 // Close the ServiceHostBase to shutdown the service.
 selfHost.Close();
 } catch (CommunicationException ce) {
 Console.WriteLine("An exception occurred: {0}", ce.Message);
 selfHost.Abort();
 }
}

WCF服务web.config配置

<?xml version="1.0"?>
<configuration>
 <appSettings>
 <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
 </appSettings>
 <system.web>
 <compilation debug="true" targetFramework="4.6.1" />
 <httpRuntime targetFramework="4.6.1"/>
 </system.web>
 <system.serviceModel>
 <behaviors>
 <serviceBehaviors>
 <behavior>
 <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
 <!--<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false"/>-->
 <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
 <serviceDebug includeExceptionDetailInFaults="false"/>
 </behavior>
 </serviceBehaviors>
 </behaviors>
 <!--<protocolMapping>
 <add binding="basicHttpsBinding" scheme="https" />
 </protocolMapping>-->
 <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
 </system.serviceModel>
 <system.webServer>
 <modules runAllManagedModulesForAllRequests="true"/>
 <!-- To browse web app root directory during debugging, set the value below to true. Set to false before deployment to avoid disclosing web app folder information. -->
 <directoryBrowse enabled="true"/>
 </system.webServer>
</configuration>
问题排查与解决

给你梳理几个核心问题点,都是控制台自托管WCF时容易踩的坑:

1. Mex端点绑定错误

你给Mex元数据端点用了BasicHttpBinding,这是完全错误的!Mex端点必须使用专门的元数据绑定,比如MetadataExchangeHttpBinding(对应HTTP场景)或者MetadataExchangeHttpsBinding(对应HTTPS场景)。普通的业务绑定不支持元数据交换的协议格式,直接用它配置Mex端点必然返回400错误。

2. 服务端点的浏览器访问误区

WCF的WSHttpBinding是SOAP服务端点,它默认只处理SOAP协议的POST请求,而浏览器发起的是HTTP GET请求,两者协议不匹配,所以直接在浏览器访问/CalculatorService会返回400错误——这是WCF的设计行为,不是bug。你需要用SOAP客户端(比如Visual Studio自带的WCF测试客户端、Postman构造SOAP请求)来调用这个端点。

3. 控制台托管时web.config无效

注意:你是用控制台应用自托管WCF服务,此时WCF服务项目里的web.config完全不起作用!控制台自托管的配置优先级是:代码硬编码配置 > 控制台应用自身的app.config,和服务项目的web.config没有任何关系。你之前在web.config里注释的serviceMetadata配置对当前托管的服务没有影响,所有配置都要在控制台代码或它的app.config里设置。

修正后的托管代码

把Mex端点的绑定改成MetadataExchangeHttpBinding,调整后的代码如下:

static void Main(string[] args) {
 Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service/");
 ServiceHost selfHost = new ServiceHost(typeof(Service1), baseAddress);
 try {
 ServiceMetadataBehavior smb = selfHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
 if (smb == null)
 smb = new ServiceMetadataBehavior();
 smb.HttpGetEnabled = true;
 smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
 selfHost.Description.Behaviors.Add(smb);
 // 替换为元数据专用绑定
 selfHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
 selfHost.AddServiceEndpoint(typeof(IService1), new WSHttpBinding(), "CalculatorService");
 selfHost.Open();
 Console.WriteLine("The service is ready.");
 Console.WriteLine("Press <ENTER> to terminate service.");
 Console.ReadLine();
 selfHost.Close();
 } catch (CommunicationException ce) {
 Console.WriteLine("An exception occurred: {0}", ce.Message);
 selfHost.Abort();
 }
}

验证方式

  • Mex端点:现在可以用svcutil.exe工具或者WCF测试客户端访问http://localhost:8000/ServiceModelSamples/Service/mex,能正常获取元数据,不会再返回400错误。
  • 服务端点:打开Visual Studio的WCF测试客户端,添加服务地址http://localhost:8000/ServiceModelSamples/Service/,就能看到IService1的方法并进行调用测试。

如果想让服务端点支持浏览器GET请求测试,可以给服务添加WebHttpBinding并配置WebHttpBehavior,不过这属于REST风格的WCF,和当前的SOAP服务模式不同,可根据需求选择是否调整。


内容的提问来源于stack exchange,提问作者Amey Deshpande

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:18:13