使用網站作為WCF服務宿主的幾種做法


內容摘要

這一篇文章探討使用網站作為WCF服務宿主的幾種做法,我將從最基本的svc文件的方式,演化成為無svc文件的方式,並且在最后介紹REST與路由規則結合的做法。

本文所講解的WCF功能,是基於WCF 4.0這個版本。我所采用的開發工具是Visual Studio 2012. 本文范例代碼可以通過 Web-host-sample.zip  下載。

本文不是WCF的入門文檔,有關WCF的典型使用場景和一些基礎知識,可以參考我之前的兩篇文章

 

范例說明

本文所采用的范例是相當簡單的,我已經定義的合約和服務如下

using System.ServiceModel;


namespace Web
{
    [ServiceContract]
    public interface IHelloService
    {
        [OperationContract]
        string SayHello();
    }

    public class HelloService : IHelloService
    {
        public string SayHello()
        {
            return "Hello,world";
        }
    }
}

 

基本做法(采用svc文件的方式)

WCF 4.0以前的版本,我們都是采用svc文件作為服務的宿主文件。例如,我們可以定義如下這樣一個HelloService.svc,其內容如下

<%@ ServiceHost Service="Web.HelloService" %>

 

需要注意的是,你在Visual Studio中無法直接添加一個空白的svc文件,我一般是選擇Text File這個模板,但是在命名的時候,將其修改為svc后綴。如下圖所示

image

 

定義好這個文件后,可以直接在瀏覽器中查看該服務的描述,如下圖所示。此時表示該服務已經被正確地宿主了。

image

 

 

無svc文件的做法

上面這個做法雖然不難,但每次都要手工創建那個svc文件,總是覺得有些多余。那么是否有辦法免去這個步驟呢?WCF 4.0提供了這種可能性。

我們需要做的是,在配置文件中指定一個虛擬的文件路徑,並且將其與服務進行關聯起來。如下所示(請重點關心粗體部分)

<?xml version="1.0"?>

<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->

<configuration>
  <system.web>
    <compilation debug="true"
                 targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>


  <system.serviceModel>

    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    
 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
                               multipleSiteBindingsEnabled="true">
      <serviceActivations>
        <add service="Web.HelloService"
             relativeAddress="MyService.svc"/>
      </serviceActivations>
    </serviceHostingEnvironment>
  </system.serviceModel>
</configuration>

為了與上面的例子區分,我特意在這里定義relativeAddress的時候,用了不一樣的名稱。你沒有看錯,只需要這樣定義就可以直接訪問到MyService.svc,而不要求你實際去創建這個文件。

image

看起來挺不錯的,但仍然有一點點美中不足就是,這個虛擬地址,必須有一個后綴名(而且推薦使用svc),對於一般的用戶而言,可能並不是特別友好。是否有辦法將這個地址進一步地簡化呢?

對於標准的SOAP服務來說,應該是沒有辦法了。但是如果是REST服務,倒是有另外一個方法來實現。請繼續閱讀下面的說明。

 

REST與路由規則

為了做演示,我將服務稍作修改,使得其成為所謂的RESTful的服務。請注意紅色粗體部分。

using System.ServiceModel;
using System.ServiceModel.Web;


namespace Web
{
    [ServiceContract]
    public interface IHelloService
    {
        [OperationContract]
   [WebGet]
        string SayHello();
    }

    public class HelloService : IHelloService
    {
        public string SayHello()
        {
            return "Hello,world";
        }
    }
}

 

然后我們還需要添加有關的配置文件設置(請注意粗體部分)

<?xml version="1.0"?>

<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->

<configuration>
  <system.web>
    <compilation debug="true"
                 targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>


  <system.serviceModel>

    <services>
      <service name="Web.HelloService">
        <endpoint contract="Web.IHelloService"
                  binding="webHttpBinding"></endpoint>
      </service>
    </services>


    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>

 <endpointBehaviors> <behavior> <webHttp helpEnabled="true"></webHttp> </behavior> </endpointBehaviors>
    </behaviors>


    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
                               multipleSiteBindingsEnabled="true">
      <serviceActivations>
        <add service="Web.HelloService"
             relativeAddress="MyService.svc"/>
      </serviceActivations>
    </serviceHostingEnvironment>
  </system.serviceModel>
</configuration>

 

為了使用我們自己想要的地址(虛擬地址)來訪問這個服務,我們可以結合路由規則來實現(這個也是WCF 4.0新增的特性)

image

將如下代碼添加到Global.asax文件中

using System;
using System.ServiceModel.Activation;
using System.Web.Routing;

namespace Web
{
    public class Global : System.Web.HttpApplication
    {
        private void RegisterRoutes()
        {
            WebServiceHostFactory factory = new WebServiceHostFactory();
            RouteTable.Routes.Add(new ServiceRoute("HelloService", factory,
               typeof(HelloService)));
  
        }

        protected void Application_Start(object sender, EventArgs e)
        {
            RegisterRoutes();
        }

        protected void Session_Start(object sender, EventArgs e)
        {

        }

        protected void Application_BeginRequest(object sender, EventArgs e)
        {

        }

        protected void Application_AuthenticateRequest(object sender, EventArgs e)
        {

        }

        protected void Application_Error(object sender, EventArgs e)
        {

        }

        protected void Session_End(object sender, EventArgs e)
        {

        }

        protected void Application_End(object sender, EventArgs e)
        {

        }
    }
}

我們在這里是定義了一個路由規則,凡是請求HelloService這個虛擬路徑的(注意,沒有帶任何后綴),就路由到我們的服務。在瀏覽器中我們可以看到效果如下

image

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM