.net core mvc启动顺序以及主要部件4-MVC
前面三章已经把mvc启动过程以及源代码做了讲解,本章开始正式mvc,mvc全称叫model view controller,也就是把表现层又细分三层,官网的图片描述:
默认创建了一个.net core web 项目,把startup类中的代码改成下面这样
public class startup
{
public void configureservices(iservicecollection services)
{
services.addmvc();
}
public void configure(iapplicationbuilder app, microsoft.aspnetcore.hosting.ihostingenvironment environment)
{
if (environment.isdevelopment())
{
app.usedeveloperexceptionpage();
}
app.usemvcwithdefaultroute();
}
}
我们.net core mvc是基于约定的一种模式,例如:控制器是放在controllers文件夹中的(当然这不是必须),视图放在pages或者views文件夹中等,首先我们讲讲controller的约定,先不管例外的情况,我们要定义一个controller首先要继承至microsoft.aspnetcore.mvc.controller类并且符合下面其中之一的条件:
1、这个类名称后缀是以controller结尾
例如:新建一个home类,那么它的签名应该像这样:public class homecontroller : controller
2、继承至带有controller后缀名的基类,
例如:你已经创建好了一个basecontroller基类,现在需要创建home类,那么他的签名可以是这样:public class home : basecontroller
3、这个类带有[controller]标签
例如:新建一个home类,那么它的签名应该像这样:
[controller]
public class home : controller
在controller类里面写的方法,我们称为action,例如下面,这就创建了一个名为index的方法, 返回值类型是一个实现了iactionresult接口的实例,这里返回的是view
public class homecontroller: controller
{
public iactionresult index()
{
return view();
}
}
在这里先说说view()这个方法到底干了什么事儿吧,我们转到源代码可以看到最终view是创建了一个viewresult这个类,这个类又继承至actionresult并且实现了iactionresult接口,其中最主要 executeresultasync方法就是返回给我们前端的数据,viewresult这个类中有两个我们常用的属性,分别是viewname和viewdata,分别代表"视图的名称"和"视图需要的数据",如果视图名称不传那么就约定以控制器action名称为准,否则已传入名称为准,如果传入viewdata那么就可以在视图中的model属性里面访问到传入的数据,并且转换为强类型,就以上面的例子,我们在views文件夹中创建一个home文件夹和index.cshtml视图文件,并且在models文件夹中创建两个实体,一个为通用的viewmodel,代码如下:
public class viewmodel<t> where t : class
{
public string title { get; set; }
public ienumerable<t> data { get; set; }
}
另一个是具体的action视图所需的数据实体,所以名称为indexmodel,具体代码如下:
public class indexmodel
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
}
另外我们再写一个获取index数据的服务,名称为homeservice,并且在startup类的configureservices方法中最前面加上services.addscoped<homeservice>();
先不管是否符合设计规范,这样做完后我们就可以在其他实体中注入homeservice的实例了,我们homeservice中代码可以是这样的:
public class homeservice
{
private ienumerable<indexmodel> _sourcedata = new list<indexmodel>
{
new indexmodel { id = 1, description = "my is code1", name = "test1" },
new indexmodel { id = 2, description = "my is code2", name = "test2" },
new indexmodel { id = 3, description = "my is code3", name = "test3" },
new indexmodel { id = 4, description = "my is code4", name = "test4" },
new indexmodel { id = 5, description = "my is code5", name = "test5" },
};
public viewmodel<indexmodel> getdata(int id)
{
return new viewmodel<indexmodel>
{
title = "index",
data = id > 0 ? _sourcedata.where(x => x.id == id) : _sourcedata
};
}
}
这个时候将homecontroller中的代码改成这样
public class homecontroller: controller
{
private readonly homeservice _service;
public homecontroller(homeservice service)
{
_service = service;
}
public iactionresult index()
{
var data = _service.getdata();
return view(data);
}
}
然后转到视图文件,视图中代码如下:
@model viewmodel<indexmodel>;
@{
viewdata["title"] = model.title;
}
<ul>
@foreach (var item in model.data)
{
<li>
<span>名称:@item.name</span>
<span>说明:@item.description</span>
<a asp-action="details" asp-route-id="@item.id">详细</a>
</li>
}
</ul>
在视图里面有一句代码值得注意
<a asp-action="details" asp-route-id="@item.id">详细</a>
这个是.net core改进部分,它叫做 taghelpers,它是由.net core解析,最终变成正常的src属性或者其他html属性,这样做的好处是更加接近于html本身的编程方式,
这里有注意到我们定义的asp-action="details"表示的是转到当前视图的控制器details方法中,最终会生成的url path是这样 /home/details?id={id},
为了能够正常的运行,我们需要创建一个details方法,代码如下:
public iactionresult details(int id)
{
var data = _service.getdata(id);
data.title = "details";
return view(data);
}
在创建details的视图文件,代码如下:
@model viewmodel<indexmodel>
@{
viewdata["title"] = model.title;
var data = model.data.firstordefault();
}
<p>@data.name,@data.description,@data.id</p>
然后我们运行程序,会看到如下界面:
点击"详细" 会出现以下界面:
好啦,mvc大致情况就介绍到这里,后面会详细说说views这个文件夹中的一些规则以及,有兴趣的也可以去官网看看