路由和区域

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)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注