频道栏目
首页 > 程序开发 > 综合编程 > 其他综合 > 正文
asp.net core 系列
2019-01-10 11:39:48         来源:花阴偷移  
收藏   我要投稿

asp.net core 系列 4 路由(上) 一. 概述

介绍asp.net core路由时,我初步想了下,分几篇来说明。 路由的知识点很多,参考了官方文档提取出一些重要的知识点来说。 在ASP.NET Core中是使用路由中间件来匹配传入请求的 URL 并将它们映射到操作(action方法)。路由是在程序启动时进行传统路由或属性路由定义。路由描述如何将 URL 路径与操作相匹配。它还用于在响应中生成送出的 URL(用于链接)。

路由操作既支持传统路由,也支持属性路由。也可混合使用。通常传统路由用于为浏览器处理 HTML 页面的控制器。属性路由用于处理 web API 的控制器。

1.1设置路由中间件

要使用传统路由,必须在UseMVC中间件中配置实现IRouteBuilder接口,在asp.net core mvc 2.2 框架下,应用程序Startup的Configure方法中,默认路由设置如下:

app.UseMvc(routes =>

{

routes.MapRoute(

name: "default",

template: "{controller=Home}/{action=Index}/{id}");

});

在对 UseMvc调用中,MapRoute 用于创建单个路由,亦称 default 路由。 大多数 MVC 应用使用带有模板的路由。对于default路由简便的方法可以使用:

app.UseMvcWithDefaultRoute();

UseMvc和UseMvcWithDefaultRoute可向中间件管道添加RouterMiddleware的实例。MVC 不直接与中间件交互,而是使用路由来处理请求。MVC 通过MvcRouteHandler实例连接到路由。

UseMvc不直接定义任何路由,它向属性路由的路由集合添加占位符{controller=Home}/{action=Index}/{id} 。通过重载UseMvc(Action)则允许用户添加自己的路由,并且还支持属性路由。

1.2 传统路由

传统路由是:具有描述性的路由方案,这样URL具有可读性。传统路由格式:{controller=Home}/{action=Index}/{id}这样的url路径是设定了一个约定: 第一段映射到控制器名称, 第二段映射到操作名称,第二段映射到可选ID。

(1) 使用默认路由:

routes.MapRoute("default", "{controller=Home}/{action=Index}/{id}");

使用此默认路由时: url路径/Products/List 将映射到程序ProductsController(控制器).List(action)中。 url路径/Blog/Article/17将映射到程序BlogController(控制器).Article(action)中。

(2) 多个路由:

通过添加对 MapRoute 的多次调用,可以在 UseMvc 内添加多个路由。 这样做可以定义多个约定,或添加专用于特定操作的传统路由,比如:

app.UseMvc(routes =>

{

routes.MapRoute("blog", "blog/{*article}",

defaults: new { controller = "Blog", action = "Article" });

routes.MapRoute("default", "{controller=Home}/{action=Index}/{id}");

});

这里的blog路由是一个专用的传统路由,这表示blog使用传统路由系统,但专用于特定的操作,也就是对于BlogController控制器的Article操作,此专用路由将始终映射。对于多个路由的路由集合会进行排序,并按添加顺序进行处理,因此,在此示例中,将先尝试blog路由,再尝试default路由。

(3) action操作的区分

在处理url请求时,当通过路由匹配到一个控制器内两项相同的action名称时,mvc必须进行区分,以选择最佳候选项,否则会引发异常(AmbiguousActionException)。

public class ProductsController : Controller

{

public IActionResult Edit(int id) { ... }

[HttpPost]

public IActionResult Edit(int id, Product product) { ... }

}

此Products控制器定义了二项操作,这两项操作均与 URL 路径的/Products/Edit/17匹配相同。解决方案是将要提交的action加上Http 谓词为POST。这样post过来时,就会选择Edit(int, Product)

1.3属性路由

通过在控制器(Controller)或操作(Action)上放置路由可实现属性路由。不能通过传统路由访问定义属性路由的操作,反之亦然。控制器上的任何路由属性,都会使控制器中的所有操作使用属性路由。

属性路由使用一组属性将action直接映射到路由模板。在下面的示例中,Configure方法使用app.UseMvc();,不传递任何路由。HomeController将匹配一组 URL,这组 URL 与默认路由{controller=Home}/{action=Index}/{id}匹配的 URL 类似:

当去掉default默认路由模板后,只使用app.UseMvc()时。运行程序时,页面报404错误:找不到localhost的网页。

app.UseMvc();

