ASP.NET 5系列教程(七)完结篇-解读代码
在本文中,我们将一起查看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,客户端同样可以接收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.NET 是ASP.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系列教程(七)完结篇-解读代码的更多相关文章
- 【ASP.NET Identity系列教程(一)】ASP.NET Identity入门
注:本文是[ASP.NET Identity系列教程]的第一篇.本系列教程详细.完整.深入地介绍了微软的ASP.NET Identity技术,描述了如何运用ASP.NET Identity实现应用程序 ...
- 【ASP.NET Identity系列教程(二)】运用ASP.NET Identity
注:本文是[ASP.NET Identity系列教程]的第二篇.本系列教程详细.完整.深入地介绍了微软的ASP.NET Identity技术,描述了如何运用ASP.NET Identity实现应用程序 ...
- 【ASP.NET Identity系列教程(三)】Identity高级技术
注:本文是[ASP.NET Identity系列教程]的第三篇.本系列教程详细.完整.深入地介绍了微软的ASP.NET Identity技术,描述了如何运用ASP.NET Identity实现应用程序 ...
- ASP.NET 5系列教程 (六): 在 MVC6 中创建 Web API
ASP.NET 5.0 的主要目标之一是统一MVC 和 Web API 框架应用. 接下来几篇文章中您会了解以下内容: ASP.NET MVC 6 中创建简单的web API. 如何从空的项目模板中启 ...
- Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇
Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇 本文主要内容: 1:spring cloud整合Eureka总结 本文是由凯哥(凯哥Java:kagejava ...
- CRL快速开发框架系列教程七(使用事务)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- ASP.NET Identity系列教程(目录)
$(document).ready(function(){ $("#hide").click(function(){ $(".en").hide(); }); ...
- ASP.NET 5系列教程 (四):向视图中添加服务和发布应用到公有云
向视图中添加服务 现在,ASP.NET MVC 6 支持注入类到视图中,和VC类不同的是,对类是公开的.非嵌套或非抽象并没有限制.在这个例子中,我们创建了一个简单的类,用于统计代办事件.已完成事件和平 ...
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(七) Exception Handling Application Block
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(七) Exception Handling Application Block 使用企业库异常处理应用程序模块的 ...
随机推荐
- MS sql server 基础知识回顾(二)-表连接和子查询
五.表连接 当数据表中存在许多重复的冗余信息时,就要考虑将这些信息建在另一张新表中,在新表中为原表设置好外键,在进行数据查询的时候,就要使用到连接了,表连接就好像两根线,线的两端分别连接两张表的不同字 ...
- springMVC + Spring + MyBatis 整合
整理下SSM(基于注解)的整合 1. web.xml 配置文件 <?xml version="1.0" encoding="UTF-8"?> < ...
- nginx伪静态
nginx 伪静态设置目录 /usr/local/nginx/conf/nginx/conf 1.域名绑定.server_name bbs.99vps.com; 2.网站根目录设置.root /ho ...
- C++STL学习笔记_(1)string知识
/*============================================ string是STL的字符串类型,通常用来表示字符串 = ======================== ...
- C#WebClient常见用法
System.Net.WebClient.DownloadFile(Uri address, String fileName) namespace:System.Net 参数: address:The ...
- Selenium2+python自动化12-操作元素(键盘和鼠标事件)
前言 在前面的几篇中重点介绍了一些元素的到位方法,到位到元素后,接下来就是需要操作元素了.本篇总结了web页面常用的一些操作元素方法,可以统称为行为事件 有些web界面的选项菜单需要鼠标悬停在某个元素 ...
- Python全栈之路3--set集合--三元运算--深浅拷贝--初识函数
一.上节课的重点回顾: 1.类名加括号其实就是执行类的__init__方法: 2.int a.创建方式 n1 = 123 #根据int类创建了一个对象 n2 = int(123) #根据int类创建一 ...
- [转]linux14.04下caffe的安装步骤
linux14.04下caffe的安装步骤 原文地址:http://blog.csdn.net/xiaoyang19910623/article/details/52997481?locatio ...
- (转)Quartus II和Modelsim的联合仿真(详细)
这篇文章不需要在modelsim中建库.映射.建工程等一些繁琐的步骤,直接使用modelsim中的默认work库.使用quartus+modelsim联合仿真. 首先推荐一篇文章 http://www ...
- 【jquery】:表单返回信息
第一个页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...