1. 程式人生 > >ASP.NET 5系列教程(七)完結篇-解讀代碼

ASP.NET 5系列教程(七)完結篇-解讀代碼

工程 display esp with isp bow use 一個 要求

??

在本文中,我們將一起查看TodoController 類代碼。

[Route] 屬性定義了Controller的URL 模板:

[Route("api/[controller]")]

全部符合該模板類型的HTTP 請求都會被路由到該controller。在本例中, 路由的命名規範為相應Controller 的前綴。對於TodoController 類。路由模板為 “api/todo”。

HTTP 方法

[HttpGet][HttpPost][HttpDelete] 屬性定義為 controller 動作相應的HTTP 方法 (另外也有[HttpPut][HttpPatch] 屬性,在本演示樣例中沒有使用。)

[HttpGet]
public IEnumerable<TodoItem> GetAll() {}
[HttpGet("{id:int}", Name = "GetByIdRoute")]
public IActionResult GetById (int id) {}
[HttpPost]
public void CreateTodoItem([FromBody] TodoItem item) {}
[HttpDelete("{id:int}")]
public IActionResult DeleteItem(int id) {}

GetById 和DeleteItem 方法中的參數能夠添加路由的傳遞信息。所以,路由模板更加完好的寫法為“api/[controller]/{id:int}”。

在 “{id:int}” 中,id是變量。而 “:int” 代表參數為整型。下面為URLs實例:

http://localhost/api/todo/1
http://localhost/api/todo/42

不能寫為:

http://localhost/api/todo/abc

註意 GetById 和 DeleteItem 方法相同擁有命名為id的參數。

framework 會自己主動傳遞實參值到Controller中。比如,假設URL為http://localhost/api/todo/42。id的值則為42,這個過程為參數綁定。

CreateTodoItem 方法代表了還有一個參數綁定:

[HttpPost]
public void CreateTodoItem([FromBody] TodoItem item) {}

[FromBody] 屬性指定framework 從Request中反序列化TodoItem 參數。

下面是request和controller 動作的相應列表:

Request

Controller Action

GET /api/todo

GetAll

POST /api/todo

CreateTodoItem

GET /api/todo/1

GetById

DELETE /api/todo/1

DeleteItem

GET /api/todo/abc

none – returns 404

PUT /api/todo

none – returns 404

最後兩個樣例因為其它用途返回404 錯誤。

比如 ‘GET /api/todo/abc‘, ‘abc‘ 實參是GetById 方法中要求的整型數據類型。

Action 返回值

TodoController 類展示了多種 controller action的返回值方法。

GetAll 方法返回了一個CLR 對象。

[HttpGet]
public IEnumerable<TodoItem> GetAll()
{
    return _items;
}

返回對象的序列化信息被存儲到Response消息中。

默認格式為JSON,client相同能夠接收XML數據格式:

GET http://localhost:5000/api/todo HTTP/1.1
User-Agent: Fiddler
Host: localhost:5000
Accept: application/xml

Response:

HTTP/1.1 200 OK
Content-Type: application/xml;charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Date: Thu, 30 Oct 2014 22:40:10 GMT
Content-Length: 228
<ArrayOfTodoItem xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TodoApi.Models"><TodoItem><Id>1</Id><IsDone>false</IsDone><Title>First Item</Title></TodoItem></ArrayOfTodoItem>

GetById 方法返回了一個IActionResult 接口:

[HttpGet("{id:int}", Name = "GetByIdRoute")]
public IActionResult GetById (int id)
{
    var item = _items.FirstOrDefault(x => x.Id == id);
    if (item == null)
    {
        return HttpNotFound();
    }
    return new ObjectResult(item);
}

假設有URL中相應的id,則這種方法會返回ObjectResult 。返回 ObjectResult 和返回CLR 模型相同。

而方法中規定返回類型為IActionResult。因此,該方法能夠返回不同的類型。

假設沒有相應ID,則返回HttpNotFound。頁面會拋出404 錯誤。

最後, CreateTodoItem 方法展示怎樣直接在方法中設置返回值:

[HttpPost]
public void CreateTodoItem([FromBody] TodoItem item)
{
    // (some code not shown here)
    Context.Response.StatusCode = 201;
    Context.Response.Headers["Location"] = url;
}

這樣的方法的缺陷是非常難進行單元測試。(關於測試相關討論,能夠參考Unit Testing Controllers in ASP.NET Web API)。

依賴註入

MVC 6 內置了依賴註入功能。

下面,讓我們創建一個包括ToDo列表的repository 類。

首先。為repository定義一個接口:

using System.Collections.Generic;
namespace TodoApi.Models
{
    public interface ITodoRepository
    {
        IEnumerable<TodoItem> AllItems { get; }
        void Add(TodoItem item);
        TodoItem GetById(int id);
        bool TryDelete(int id);
    }
}

之後定義詳細實現方法。

using System;
using System.Collections.Generic;
using System.Linq;
namespace TodoApi.Models
{
    public class TodoRepository : ITodoRepository
    {
        readonly List<TodoItem> _items = new List<TodoItem>();
        public IEnumerable<TodoItem> AllItems
        {
            get
            {
                return _items;
            }
        }
        public TodoItem GetById(int id)
        {
            return _items.FirstOrDefault(x => x.Id == id);
        }
        public void Add(TodoItem item)
        {
            item.Id = 1 + _items.Max(x => (int?)x.Id) ?

? 0;

            _items.Add(item);
        }
        public bool TryDelete(int id)
        {
            var item = GetById(id);
            if (item == null)
            {
                return false;
            }
            _items.Remove(item);
            return true;
        }
    }
} 

