zoukankan      html  css  js  c++  java
  • 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,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 图标。

    clip_image001

    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”。

    clip_image001[5]

    点击F5执行App。Visual Studio 这时会执行启动WebListener 的控制台应用。

    clip_image001[7]

    打开浏览器,输入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

    文件夹:

  • 相关阅读:
    关于sharepoint 2010 匿名环境下打开office文档避免登录框出现的解决办法
    sharepoint user profile
    烙饼排序1(最基本的排序) 下
    使用DevExpress.XtraReports.UI.XtraReport 设计报表的时候如何格式化字符串 下
    C#排序1(冒泡排序、直接排序、快速排序) 下
    C# winform中自定义用户控件 然后在页面中调用用户控件的事件 下
    单向非循环列表的简单操作 下
    C# 格式化字符串(网址) 下
    (转)C# Enum,Int,String的互相转换 枚举转换 下
    烙饼排序2(比较高效率的方法) 下
  • 原文地址:https://www.cnblogs.com/llguanli/p/7073104.html
Copyright © 2011-2022 走看看