問題
怎么樣將 Asp.Net Web Api 加入到現有的 Asp.Net MVC 項目中
解決方案
在 Visual Studio 2012 中就已經把 Asp.Net Web Api 自動地整合到了 MVC 項目模板中。自 Visual Studio 2013 以后,創建 ASP.Net Web應用程序使用的是一種新的"One ASP.NET"項目向導,在這里可以選擇相應的組件,例如,MVC,Web API,WebForm,等等。"One ASP.NET" 是基于微軟統一 ASP.NET平臺的概念。如圖所示 圖1-1
圖1-1. "One ASP.NET" 項目向導,在一個項目中使用 MVC 和 Web Api
有意思的是,如果你選擇了 Web API 項目模板,MVC 的復選框是自動被選中,因為ASP.NET Web API Help Pages 依賴于 MVC 來提供內容。
你也可以在任何已經存在的 MVC 項目中他通過 NuGet 安裝"Install-Package Microsofty.Asp.Net.WebApi"來添加 Web API。
其實,上面兩種,在 ASP.NET Web 應用項目中,添加 Web API 的方式是等效的,因為項目向導也僅僅是從NuGet 中安裝了 ASP.NET Web API。
工作原理
ASP.NET Web API 的構建圍繞著一個叫做 System.Web.IHttpAsyncHandler 的異步 HTTP Handler,如演示清單1-1.Handlers 是 ASP.NET 的主干,就是一些可以攔截和處理發送給服務器的 HTTP 請求以及響應相應的請求給客戶端的類。
清單 1-1. IhttpAsyncHandler 的定義
1
2
3
4
5
6
|
public interface IHttpAsyncHandler : object , IHttpHandler { System.IAsyncResult BeginProcessRequest(HttpContext context, System.AsyncCallback cb, object extraData); void EndProcessRequest(System.IAsyncResult result); } |
事實上,這個和 ASP.NET MVC 框架的體系結構沒有多大的不同,他也是位于 Http Hander 上層。其實,他們的框架都是軟件工程中復雜的一部分,和常規的 IHttpHandler 或 IHttpAsyncHandler 沒有什么特別之處,也許,以前你就創建過處理各種處理基于 HTTP 的工作。
Web API IHttpAsyncHandler 的大致結構——HttpControllerHandler 和他的公共成員,如清單1-2所示
清單 1-2. HttpControllerHandler 的公共成員
1
2
3
4
5
6
|
public class HttpControllerHandler : HttpTaskAsyncHandler { public HttpControllerHandler(RouteData routeData); public HttpControllerHandler(RouteData routeData, HttpMessageHandler handler); public override Task ProcessRequestAsync(HttpContext context); } |
MVC 和 Web API 的主要不同是從版本2開始的。Web API Handler-HttpControllerHandler,是HttpTaskAsyncHandler 的一個子類。在 MVC 的版本中,MvcHandler,實現了接口IHttpAsyncHandler。HttpTaskAsyncHandler是在 .NET 4.5 才有的,而 .NET 4.5 是 Web API 2 才支持。
當在同一個 ASP.NET 進程中運行 MVC 和 Web API 的時候,ASP.NET 使用的是HttpApplication。MapRequestHandler事件來決定哪個 HTTP handler 被翻牌子,來處理請求。在這個階段,進行路由匹配,請求進入到相應匹配路由的 IRouteHandler。IRouteHandler 的唯一目的就是創建一個可以處理請求的 IHttpHandler。
如果 IRouteHandler 是 HttpControllerRouteHandler(Web API 路由),那么,被選擇的 Web API 地址路徑的請求將被終結在 HttpControllerRouteHandler。相反的,如果路由處理器是 MvcRouteHandler,那么,MVC 的地址路徑由 MvcHandler 接管。
代碼演示
這一部分要演示的是,ASP.NET MVC 和ASP.NET Web API 將運行在在同一個進程中,他們可以輕而易舉的共享狀態,例如,靜態對象或者 Global.asax 事件。另外,配置文件 web.config 對于兩個框架也是通用的。
清單 1-3 展示了兩個Controller,MVC Controller 和 ASP.NET Web API Controller,他們可以在一個ASP.NET Web 應用程序共存。值得注意的是,因為他們在不同的命名空間中,所以他們設置可以使用相同的名稱。此外,他們可以根據需要共享同一個 model(DTO),非常完美。
清單 1-3. 簡單的 MVC 和 Web API 控制器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public class Book { public int Id { get ; set ; } public string Author { get ; set ; } public string Title { get ; set ; } public string Link { get ; set ; } } Namespace WebApplication.Controllers.Mvc { public class BooksController : Controller { public ActionResult Details( int id) { var book = Books.List.FirstOrDefault(x => x.Id == id); if (book == null ) return new HttpNotFoundResult(); return View(book); } } } namespace WebApplication.Controllers.WebApi { public class BooksController : ApiController { public Book GetById( int id) { var book = Books.List.FirstOrDefault(x => x.Id == id); if (book == null ) throw new HttpResponseException(HttpStatusCode.NotFound); return book; } } } |
避免兩個框架沖突的關鍵是謹慎驚醒路由設置,為了方便,默認情況下, ASP.NET Web API 將 /api 占位在 URI 下,這樣,所有根級別的 URL 將被 MVC 處理。通常情況下,Web API 路由是被定義在 WebApiConfig靜態類中,使用 HttpConfiguration 對象和他的 Route 屬性。MVC 的路由被定義在 RouteConfig 靜態類中,直接使用 System.Web.RouteCollection。兩個框架路由的默認定義顯示下,清單 1-4.
清單 1-4. Web API 和 MVC 的默認路由
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//Web API 路由配置 public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 配置和服務 // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi" , routeTemplate: "api/{controller}/{id}" , defaults: new { id = RouteParameter.Optional } ); } } //MVC 路由配置 public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" ); routes.MapRoute( name: "Default" , url: "{controller}/{action}/{id}" , defaults: new { controller = "Home" , action = "Index" , id = UrlParameter.Optional } ); } } |
第三部分將專門介紹路由,如清單1-4所示,下面的地址是 ASP.NET 應用程序暴露出來的
-
/api/books/{id} 路由到 ASP.NET Web API
-
/books/details/{id} 路由到 ASP.NET MVC
文章列表