.Net Framework 4.5與Visual Studio 11 - WCF Web API (2)

by vivid 1. 二月 2012 01:00

.NET Magazine國際中文電子雜誌
者:許薰尹
稿:張智凱
文章編號:N120212101
出刊日期:2012/02/01

本文延續《.Net Framework 4.5與Visual Studio 11 - WCF Web API (1)》一文的內容來探討WCF Web API提供的新功能,利用Visual Studio 11 Developer Preview開發工具來開發服務程式碼,讓你更容易設計支援REST類型的WCF服務。由於本文撰寫時使用的工具是Visual Studio 11 Developer Preview,而WCF Web API 則是Preview 6版,因此本文探討的內容在正式版上市時可能不適用。

延續前一篇文章《.Net Framework 4.5與Visual Studio 11 - WCF Web API (1)》的情境,介紹如何透過WCF Web API來提供新增、刪除、修改資料的功能。

定義介面

首先為WCF服務設計好用來新增、刪除以及修改資料所需的操作(Operation)。在IService.cs檔案中,為IService介面新增CreateEmployee、DeleteEmployee與UpdateEmployee三個方法定義,IService1介面的程式碼看起來如下:

namespace WCFWebLib
{
     [ServiceContract]
    public interface IService1
    {
        [WebGet ( UriTemplate = "/employees" )]
         [OperationContract]
         List<Employee> GetEmployees ( );

        [WebGet ( UriTemplate = "/employees/{id}" )]
        [OperationContract]
         Employee GetEmployeeByID ( int id );

        [WebInvoke ( UriTemplate = "/employees" , Method = "POST" )]
         HttpResponseMessage<Employee>
            CreateEmployee (  HttpRequestMessage<Employee> request);

        [WebInvoke ( UriTemplate = "/employees/{id}" , Method = "DELETE" )]
         Employee DeleteEmployee ( int id );

        [WebInvoke ( UriTemplate = "/employees/{id}" , Method = "PUT" )]
        Employee UpdateEmployee (Employee emp );

    }   
}

CreateEmployee、DeleteEmployee與UpdateEmployee方法上方套用了WebInvoke Attribute,並分別設定Method為POST、DELETE與PUT,以處理HTTP POST、DELETE與PUT請求,在這個範例中,分別以HTTP POST、DELETE與PUT請求來進行資料的新增、刪除與修改。

WCF Web API除了新增一個HTTPClient類別來傳送HTTP請求、接收HTTP回應之外,另設計了HTTPRequestMessage與HttpResponseMessage類別來代表HTTP請求與回應的訊息。

實作方法

定義好介面之後,接著在Service1類別中實作CreateEmployee、DeleteEmployee與UpdateEmployee三個方法,CreateEmployee方法的程式碼看起來如下:

public System.Net.Http.HttpResponseMessage<Employee>
         CreateEmployee ( HttpRequestMessage<Employee> request )
     {
         HttpResponseMessage<Employee> response = null;

       Employee emp = ( Employee ) request.Content.ReadAsAsync ( ).Result;

         if ( emp == null )
         {
             response = new HttpResponseMessage<Employee> (
                 HttpStatusCode.BadRequest );
         }
         else
         {
           
             Store.Add (emp ); 
             response = new HttpResponseMessage<Employee> (
                 emp , HttpStatusCode.Created );

             response.Headers.Location = new Uri (
                 request.RequestUri , emp.EmployeeID.ToString ( ) );
         }
         return response;

     }

範例中CreateEmployee方法用來新增資料,此方法將會回傳一個HttpResponseMessage<Employee>型別的物件,以便傳回執行結果,像是HTTP狀態碼等資訊。方法中先讀取HttpRequestMessage<Employee>訊息內文是否包含一個Employee物件,若沒有則回傳HTTP狀態碼 400 (HttpStatusCode.BadRequest列舉值)。若包含一個Employee物件,則回傳HTTP狀態碼201 (HttpStatusCode.Created列舉值),並利用HTTP Header傳回URI等資訊。

