日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Web API 中的属性路由

發(fā)布時(shí)間:2025/3/11 asp.net 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Web API 中的属性路由 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

為什么要有屬性路由?

基于約定路由的一個(gè)優(yōu)點(diǎn)是模板在單個(gè)位置中定義,并且路由規(guī)則在所有控制器上一致的應(yīng)用。但是基于約定的路由很難支持RESTFUl 中常見的某些URI模式。例如,資源通常包含子資源,客戶有訂單,電影有演員,書有作者等等。創(chuàng)建反應(yīng)這些URI是很自然的,如下圖所示:

/customers/1/orders

?使用屬性路由,為此URI定義路由很簡單,只需向控制器中添加一個(gè)屬性,如下圖所示:

[Route("customers/{customerId}/orders")] public IEnumerable<Order> GetOrdersByCustomer(int customerId) { ... }

?


啟用屬性路由?

要啟用屬性路由,要在配置期間調(diào)用MapHttpAttributeRoutes,此方法在System.Web.Http.HttpConfigurationExtensions類中定義。如下圖所示:?

using System.Web.Http;namespace WebApplication {public static class WebApiConfig{public static void Register(HttpConfiguration config){// Web API routesconfig.MapHttpAttributeRoutes();// Other Web API configuration not shown.}} }

屬性路由可以和約定路由相結(jié)合,要定義基于約定的路由,可以調(diào)用MapHttpRoute方法。如下圖所示:?

public static class WebApiConfig {public static void Register(HttpConfiguration config){// Attribute routing.config.MapHttpAttributeRoutes();// Convention-based routing.config.Routes.MapHttpRoute(name: "DefaultApi",routeTemplate: "api/{controller}/{id}",defaults: new { id = RouteParameter.Optional });} }

添加屬性路由?

public class OrdersController : ApiController {[Route("customers/{customerId}/orders")][HttpGet]public IEnumerable<Order> FindOrdersByCustomer(int customerId) { ... } }

字符串“customers/{customerId}/orders”是路徑的URI模板,Web API嘗試將請求URI和模板匹配。在此示例中,“customers”和“orders”是靜態(tài)片段,{customerId}是可變參數(shù),以下URI將與此模板匹配:

  • http://localhost/customers/1/orders
  • http://localhost/customers/bob/orders
  • http://localhost/customers/1234-5678/orders

請注意:路由模板中的{customerId}參數(shù)要和方法中customerId相匹配,當(dāng)WebAPI調(diào)用控制器操作時(shí),它會嘗試綁定路由參數(shù)。例如?URI為 http://example.com/customers/1/orders ,則Web API會嘗試將 值“1”綁定到操作的customerId參數(shù)中。

URI模板中可以有多個(gè)參數(shù),如下圖所示:

[Route("customers/{customerId}/orders/{orderId}")] public Order GetOrderByCustomer(int customerId, int orderId) { ... }

?

Web API還根據(jù)請求的Http方法(Get,Post等)選擇操作。默認(rèn)情況下,Web API會查找與控制器方法名稱的開頭不區(qū)分大小寫的匹配項(xiàng)。例如,控制器方法PutCustomer匹配HTTP PUT請求。?

以下示例將CreateBook方法映射到HTTP POST請求。?

[Route("api/books")] [HttpPost] public HttpResponseMessage CreateBook(Book book) { ... }

對于所有其他HTTP方法(包括非標(biāo)準(zhǔn)方法),請使用AcceptVerbs屬性,該屬性采用HTTP方法列表。?

// WebDAV method [Route("api/books")] [AcceptVerbs("MKCOL")] public void MakeCollection() { }

?


路由前綴?

通常,控制器的中的路由都以相同的前綴開頭,例如:?

public class BooksController : ApiController {[Route("api/books")]public IEnumerable<Book> GetBooks() { ... }[Route("api/books/{id:int}")]public Book GetBook(int id) { ... }[Route("api/books")][HttpPost]public HttpResponseMessage CreateBook(Book book) { ... } }

您可以使用[RoutePrefix]屬性為整個(gè)控制器設(shè)置公共前綴:?

[RoutePrefix("api/books")] public class BooksController : ApiController {// GET api/books[Route("")]public IEnumerable<Book> Get() { ... }// GET api/books/5[Route("{id:int}")]public Book Get(int id) { ... }// POST api/books[Route("")]public HttpResponseMessage Post(Book book) { ... } }

在method屬性上使用波浪號(?)來覆蓋路由前綴:?

[RoutePrefix("api/books")] public class BooksController : ApiController {// GET /api/authors/1/books[Route("~/api/authors/{authorId:int}/books")]public IEnumerable<Book> GetByAuthor(int authorId) { ... }// ... }

路由前綴可以包含參數(shù):?

[RoutePrefix("customers/{customerId}")] public class OrdersController : ApiController {// GET customers/1/orders[Route("orders")]public IEnumerable<Order> Get(int customerId) { ... } }

路徑約束允許限制路徑模板中的參數(shù)匹配方式。一般語法是“{parameter:constraint}”。例如:?

[Route("users/{id:int}")] public User GetUserById(int id) { ... }[Route("users/{name}")] public User GetUserByName(string name) { ... }

?這時(shí)候,只有id是整數(shù)時(shí),才匹配第一路徑。否則,將選擇第二路徑。完整的約束列表如下圖所示:

約束描述例子
alpha匹配大寫或者小寫拉丁字母:(a-z , A-Z){x:alpha}
bool匹配布爾類型{x:bool}
datetime匹配DataTime類型{x:datetime}
decimal匹配小數(shù)值{x:decimal}
double匹配64位浮點(diǎn)數(shù){x:double}
float匹配32位浮點(diǎn)數(shù){x:float}
guid匹配Guid值{x:guid}
int匹配32位整型{x:int}
length匹配具有指定長度或者具有指定長度范圍的字符串{x:length(6)} {x:length(1,20)}
long匹配64位整數(shù)值{x:long}
max匹配具有最大值的整數(shù){x:max(10)}
maxlength匹配具有最大長度的字符串{x:maxlength(10)}
min匹配具有最小值的整數(shù){x:min(10)}
minlength匹配具有最小長度的字符串{x:minlength(10)}
range匹配值范圍內(nèi)的整數(shù){x:range(10,50)}
regex匹配正則表達(dá)式{x:regex(^\d{3}-\d{3}-\d{4}$)}

可以將多個(gè)約束應(yīng)用于參數(shù),以冒號分隔?

[Route("users/{id:int:min(1)}")] public User GetUserById(int id) { ... }

?

可以通過實(shí)現(xiàn)IHttpRouteConstraint,來創(chuàng)建自定義路由約束。例如,以下約束將參數(shù)限制為非零整數(shù)值。?

public class NonZeroConstraint : IHttpRouteConstraint {public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection){object value;if (values.TryGetValue(parameterName, out value) && value != null){long longValue;if (value is long){longValue = (long)value;return longValue != 0;}string valueString = Convert.ToString(value, CultureInfo.InvariantCulture);if (Int64.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out longValue)){return longValue != 0;}}return false;} }

以下代碼顯示了如何注冊約束:?

public static class WebApiConfig {public static void Register(HttpConfiguration config){var constraintResolver = new DefaultInlineConstraintResolver();constraintResolver.ConstraintMap.Add("nonzero", typeof(NonZeroConstraint));config.MapHttpAttributeRoutes(constraintResolver);} }

可以在路由中應(yīng)用約束:?

[Route("{id:nonzero}")] public HttpResponseMessage GetNonZero(int id) { ... }

?


可選的URI參數(shù)和默認(rèn)值?

?可以通過向路由參數(shù)添加問號來使URI參數(shù)可選。如果route參數(shù)是可選的,則必須為方法參數(shù)定義默認(rèn)值

public class BooksController : ApiController {[Route("api/books/locale/{lcid:int?}")]public IEnumerable<Book> GetBooksByLocale(int lcid = 1033) { ... } }

?在這個(gè)例子中,/api/books/locale/1033? 和 /api/books/locale 返回相同的資源。或者可以在路由模板中指定默認(rèn)值,如下圖所示:

public class BooksController : ApiController {[Route("api/books/locale/{lcid:int=1033}")]public IEnumerable<Book> GetBooksByLocale(int lcid) { ... } }

路由名稱?

在Web API 中,每個(gè)路由都有一個(gè)名稱。路由名稱對于對于生成鏈接十分有用,因此可以在HTTP響應(yīng)中包含鏈接。

要指定路由名稱,請?jiān)趯傩陨显O(shè)置“Name”屬性,以下示例顯示如何設(shè)置路由名稱,以及如何在生成的鏈接時(shí)使用路由名稱。

public class BooksController : ApiController {[Route("api/books/{id}", Name="GetBookById")]public BookDto GetBook(int id) {// Implementation not shown...}[Route("api/books")]public HttpResponseMessage Post(Book book){// Validate and add book to database (not shown)var response = Request.CreateResponse(HttpStatusCode.Created);// Generate a link to the new book and set the Location header in the response.string uri = Url.Link("GetBookById", new { id = book.BookId });response.Headers.Location = new Uri(uri);return response;} }

路由順序?

當(dāng)框架嘗試將URI與路由匹配時(shí),它會按特定的順序評估路由,要指定順序,需要在Route屬性上設(shè)置Order屬性,框架首先評估Order值較低的方法,默認(rèn)Order值為零。

以下是確定總排序的方式:

1、比較Route屬性的Order屬性。

2、查看路由模板中的每個(gè)URI片段,對于細(xì)分,約定如下:

? ? ? a、靜態(tài)片段。

? ? ? b、使用約束路由參數(shù)。

? ? ? c、路由參數(shù)沒有約束。

? ? ? d、具有約束的通配符參數(shù)段

? ? ? e、沒有約束的通配符參數(shù)段

[RoutePrefix("orders")] public class OrdersController : ApiController {[Route("{id:int}")] // constrained parameterpublic HttpResponseMessage Get(int id) { ... }[Route("details")] // literalpublic HttpResponseMessage GetDetails() { ... }[Route("pending", RouteOrder = 1)]public HttpResponseMessage GetPending() { ... }[Route("{customerName}")] // unconstrained parameterpublic HttpResponseMessage GetByCustomer(string customerName) { ... }[Route("{*date:datetime}")] // wildcardpublic HttpResponseMessage Get(DateTime date) { ... } }

以上路由將按以下順序執(zhí)行:

1、orders/details?

2、orders/{id}

3、orders/{customerName}

4、orders/{*date}

5、orders/pending

?

?

?

?

?

?

?

?

?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的ASP.NET Web API 中的属性路由的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。