欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET 5系列教程(七)完结篇-解读代码

程序员文章站 2022-03-09 21:37:27
在本文中,我们将一起查看todocontroller 类代码。 [route] 属性定义了controller的url 模板: [route(api/[controller])]   所...

在本文中,我们将一起查看todocontroller 类代码。

[route] 属性定义了controller的url 模板:

[route(api/[controller])]

 

所有符合该模板类型的http 请求都会被路由到该controller。在本例中, 路由的命名规范为对应controller 的前缀,对于todocontroller 类,路由模板为 “api/todo”。

http 方法

[httpget][httppost][httpdelete] 属性定义为 controller 动作对应的http 方法 (另外也有[httpput][httppatch] 属性,在本示例中没有使用。)

[httpget]
public ienumerable 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实例:

https://localhost/api/todo/1
https://localhost/api/todo/42

不能写为:

https://localhost/api/todo/abc

 

注意 getbyid 和 deleteitem 方法同样拥有命名为id的参数。framework 会自动传递实参值到controller中。例如,如果url为https://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 getall()
{
    return _items;
}

返回对象的序列化信息被存储到response消息中。默认格式为json,客户端同样可以接收xml数据格式:

get https://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

1false

 

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 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 _items = new list();

        public ienumerable 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 _items = new list()
    //{
    //    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 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();
}

 

应用运行时, 一旦controller被创建,framework 自动注入todorepository 到controller中,它将作用于整个应用的生命周期。

在iis外独立部署应用

默认情况下,当你点击f5,应用会在iis express中运行。你可以在工具栏中看到iis express 图标。

ASP.NET 5系列教程(七)完结篇-解读代码

 

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 https://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”。

ASP.NET 5系列教程(七)完结篇-解读代码

 

点击f5运行app。visual studio 这时会运行启动weblistener 的控制台应用。

ASP.NET 5系列教程(七)完结篇-解读代码

打开,输入https://localhost:5000。你可以看到欢迎界面。

如果需要使用iis,在上一步骤中更改debug target 为 “iis express”即可。

 

 

目录:

asp.net 5系列教程 (一):领读新特性asp.net 5系列教程 (二):hello worldasp.net 5系列教程 (三):view components介绍asp.net 5系列教程 (四):向视图中添加服务和发布应用到公有云asp.net 5系列教程 (五):在visual studio 2015中使用grunt、bower开发web程序asp.net 5系列教程 (六): 在 mvc6 中创建 web apiasp.net 5系列教程(七)完结篇-解读代码