使用構造函數註入repository 到 controller:

[Route("api/[controller]")]
public class TodoController : Controller
{
    // Remove this code:
    //static readonly List<TodoItem> _items = new List<TodoItem>()
    //{
    //    new TodoItem { Id = 1, Title = "First Item" }
    //};
    // Add this code:
    private readonly ITodoRepository _repository;
    public TodoController(ITodoRepository repository)
    {
        _repository = repository;
    }

然後更新controller 方法到repository:

[HttpGet]
public IEnumerable<TodoItem> GetAll()
{
    return _repository.AllItems;
}
[HttpGet("{id:int}", Name = "GetByIdRoute")]
public IActionResult GetById(int id)
{
    var item = _repository.GetById(id);
    if (item == null)
    {
        return HttpNotFound();
    }
    return new ObjectResult(item);
}
[HttpPost]
public void CreateTodoItem([FromBody] TodoItem item)
{
    if (!ModelState.IsValid)
    {
        Context.Response.StatusCode = 400;
    }
    else
    {
        _repository.Add(item);
        string url = Url.RouteUrl("GetByIdRoute", new { id = item.Id }, Request.Scheme, Request.Host.ToUriComponent());
        Context.Response.StatusCode = 201;
        Context.Response.Headers["Location"] = url;
    }
}
[HttpDelete("{id}")]
public IActionResult DeleteItem(int id)
{
    if (_repository.TryDelete(id))
    {
        return new HttpStatusCodeResult(204); // 201 No Content
    }
    else
    {
        return HttpNotFound();
    }
}

我們須要註冊repository到依賴註入系統才幹使其啟作用。

在Startup 類中。加入下面代碼:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    // New code
    services.AddSingleton<ITodoRepository, TodoRepository>();
}

應用執行時, 一旦controller被創建。framework 自己主動註入TodoRepository 到controller中,它將作用於整個應用的生命周期。

在IIS外獨立部署應用

默認情況下,當你點擊F5,應用會在IIS Express中執行。你能夠在工具欄中看到IIS Express 圖標。

技術分享

ASP.NET 5.0 能夠部署到不同的服務器中,在本節中,我們將使用可執行在IIS外的WebListener。

註意:將應用部署在IIS中仍有諸多的優勢,比如安全性、進度管理等。

在project.json 文件。加入Microsoft.AspNet.Server.WebListener 包:

"dependencies": {
    "Microsoft.AspNet.Server.IIS": "1.0.0-beta1",
    "Microsoft.AspNet.Diagnostics": "1.0.0-beta1",
    "Microsoft.AspNet.Mvc": "6.0.0-beta1",
    // New:
    "Microsoft.AspNet.Server.WebListener": "6.0.0-beta1"
},

接下來加入下面選項到project.json。

{
    // Other sections not shown
    "commands": {
        "web ": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000"
    }
}

“commands” 中包括了能夠傳遞給K 執行時的提前定義指令列表。在這個樣例中。 “web” 是指令名稱。它能夠是隨意實際指令名稱值。

Microsoft.AspNet.Hosting 程序集用於部署ASP.NET 5.0 應用。

· --server 標記用於聲明服務器,在這個樣例中為WebListener。

· --server.urls 標記提供須要監聽的URL。

保存project.json 文件。

在Solution Explorer中,右鍵點擊工程選擇Properties。在 Properties 欄,點擊Debug。在Debug target 下。更改 “IIS Express” 為 “web”。

技術分享

點擊F5執行App。Visual Studio 這時會執行啟動WebListener 的控制臺應用。

技術分享

打開瀏覽器,輸入http://localhost:5000。

你能夠看到歡迎界面。

假設須要使用IIS。在上一步驟中更改Debug Target 為 “IIS Express”就可以。

這篇文章為本系列文章的最後一篇,感謝大家的關註。本系列的全部教程旨在幫助大家更好的理解ASP.NET 5。以便更好的進行開發。同一時候,也能夠借助一些開發工具來助力開發過程。

ComponentOne Studio for ASP.NETASP.NET平臺上的一整套完備的開發工具包,用於在各種瀏覽器中創建和設計具有現代風格的Web應用程序。

原文鏈接:http://www.asp.net/vnext/overview/aspnet-vnext/create-a-web-api-with-mvc-6

文件夾:

  • ASP.NET 5系列教程 (一):領讀新特性
  • ASP.NET 5系列教程 (二):Hello World
  • ASP.NET 5系列教程 (三):view components介紹
  • ASP.NET 5系列教程 (四):向視圖中加入服務和公布應用到公有雲
  • ASP.NET 5系列教程 (五):在Visual Studio 2015中使用Grunt、Bower開發Web程序
  • ASP.NET 5系列教程 (六): 在 MVC6 中創建 Web API
  • ASP.NET 5系列教程(七)完結篇-解讀代碼

ASP.NET 5系列教程(七)完結篇-解讀代碼