DeleteEmployee與UpdateEmployee方法雷同,先叫用GetEmployeeById方法來取得欲刪除與修改的Employee物件 ,若找不到時將丟出HttpResponseException例外錯誤,並傳回狀態碼。若找到欲刪除與修改的Employee物件再進行刪除或修改的動作。

public Employee DeleteEmployee ( int id )
{
    Employee emp = Store.GetEmployeeById ( id );
    if ( emp == null )
    {

        throw new HttpResponseException ( HttpStatusCode.NotFound );
    }
    Store.Delete ( emp );
    return emp;

}

public Employee UpdateEmployee ( Employee emp  )
{

    var toUpdate = Store.GetEmployeeById ( emp.EmployeeID );
    if ( toUpdate == null )
    {
        throw new HttpResponseException ( HttpStatusCode.NotFound );
    }

    Console.WriteLine ( "Service..." );
    Console.WriteLine ("New Name:" +  emp.EmployeeName );
    Console.WriteLine ( "Original Name:" + toUpdate.EmployeeName );
    toUpdate.EmployeeName = emp.EmployeeName;
    return toUpdate;

}

更新資料用戶端程式

用戶端利用HttpClient類別的PutAsync方法執行呼叫,使用HTTP PUT動詞,利用非同步方式來進行資料的修改動作。在本文的範例中,想要修改1號員工的EmployeeName屬性,將其值設定為「New Mary」:

static void Main ( string [ ] args )
{
    HttpClient client = new HttpClient ( );
    client.BaseAddress = new Uri ( "http://localhost:8000/api/" );

    Employee emp = new Employee ( ) { EmployeeID = 1 , EmployeeName = "New Mary" };

    string id = "1";
    var resp = client.PutAsync ( "employees/"+id ,
        new ObjectContent<Employee> ( emp ,
                XmlMediaTypeFormatter.DefaultMediaType ) )
                .ContinueWith ( r =>
                {

                    Console.WriteLine ( "Employee Updated..." );
                    Console.WriteLine ( r.Result.ToString ( ) );

                    r.Result.Content.ReadAsAsync<Employee> ( ).ContinueWith ( b =>
                    {

                        Employee e = b.Result;
                        Console.WriteLine ( "執行結果:");
                        Console.WriteLine ( "=========" );
                        Console.WriteLine ( "員工名稱:" + e.EmployeeName );
                    } );
                } );

    Console.WriteLine ( "Press [enter] to quit." );
    Console.ReadLine ( );

}

此範例執行的結果請參考下圖所示,服務端程式執行結果:

clip_image002

圖 1:修改資料,服務端程式執行結果。

用戶端程式執行結果,請參考圖2所示:

clip_image004

圖 2:修改資料,用戶端程式執行結果。

 

刪除資料用戶端程式

刪除資料時,叫用的是HttpClient類別的DeleteAsync方法,以非同步方式進行刪除的作業。

static void Main ( string [ ] args )
        {
            HttpClient client = new HttpClient ( );
            client.BaseAddress = new Uri ( "http://localhost:8000/api/" );
            string id = "1";
            var resp = client.DeleteAsync(String.Format ( "employees/{0}" , id ) );

            Console.WriteLine ( resp.Result);

            Console.WriteLine ( "Press [enter] to quit." );
            Console.ReadLine ( );

        }

 

刪除資料的範例用戶端執行結果如下圖所示:

clip_image006

圖 3:刪除資料,用戶端程式執行結果。

 

新增資料用戶端程式

若要新增資料,則使用HTTP POST動詞,利用HttpClient 類別PostAsync方法來進行:

static void Main ( string [ ] args )
  {
      HttpClient client = new HttpClient ( );
      client.BaseAddress = new Uri ( "http://localhost:8000/api/" );

      Employee emp = new Employee ( ) { EmployeeID = 4 , EmployeeName = "Landy" };

      var resp = client.PostAsync ( "employees/" ,
          new ObjectContent<Employee> ( emp ,
                  XmlMediaTypeFormatter.DefaultMediaType ) )
                  .ContinueWith ( r =>
                  {

                      Console.WriteLine ( "Employee Added..." );
                      Console.WriteLine ( r.Result.ToString ( ) );

                     
                  } );

 

      Console.WriteLine ( "Press [enter] to quit." );
      Console.ReadLine ( );

  }

