Welcome

首页 / 软件开发 / WCF / WCF技术剖析之六

WCF技术剖析之六2012-10-11 cnblogs Artech为什么在基于ASP.NET应用寄宿(Hosting)下配置的BaseAddress无效?

本篇文章来源于几天前一个朋友向我咨询的问题。问题是这样的,他说他采用ASP.NET应用程序的方式对定义的WCF服务进行寄宿(Hosting),并使用配置的方式对服务的BaseAddress进行了设置,但是在创建ServiceHost的时候却抛出InvalidOperationException,并提示相应Address Scheme的BaseAddress找不到。我意识到这可能和WCF中用于判断服务寄宿方式的逻辑有关,于是我让这位朋友将相同的服务寄宿代码和配置迁移到GUI程序或者Console应用中,看看是否正常。结果如我所想,一切正常,个人觉得这应该是WCF的一个Bug。今天撰文与大家讨论,看看大家对这个问题有何见解。

一、问题重现

问题很容易重现,假设我们通过ASP.NET应用对服务CalculatorService进行寄宿,为了简单起见,我将服务契约和服务实现定义在一起。CalculatorService的定义如下面的代码片断所示:

 1: using System.ServiceModel;
2: namespace Artech.AspnetHostingDemo
3: {
4: [ServiceContract(Namespace = "urn:artech.com")]
5: public class CalculatorService
6: {
7: [OperationContract]
8: public double Add(double x, double y) { return x + y; }
9: }
10: }
下面是服务寄宿相关的配置,在<host>/<baseAddresses>配置节中为服务添加了一个Scheme为http的BaseAddress:http://127.0.0.1:3721/services,那么终结点的地址就可以定义为基于该BaseAddress的相对地址了:calculatorservice。

 1: <?xml version="1.0"?>
2: <configuration>
3: <system.serviceModel>
4: <services>
5: <service name="Artech.AspnetHostingDemo.CalculatorService">
6: <host>
7: <baseAddresses>
8: <add baseAddress="http://127.0.0.1:3721/services"/>
9: </baseAddresses>
10: </host>
11: <endpoint address="calculatorservice" binding="wsHttpBinding" contract="Artech.AspnetHostingDemo.CalculatorService"/>
12: </service>
13: </services>
14: </system.serviceModel>
15: <system.web>
16: <compilation debug="true"/>
17: </system.web>
18: </configuration>
我们把服务寄宿的代码定义在一个Web Page的Load事件中。但程序执行到到创建ServiceHost的时候,抛出如下图所示的InvalidOperationException异常。

下面是错误信息和异常的StackTrace:

 1: Could not find a base address that matches scheme http for the endpoint with binding WSHttpBinding. Registered base address schemes are [].
1: at System.ServiceModel.ServiceHostBase.MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding, UriSchemeKeyedCollection baseAddresses)
2: at System.ServiceModel.Description.ConfigLoader.LoadServiceDescription(ServiceHostBase host, ServiceDescription description, ServiceElement serviceElement, Action`1 addBaseAddress)
3: at System.ServiceModel.ServiceHostBase.LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, ServiceElement serviceSection)
4: at System.ServiceModel.ServiceHostBase.LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, String configurationName)
5: at System.ServiceModel.ServiceHostBase.ApplyConfiguration()
6: at System.ServiceModel.ServiceHostBase.InitializeDescription(UriSchemeKeyedCollection baseAddresses)
7: at System.ServiceModel.ServiceHost.InitializeDescription(Type serviceType, UriSchemeKeyedCollection baseAddresses)
8: at System.ServiceModel.ServiceHost..ctor(Type serviceType, Uri[] baseAddresses)
9: at Artech.AspnetHostingDemo._Default.Page_Load(Object sender, EventArgs e) in e:WCF ProjectsAspnetHostingDemoAspnetHostingDemoDefault.aspx.cs:line 16
10: at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
11: at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
12: at System.Web.UI.Control.OnLoad(EventArgs e) at System.Web.UI.Control.LoadRecursive()
13: at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)