(1) 属性路由基本使用

如果定义了属性路由的操作,此时就是启动属性路由功能。Home控制器的属性路由示例如下:

public class HomeController : Controller

{

[Route("")]

[Route("Home")]

[Route("Home/Index")]

public IActionResult Index()

{

return View();

}

}

在index的action上加[Route("")]属性路由。 浏览器可以使用下面三种url来访问,也是程序启动时的默认加载页面:

https://localhost:30081/

https://localhost:30081/Home/

https://localhost:30081/Home/index

(2)属性路由精确控制

属性路由需要更多输入来指定路由;传统的默认路由处理路由的方式则更简洁。但是,属性路由允许(并需要)精确控制应用于每项操作的路由模板。下面示例是精确控制每项操作的路由模板,比如url访问/home/index时,即是调用MyIndex的action方法。

public class MyDemoController : Controller

{

[Route("")]

[Route("Home")]

[Route("Home/Index")]

public IActionResult MyIndex()

{

return View("Index");

}

}

1.4 使用 Http[Verb] 属性的属性路由

属性路由还可以使用Http[Verb]属性,比如HttpPostAttribute。所有这些属性都可采用路由模板。此示例展示,同一路由模板匹配的两项操作:

[HttpGet("/products")]

public IActionResult ListProducts()

{

// ...

}

[HttpPost("/products")]

public IActionResult CreateProduct(...)

{

// ...

}

当 Http 谓词为GET时将执行ProductsApi.ListProducts操作, 当 Http 谓词为POST时将执行ProductsApi.CreateProduct。生成 REST API 时,很少会在操作方法上使用[Route(...)]。建议使用更特定的Http*Verb*Attributes来明确 API 所支持的操作。REST API 的客户端需要知道映射到特定逻辑操作的路径和 Http 谓词。

例如下面一个web api访问路由,使用Http*Verb*Attributes来明确定义如下:

public class ProductsApiController : Controller

{

[HttpGet("/products/{id}", Name = "Products_List")]

public IActionResult GetProduct(int id) { ... }

}

上面定义只有针对如访问url如: /products/3(而非/products)之类的 URL才会执行ProductsApi.GetProduct(int)操作。

1.5路由合并

若要使属性路由减少重复,可将控制器Controller上的路由属性与各个操作Action上的路由属性合并。控制器上定义的所有路由模板均作为操作上路由模板的前缀。在控制器上放置路由属性会使控制器中的所有操作都使用属性路由。

下面是一个web api的路由合并,访问Get的方法的访问路径为: https://localhost:30081/api/Products/1

[Route("api/Products")]

public class ProductsApiController : Controller

{

// GET api/values/5

[HttpGet("{id}")]

public string Get(int id)

{

return "value";

}

}

下面是一个控制器的路由合并。访问index页面的访问路径为: https://localhost:30081/home/index

[Route("Home")]

public class HomeController : Controller

{

[Route("")] // Combines to define the route template "Home"

[Route("Index")] // Combines to define the route template "Home/Index"

[Route("/")] // Doesn't combine, defines the route template ""

public IActionResult Index()

{

//...

}

}

1.6 指定属性路由参数约束

[HttpGet("Home/{id:int}",Name = "Pri")]

public IActionResult Privacy(int id)

{

return View();

}

如果输入非整数类型的参数,浏览器提示:找不到与以下网址对应的网页:https://localhost:30081/home/dd

1.7自定义路由属性

该框架中提供的所有路由属性([Route(...)]、[HttpGet(...)]等)都可实现IRouteTemplateProvider接口。当应用启动时,MVC 会查找控制器类和操作方法上的属性,并使用可实现IRouteTemplateProvider的属性生成一组初始路由。

下面使用IRouteTemplateProvider来定义自己的路由属性。每个IRouteTemplateProvider都允许定义一个包含自定义路由模板、顺序和名称的路由:

public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider

{

//实现接口的三个属性,这里的[controller]是一个标记替换。

public string Template => "api/[controller]/{action}/{id}";

public int Order { get; set; }

public string Name { get; set; }

}

public class ProductsApiController : Controller

{

// GET api/values/5

// [HttpGet("{id}")]

[MyApiController()]

public string Get(int id)

{

return "value";

}

}

通过访问url: https://localhost:30081/api/ProductsApi/get/1 来调用get方法。

点击复制链接 与好友分享!回本站首页
相关TAG标签 asp net core 系列
上一篇:C# 命令行编译C#程序问题详解
下一篇:其实Python和人工智能是这样的
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站