用戶端執行結果,請參考圖4所示:

clip_image008

圖 4:新增資料,用戶端程式執行結果。

 

在ASP.NET裝載服務

若不想為WCF撰寫裝載程式,可以將WCF服務直接裝載在IIS上執行,本文最後介紹如何將使用 WCF Web API類型的服務裝載在ASP.NET類型的專案上。你可以在建立專案時,直接選擇使用Web應用程式,從Visual Studio 11 Developer Preview的「File」-「New」-「Project」,開啟「New Project」對話盒,然後選取程式語言,如Visual C#,再選擇「Web」-「ASP.NET MVC 4 Web Application」範本,取一個名字後按下「OK」按鈕建立專案,請參考圖5所示:

clip_image010

圖 5:建立「ASP.NET MVC 4 Web Application」專案。

接著會出現「New ASP.NET MVC 4 Project」對話盒,在這個範例中只需要建立Empty類型的範本即可,選取「Empty」範本之後,按下「OK」按鈕,請參考圖6所示:

clip_image012

圖 6:選取「Empty」範本。

和《.Net Framework 4.5與Visual Studio 11 - WCF Web API (1)》一文介紹的內容一樣,要先安裝NuGet Packages。在「Solution Explorer」視窗中選取你的專案,按滑鼠右鍵,從突顯式選單中,選取「Manage NuGet Packages」,請參考圖7所示:

clip_image014

圖 7:安裝NuGet Packages。

在「Manage NuGet Packages」對話盒Online選單中搜尋「WebApi.All」,然後按下「Install」按鈕,請參考圖8所示。

clip_image016

圖 8:安裝「WebApi.All」。

在專案中,新增一個Employee類別。從「Solution Explorer」視窗,選取專案,按滑鼠右鍵,從突顯式選單中,選取「Add」-「Class」,加入一個Employee類別,宣告類別中包含兩個屬性,分別是int型別的EmployeeID屬性,以及string型別的EmployeeName屬性:

public class Employee
    {
        public int EmployeeID { get; set; }
        public string EmployeeName { get; set; }
    }

按相同的方式新增EmployeeRepository類別:

public class EmployeeRepository
    {

        List<Employee> emps = new List<Employee> ( );
        public EmployeeRepository ( )
        {
            Add ( new Employee ( ) { EmployeeID = 1 , EmployeeName = "Mary" } );
            Add ( new Employee ( ) { EmployeeID = 2 , EmployeeName = "Candy" } );
            Add ( new Employee ( ) { EmployeeID = 3 , EmployeeName = "Judy" } );

        }
        public void Add ( Employee emp )
        {

            emps.Add ( emp );
        }

        public void Delete ( Employee emp )
        {
            emps.Remove ( emp );
        }

        public List<Employee> GetEmployees ( )
        {
            return emps;
        }

        public Employee GetEmployeeById ( int id )
        {
            return emps.Find ( ( x ) => x.EmployeeID == id );
        }
    }

 

 

下一個步驟是新增一個EmployeeService類別來做為服務,您可以不必從定義介面開始,然後再實作介面。另外,在WCF Web API Preview 6版,宣告WCF Web API所需的類別上可以省略不用標識ServiceContract Attribute,服務的方法也不用標示OperationContract Attribute。但方法的上方要套用WebGet Attribute,並設定好UriTemplate將URL與方法對應在一起:

//[ServiceContract]
    public class EmployeeService
    {
        static EmployeeRepository Store = new EmployeeRepository ( );

        [WebGet ( UriTemplate = "/employees" )]
        public List<Employee> GetEmployees ( )
        {
            return Store.GetEmployees ( );
        }    

    }

 

