25-ASP.NET Core MVC概念理解
什么是MVC模式
- 模型职责
- 视图职责
- 控制器职责
什么是ASP.NET Core MVC:配合使用ASP.NET Core的Web开发框架。主要包含:
- Routing
- Model Binding
- Model validation
- Dependency injection
- Filters
- Areas
- Web APIs
- Testability
- Razor view engine
- Strongly typed views
- Tag Helpers
- View Components
下面我们来一一学习。
26-关于路由配置MapRoute
在Configure方法中设置路由中间件:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});Code language: JavaScript (javascript)
MapRoute 方法签名说明(来自元数据):
//
// 摘要:
// Adds a route to the Microsoft.AspNetCore.Routing.IRouteBuilder with the specified
// name and template.
//
// 参数:
// routeBuilder: The Microsoft.AspNetCore.Routing.IRouteBuilder to add the route to.
// name: The name of the route.
// template: The URL pattern of the route.
//
// 返回结果:
// A reference to this instance after the operation has completed.
public static IRouteBuilder MapRoute(this IRouteBuilder routeBuilder, string name, string template);
//
// 摘要:
// Adds a route to the Microsoft.AspNetCore.Routing.IRouteBuilder with the specified
// name, template, and default values.
public static IRouteBuilder MapRoute(this IRouteBuilder routeBuilder, string name, string template, object defaults);
//
// 摘要:
// Adds a route to the Microsoft.AspNetCore.Routing.IRouteBuilder with the specified
// name, template, default values, and constraints.
public static IRouteBuilder MapRoute(this IRouteBuilder routeBuilder, string name, string template, object defaults, object constraints);
//
// 摘要:
// Adds a route to the Microsoft.AspNetCore.Routing.IRouteBuilder with the specified
// name, template, default values, and data tokens.
public static IRouteBuilder MapRoute(this IRouteBuilder routeBuilder, string name, string template, object defaults, object constraints, object dataTokens);Code language: PHP (php)
当我们访问 http://localhost:64913/home/index/1 就可以匹配到下面action 并且id = 1:
public IActionResult Index(int? id)Code language: PHP (php)
以下地址均可匹配:
/home/index//home/
另外,app.UseMvc 可以替换为:
//app.UseMvc(routes =>
//{
// routes.MapRoute(
// name: "default",
// template: "{controller=Home}/{action=Index}/{id?}");
//});
//可以替换上面的代码
app.UseMvcWithDefaultRoute();Code language: JavaScript (javascript)
添加多个路由:
app.UseMvc(routes =>
{
//特殊的路由放上面 因为匹配顺序有关 特殊就是小众 就是给几个控制器用
routes.MapRoute(template:"login", name:"login", defaults: new { controller="abc", action="def" });
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});Code language: JavaScript (javascript)
27-ASP.NET CORE MVC 的Area区域
区域可以把整个MVC所有的模式分组到一个独立的区域模块中。比如我们现在如果有一个后台,我们可以添加一个后台区域,可以添加多个区域。区域的配置就是路由规则而已。
添加下面的路由到Configure方法里面(Scaffolding 会自动生成文件并添加依赖,但 Startup 可能需要手动调整):
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
});Code language: JavaScript (javascript)
完整路由配置示例:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
//特殊的路由放上面 因为匹配顺序有关 特殊就是小众 就是给几个控制器用
routes.MapRoute(template:"login", name:"login", defaults: new { controller="abc", action="def" });
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});Code language: JavaScript (javascript)
右击项目-添加区域。添加区域路由:
//先添加区域路由
routes.MapRoute(
name: "admin",
template: "admin/{controller=Home}/{action=Index}/{id?}");
//也可以这样来配置区域路由
routes.MapAreaRoute("admin1", "admin", "admin/{controller=Home}/{action=Index}/{id?}");Code language: JavaScript (javascript)
如果未给区域控制器添加标注,会出现以下异常:
An unhandled exception occurred while processing the request.
AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:
EfcoreSqlite.Controllers.HomeController.Index (EfcoreSqlite)
EfcoreSqlite.Areas.Admin.Controllers.HomeController.Index (EfcoreSqlite)
Microsoft.AspNetCore.Mvc.Internal.ActionSelector.SelectBestCandidate(RouteContext context, IReadOnlyList<ActionDescriptor> candidates)Code language: CSS (css)
原因是:我们在路由中只是指定了home控制器,但是mvc发现有两个home控制器,所以冲突了。解决办法如下:
[Area("Admin")]//我们这个控制器是区域控制器 这样就不会和非区域的控制器冲突
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
给区域的控制器加入标注 [Area("Admin")]。
也可以注册两个MVC中间件:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
});
app.UseMvc(routes =>
{
//特殊的路由放上面 因为匹配顺序有关 特殊就是小众 就是给几个控制器用
routes.MapRoute(template:"login", name:"login", defaults: new { controller="abc", action="def" });
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});Code language: JavaScript (javascript)
Previous: 操作数据库
Next: 模型Model和数据验证