專案中預設會包含一個Global.asax.cs檔案,在檔案的上方引用以下命名空間:

using Microsoft.ApplicationServer.Http.Activation;
using System.ServiceModel.Activation;

Global.asax.cs檔案中預設定義一個MvcApplication類別,在類別之中宣告一個HttpServiceHostFactory型別的變數:

static HttpServiceHostFactory _factory = null;

然後在Global.asax.cs檔案Application_Start方法中加入以下程式碼,這段程式碼的主要用途是將http://localhost:4462/api/employees

格式的URL對應到EmployeeService類別:

_factory = new HttpServiceHostFactory ( );
RouteTable.Routes.Add ( new ServiceRoute ( "api" , _factory , typeof ( EmployeeService ) ) );

完成這個動作之後,��可以進行測式。按F5執行網站,開啟瀏覽器,在URL上輸入 (注意localhost後方的埠號可能和您的專案不同):

http://localhost:4462/api/employees

網頁上便將查詢回來的Employee資料以XML方式呈現,請參考圖9所示:

clip_image018

圖 9:將查詢回來的Employee資料以XML方式呈現。

使用JavaScript與jQuery呼叫服務

在這個小節,我們將撰寫一個ASP.NET Web表單,以JavaScript和jQuery來呼叫服務。首先在專案中加一個Webform1.aspx,從「Solution Explorer」視窗,選取專案,按滑鼠右鍵,從突顯式選單中,選取「Add」-「New Item」,加入一個「Web Form」。

在Form標籤之中加入一個div,將id設定為emp:

<form id="form1" runat="server">
<div id="emp">

</div>
</form>

 

引用jquery函式庫,並撰寫以下JavaScript,在網頁載入時,叫用getJSON方法,取回所有員工資料,然後利用each方法,將EmployeeName顯示在li清單項目上:

  <script src="Scripts/jquery-1.6.2.js" type="text/javascript"></script>
  <script type="text/javascript">
        $(document).ready(function () {
            $.getJSON("api/employees",
                function (data) {
                $('#emp').empty();
                $.each(data, function (key, val) {
                    $('<li/>', { html: val.EmployeeName })
                    .data({ employee: val })
                    .appendTo($('#emp'));
                });
            });
        });
</script>

按F5執行網站,開啟瀏覽器,參考網頁執行結果:

clip_image020

圖 10:使用JavaScript與jQuery呼叫服務。

啟用WCF Web API Test Client

WCF Web API提供一個用戶端測試的工具程式,可以在開發階段讓程式設計師用來檢測服務的運行。若要使用這個工具程式來進行測試,您可以修改專案Application_Start方法如下,將HttpConfiguration類別的EnableTestClient屬性設定為true ,然後將HttpConfiguration設定給HttpServiceHostFactory的Configuration屬性,參考以下程式碼所示:

protected void Application_Start ( )
        {

            var config = new HttpConfiguration ( ) { EnableTestClient = true };
            _factory = new HttpServiceHostFactory ( ) { Configuration = config };
            RouteTable.Routes.Add ( new ServiceRoute ( "api" , _factory , typeof ( EmployeeService ) ) );

        }

 

按F5執行網站,開啟瀏覽器,輸入以下URL:

http://localhost:4462/api/test/home

就可以看到WCF Web API Test Client的測試頁面了,請參考圖11所示。

clip_image022

圖 11:WCF Web API Test Client的測試頁面。

若服務不是裝載在IIS上執行,則裝載程式啟動前可以加入以下程式碼,利用HttpConfiguration類別啟用Test Client:

var config = new HttpConfiguration ( ) { EnableTestClient = true };
            var host = new HttpServiceHost (
            typeof ( Service1 ) ,config, "http://localhost:8000/api/" );      
            host.Open ( );
            Console.WriteLine ( "Service is running..." );
            Console.ReadLine ( );

Tags:

WCF Web API | Visual Studio | .NET Magazine國際中文電子雜誌 | 許薰尹Vivid Hsu

NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List