ASP.NET Web API基础(02)---WebAPI 中的路由

WebApi有两种路由规则,默认路由和特性路由,都位于WebApiConfig类中的Register方法里进行配置,

(1). config.MapHttpAttributeRoutes(); 代表特性路由

(2). config.Routes.MapHttpRoute(); 代表统一的默认路由

特别注意:特性路由的优先级 大于 默认路由的优先级

2.1 默认路由

2.1.1 默认路由规则

Visual Studio的Web API项目模板就创建了一个默认的路由表:

routes.MapHttpRoute(

name: "API Default",

routeTemplate: "api/{controller}/{id}",

defaults: new { id = RouteParameter.Optional }

);

这个路由被定义在App_Start目录下的WepApiConfig.cs文件中。

路由表中的每条记录都包含了一个路由模板。Web API的默认路由模板是"api/{controller}/{id}"。在这个模板中,"api"是一个字面路径字段,而{controller}和{id}都是占位符变量。

当Web API框架收到了HTTP请求时,它将会尽力匹配URI到路由表中的路由模板的其中一个。如果没有路由被匹配到,客户端就会收到404错误。例如,以下URI会匹配到默认路由:

1. /api/contacts

2. /api/contacts/1

3. /api/products/gizmo1

然而,以下URI不会匹配到,因为它缺乏"api"字段。

/contacts/1

备注:在路由中使用"api"的原因是为了避免和ASP.NET MVC的路由冲突。也就是说,你可以使用"/contacts"匹配到MVC的路由,使用"api/contacts"匹配到Web API的路由。当然了,如果你不喜欢这种约定,你也可以修改默认路由表。

一旦某个路由匹配到了,Web API就会选择相应的控制器及动作:

  • 为了找到控制器,Web API将"Controller"添加到{controller}变量上。
  • 为了找到动作,Web API会遍历HTTP方法,然后查找一个其名字以HTTP方法的名字开头的动作。例如,有一个GET请求,Web API会查找以"Get…."开头的动作,比如"GetContact"或"GetAllContacts"。这种方式仅仅适用于GET、POST、PUT和DELETE方法。
  • 路由模板的其他占位符变量,比如{id},会被映射到动作的参数。

    让我们来看一个示例。假定你定义了如下的控制器:

public class ProductsController : ApiController

{

public void GetAllProducts() { }

public IEnumerable<Product> GetProductById(int id) { }

public HttpResponseMessage DeleteProduct(int id){ }

}

这里是一些可能的HTTP请求,以及相应的得到执行的动作:

HTTP Method

URI Path

Action

Parameter

GET

api/products

GetAllProducts

(none)

GET

api/products/4

GetProductById

4

DELETE

api/products/4

DeleteProduct

4

POST

api/products

(no match)

注意URI的{id}字段,如果存在,它会被映射到动作的id参数中。在本例,控制器定义了两个GET方法,其中一个包含id参数,而另一个不包含id参数。

同样的,注意到POST请求会失败,因为控制器中并没有定义"POST…"方法。

2.1.2 路由偏差(Routing Variations)

除了使用这些HTTP方法的命名约定,你也可以通过用HttpGet、HttpPut、HttpPost或HttpDelete属性来赋予这些动作来具体地为每个动作设定HTTP方法。

在下面这个例子中,FindProduct方法被映射到GET请求:

public class ProductsController : ApiController

{

[HttpGet]

public Product FindProduct(id) {}

}

 为了让一个动作支持多个HTTP方法,或支持除GET、PUT、POST和DELETE之外的HTTP方法,你可以使用AcceptVerbs属性,它以一个HTTP方法列表为参数。

public class ProductsController : ApiController

{

[AcceptVerbs("GET", "HEAD")]

public Product FindProduct(id) { }

[AcceptVerbs("Link")]

public void MakeCollection() { }

}

上述两个方法可以通过设置请求方式为"GET"、"Head"、"Link"即可请求相应的方法

2.1.3 定义多个路由

默认路由可以同时声明多个,只要里面的name值不一样即可,满足任何一个路由规则都可以访问。

2.2 特性路由

可以通过[Route]和[RoutePrefix]这两个标记来自定义路由规则,[Route]作用于action,[RoutePrefix]作用于Controller, 一旦设置了其中任何一个,默认路由routeTemplate就不起任何作用了。

当[RoutePrefix]和[Route]都存在的话,规则为二者的拼接结合,先[RoutePrefix] 后[Route]

//[RoutePrefix("Api/Third")]

public class ThirdController : ApiController

{

/// <summary>

/// 演示多个默认路由的情况

/// 需要把控制器的特性注释掉!需要把WebApiConfig中的 DefaultApi2和DefaultApi3两个路由打开,其他的都注释掉

/// </summary>

/// <param name="userName"></param>

/// <returns></returns>

[HttpGet]

public string GetUserName(string userName)

{

return $"userName的值为{userName}";

}

/// <summary>

/// 演示淡出的[Route]特性

/// </summary>

/// <param name="userName"></param>

/// <returns></returns>

[Route("myApi/Third/GetM1")]

[HttpGet]

public string GetM1(string userName)

{

return $"GetM1您的返回值为:{userName}";

}

/// <summary>

/// 演示[RoutePrefix]和[Route]

/// </summary>

/// <param name="userName"></param>

/// <returns></returns>

[Route("myApi/Third/GetM2")]

[HttpGet]

public string GetM2(string userName)

{

return $"GetM2您的返回值为:{userName}";

}

/// <summary>

/// 演示自定义[Route]的特殊写法

/// </summary>

/// <param name="firstName"></param>

/// <param name="lastName"></param>

/// <returns></returns>

[Route("myApi/Third/GetFullName/{firstName}/{lastName}")]

[HttpGet]

public string GetFullName(string firstName,string lastName)

{

return $"firstName值为{firstName},lastName值为{lastName}";

}

}

特性路由的作用

(1). 标记特殊的访问路径,该功能有点鸡肋,用的比较少。

(2). 多版本控制的时候会使用. (后面介绍)

2.3 请求规则

2.3.1 Get请求规则

发起请求的方式都为 api/Second/CheckLogin?userName=admin&pwd=123456 这种类型,不管几个参数(1个或多个),接收的时候,如果是分参数接收,没有任何问题, 可以正常接收,但如果是通过实体类来接收,必须在前面加特性[FromUri],否则接收不到。

备注:当然也可以什么参数都不写,通过传统的Request或者Request.QueryString来接受。

例如:

实体类:

public class LoginModel

{

public string userName { get; set; }

public string pwd { get; set; }

}

服务器端代码

/// <summary>

/// Get api/Second/CheckLogin1?userName=admin&pwd=123456

/// </summary>

/// <param name="userName"></param>

/// <param name="pwd"></param>

/// <returns></returns>

[HttpGet]

public string CheckLogin1(string userName, string pwd)

{

if (userName == "admin" && pwd == "123456")

{

return "ok";

}

else

{

return "error";

}

}

#endregion

#region 02-用实体接收,加[FromUri]特性

/// <summary>

/// Get api/Second/CheckLogin2?userName=admin&pwd=123456

/// </summary>

/// <param name="model"></param>

/// <returns></returns>

[HttpGet]

public string CheckLogin2([FromUri]LoginModel model)

{

if (model.userName == "admin" && model.pwd == "123456")

{

return "ok";

}

else

{

return "error";

}

}

#endregion

#region 03-用实体接收,不加[FromUri]特性

/// <summary>

/// Get api/Second/CheckLogin3?userName=admin&pwd=123456

/// </summary>

/// <param name="model"></param>

/// <returns></returns>

[HttpGet]

public string CheckLogin3(LoginModel model)

{

if (model.userName == "admin" && model.pwd == "123456")

{

return "ok";

}

else

{

return "error";

}

}

#endregion

#region 04-用dynamic接收,加[FromUri]特性

/// <summary>

/// Get api/Second/CheckLogin4?userName=admin&pwd=123456

/// </summary>

/// <param name="model"></param>

/// <returns></returns>

[HttpGet]

public string CheckLogin4([FromUri]dynamic model)

{

if (model.userName == "admin" && model.pwd == "123456")

{

return "ok";

}

else

{

return "error";

}

}

#endregion

#region 05-没有任何参数,直接用Request相关方法接收

/// <summary>

/// Get api/Second/CheckLogin5?userName=admin&pwd=123456

/// </summary>

/// <param name="model"></param>

/// <returns></returns>

[HttpGet]

public string CheckLogin5()

{

var userName = HttpContext.Current.Request["userName"];

var pwd = HttpContext.Current.Request.QueryString["pwd"];

if (userName == "admin" && pwd == "123456")

{

return "ok";

}

else

{

return "error";

}

}

前端JS代码

//一.下面是Get请求的测试

//1. 分参数接收,可以正常访问

$("#getBtn1").click(function () {

$.ajax({ url: "/api/Second/CheckLogin1", type: "get", data: { userName: "admin", pwd: "123456" }, success: function (data) { alert(data); } });

});

//2. 用实体类接收,前面加[FromUrl],可以正常访问

$("#getBtn2").click(function () {

$.ajax({ url: "/api/Second/CheckLogin2", type: "get", data: { userName: "admin", pwd: "123456" }, success: function (data) { alert(data); } });

});

//3. 用实体类接收,前面什么不加,报错

// "Message":"出现错误","ExceptionMessage":"未将对象引用设置到对象的实例"

$("#getBtn3").click(function () {

$.ajax({ url: "/api/Second/CheckLogin3", type: "get", data: { userName: "admin", pwd: "123456" }, success: function (data) { alert(data); } });

});

//4. 用dynamic接收,前面什么不加,报错

// "Message":"出现错误","ExceptionMessage":"未将对象引用设置到对象的实例"

$("#getBtn4").click(function () {

$.ajax({ url: "/api/Second/CheckLogin4", type: "get", data: { userName: "admin", pwd: "123456" }, success: function (data) { alert(data); } });

});

//5. 后台直接用Request或者Request.QueryString,能正常接收

$("#getBtn5").click(function () {

$.ajax({ url: "/api/Second/CheckLogin5", type: "get", data: { userName: "admin", pwd: "123456" }, success: function (data) { alert(data); } });

});

示例说明:

(1). 分别调用CheckLogin1、CheckLogin2、CheckLogin3方法, 发现前两个方法都能正常调用,CheckLogin3这个方法报错, 报:"Message":"出现错误","ExceptionMessage":"未将对象引用设置到对象的实例"。

(2). 调用CheckLogin4方法,报与上面相同的错误,证明dynamic类型也不能这么用。

(3). 调用CheckLogin5方法,能正常接收,表明可以通过传统的Request或者Request.QueryString来接受。

2.3.2 Post请求规则

参数一定要用"实体类"接收(即使一个参数也要封装实体类),客户端既可以用ContentType="application/x-www-form-urlencoded"提交表单,也可以用 ContentType ="application/json"提交, 模型类前面可以加[FromBody],但只能在一个参数前面加.

#region 01-单个参数,加[FromBody]特性

[HttpPost]

public string Register0([FromBody]string userName)

{

if (userName == "admin")

{

return "ok";

}

else

{

return "error";

}

}

#endregion

#region 02-多个参数,分参数接收

[HttpPost]

public string Register1(string userName, string pwd)

{

if (userName == "admin" && pwd == "123456")

{

return "ok";

}

else

{

return "error";

}

}

#endregion

#region 03-用实体接收,加[FromBody]特性

[HttpPost]

public string Register2([FromBody]LoginModel model)

{

if (model.userName == "admin" && model.pwd == "123456")

{

return "ok";

}

else

{

return "error";

}

}

#endregion

#region 04-用dynamic接收,加[FromBody]特性

[HttpPost]

public string Register3([FromBody]dynamic model)

{

if (model.userName == "admin" && model.pwd == "123456")

{

return "ok";

}

else

{

return "error";

}

}

#endregion

#region 05-没有任何参数,直接用Request相关方法接收

[HttpPost]

public string Register4()

{

var userName = HttpContext.Current.Request["userName"];

var pwd = HttpContext.Current.Request.Form["pwd"];

if (userName == "admin" && pwd == "123456")

{

return "ok";

}

else

{

return "error";

}

}

#endregion

}

服务器端代码

//二.下面是Post请求的测试(默认情况下为:ContentType="application/x-www-form-urlencoded"提交表单的形式)

//PS: { userName: "admin", pwd: "123456" } 这就是一个JSON对象,也可以叫实体

//1. 一个参数的情况,后台分参数接收,且必须加[FromBody]特性

$("#postBtn0").click(function () {

//1.1 正常拼接,可以访问通,但是拿不到userName的值

$.ajax({ url: "/api/Second/Register0", type: "Post", data: { userName: "admin" }, success: function (data) { alert(data); } });

//1.2 没有键,只有值,可以正常访问,能拿到userName的值

//$.ajax({ url: "/api/Second/Register0", type: "Post", data: { "": "admin" }, success: function (data) { alert(data); } });

});

//2. 多个参数的情况,后台分参数接收,正常的键值对提交,无法访问,找不到匹配的资源

$("#postBtn1").click(function () {

//访问不通

$.ajax({ url: "/api/Second/Register1", type: "Post", data: { userName: "admin", pwd: "123456" }, success: function (data) { alert(data); } });

});

//3. 一个或多个参数的情况,后台用实体接收,且加[FromBody]特性,可以正常访问,并获取到请求值

$("#postBtn2").click(function () {

//情况①,默认的post请求,即ContentType="application/x-www-form-urlencoded"的形式,可以正常请求

//$.ajax({ url: "/api/Second/Register2", type: "Post", data: { userName: "admin", pwd: "123456" }, success: function (data) { alert(data); } });

//情况②,将post请求指定为contentType: 'application/json',且传递的参数格式化成Json字符串,则可以正常访问

$.ajax({ url: "/api/Second/Register2", type: "Post", contentType: 'application/json', data: JSON.stringify({ userName: "admin", pwd: "123456" }), success: function (data) { alert(data); } });

});

//4. 一个或多个参数的情况,后台用dynamic接收,且加[FromBody]特性,需要分情况讨论

$("#postBtn3").click(function () {

//情况①,默认的post请求,即ContentType="application/x-www-form-urlencoded"的形式,服务器报500错误

//$.ajax({ url: "/api/Second/Register3", type: "Post", data: { userName: "admin", pwd: "123456" }, success: function (data) { alert(data); } });

//情况②,将post请求指定为contentType: 'application/json',且传递的参数格式化成Json字符串,则可以正常访问

$.ajax({ url: "/api/Second/Register3", type: "Post", contentType: 'application/json', data: JSON.stringify({ userName: "admin", pwd: "123456" }), success: function (data) { alert(data); } });

});

//5. 一个或多个参数的情况,没有参数,通过Request或者Request.Form相关方法可以获取请求值

$("#postBtn4").click(function () {

//访问不通

$.ajax({ url: "/api/Second/Register4", type: "Post", data: { userName: "admin", pwd: "123456" }, success: function (data) { alert(data); } });

});

前端JS代码

(1). 当只有一个参数的情况,且加[FromBody]特性,不封装实体,如Register0,正常的键值对 { userName: "admin" }能访问通,但后台拿不到值,只有省掉键名{ "": "admin" },才能正常访问,且后台能拿到值。

(2). 多个参数的情况,后台分参数接收,如Register1,正常的键值对提交,无法访问,提示找不到匹配的资源。

(3). 一个或多个参数的情况,后台用实体接收,如Register2,且加[FromBody]特性,可以正常访问,并获取到请求值。

①:默认的post请求,即ContentType="application/x-www-form-urlencoded"的形式,可以正常请求。

②:将post请求指定为contentType: 'application/json',且传递的实体格式化成Json字符串,则可以正常请求。

(4). 一个或多个参数的情况,后台用dynamic接收,且加[FromBody]特性,需要分情况讨论。

①:默认的post请求,即ContentType="application/x-www-form-urlencoded"的形式,服务器报500错误。

②:将post请求指定为contentType: 'application/json',且传递的实体格式化成Json字符串,则可以正常请求。

阶段总结:后台用实体接收和用dynamic类型接收,用实体接收,无论是"application/x-www-form-urlencoded"还是"application/json"都能访问;如果用dynamic类型接收,只有"application/json"能访问, 且参数必须是序列化后的字符串

(5). 一个或多个参数的情况,没有参数,如Register4,通过Request或者Request.Form相关方法可以获取请求值。

Put和Delete请求与Post请求的规则相同。

在实际开发中,记住Get请求和Post请求的标准用法以及基本的调用规则,注意的是ajax的Get请求,加上一个当前时间或者随机数的参数,使用HttpClient 等需要禁用缓存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录 C#进阶系列——WebApi 路由机制剖析:你准备好了吗? ................................................................................................... 3 一、MVC和WebApi路由机制比较 ........................................................................................................................................ 5 1、MVC里面的路由 ......................................................................................................................................................... 5 2、WebApi里面的路由 ................................................................................................................................................... 5 二、WebApi路由基础 ............................................................................................................................................................. 7 1、默认路由 ..................................................................................................................................................................... 7 2、自定义路由 ............................................................................................................................................................... 10 2.1、自定义路由一:匹配到action ................................................................................................................. 11 2.2、自定义路由二 ............................................................................................................................................... 12 3、路由原理 ................................................................................................................................................................... 12 三、WebApi路由过程 ........................................................................................................................................................... 13 1、根据请求的url匹配路由模板 .............................................................................................................................. 13 2、找到控制器 ............................................................................................................................................................... 13 3、找到action ............................................................................................................................................................. 15 四、WebApi特性路由 ........................................................................................................................................................... 16 1、启动特性路由 ........................................................................................................................................................... 17 2、最简单的特性路由 ................................................................................................................................................... 17 3、带参数的特性路由 ................................................................................................................................................... 19 4、参数的约束和默认值 ............................................................................................................................................... 20 5、路由前缀 ................................................................................................................................................................... 20 五、第一个Restful风格的WebApi服务 ......................................................................................................................... 21 六、总结 ................................................................................................................................................................................. 22 C#进阶系列——WebApi 异常处理解决方案 ......................................................................................................................... 23 一、使用异常筛选器捕获所有异常 ..................................................................................................................................... 24 1、接口级别 ........................................................................................................................................................... 31 2、控制器级别 ....................................................................................................................................................... 33 3、全局配置 ........................................................................................................................................................... 34 二、HttpResponseException自定义异常信息 .............................................................................................................. 35 三、返回HttpError ............................................................................................................................................................ 37 四、总结 ................................................................................................................................................................................. 38 C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解 ......................................................................................... 39 一、void无返回值 ............................................................................................................................................................... 40 二、IHttpActionResult .................................................................................................................................................... 42 1、Json(T content) ........................................................................................................................................... 42 2、Ok()、 Ok(T content) ................................................................................................................................. 45 3、NotFound() ............................................................................................................................................................. 47 4、其他 ........................................................................................................................................................................... 49 4.1、Content(HttpStatusCode statusCode, T value) .................................................................. 49 4.2、BadRequest() ............................................................................................................................................ 49 4.3、Redirect(string location) ................................................................................................................ 50 5、自定义IHttpActionResult接口的实现 ............................................................................................................ 50 三、HttpResponseMessage ............................................................................................................................................... 53 四、自定义类型 ..................................................................................................................................................................... 54 五、总结 ................................................................................................................................................................................. 55 C#进阶系列——WebApi 接口参数不再困惑:传参详解 ..................................................................................................... 56 一、get请求 ......................................................................................................................................................................... 57 1、基础类型参数 ........................................................................................................................................................... 57 2、实体作为参数 ........................................................................................................................................................... 58 3、数组作为参数 ........................................................................................................................................................... 62 4、“怪异”的get请求 .................................................................................................................................................. 62 (1)WebApi方法名称以get开头 ................................................................................................................ 62 (2)WebApi方法名称不以get开头 ............................................................................................................ 64 二、post请求 ....................................................................................................................................................................... 66 1、基础类型参数 ........................................................................................................................................................... 66 (1)错误的写法 ................................................................................................................................................... 66 (2)正确的用法 ................................................................................................................................................... 67 (1)错误写法 ....................................................................................................................................................... 68 (2)正确用法 ....................................................................................................................................................... 69 (3)推荐用法 ....................................................................................................................................................... 70 2、实体作为参数 ........................................................................................................................................................... 70 (1)单个实体作为参数 ....................................................................................................................................... 70 (2)实体和基础类型一起作为参数传递 ........................................................................................................... 73 3、数组作为参数 ........................................................................................................................................................... 74 (1)基础类型数组 ............................................................................................................................................... 74 (2)实体集合 ....................................................................................................................................................... 74 4、后台发送请求参数的传递 ....................................................................................................................................... 75 三、put请求 ......................................................................................................................................................................... 77 1、基础类型参数 ........................................................................................................................................................... 77 2、实体作为参数 ........................................................................................................................................................... 77 3、数组作为参数 ........................................................................................................................................................... 78 四、delete请求 ................................................................................................................................................................... 78 五、总结 ................................................................................................................................................................................. 79 C#进阶系列——WebApi 身份认证解决方案:Basic基础认证.......................................................................................... 80 一、为什么需要身份认证 ..................................................................................................................................................... 81 1、我们不加身份认证,匿名用户可以直接通过url随意访问接口: ........................................................... 81 2、增加了身份认证之后,只有带了我们访问票据的请求才能访问我们的接口。 ....................................... 82 二、Basic基础认证的原理解析 ......................................................................................................................................... 84 1、常见的认证方式 ....................................................................................................................................................... 84 2、Basic基础认证原理 ............................................................................................................................................... 85 三、Basic基础认证的代码示例 ......................................................................................................................................... 85 1、登录过程 ................................................................................................................................................................... 85 1.1、Web前端 ....................................................................................................................................................... 85 1.2、登录的API接口 .......................................................................................................................................... 86 2、/Home/Index主界面 .............................................................................................................................................. 88 3、WebApiCORS验证部分(重点) ............................................................................................................................ 90 3.1、在WebApiCORS项目里面自定义一个类RequestAuthorizeAttribute,去继承我们的AuthorizeAttribute这个类。然后重写OnAuthorization方法,在这个方法里面取到请求头的Ticket信息,然后校验用户名密码是否合理。 ............................................................................................................. 90 3.2、在具体的Api接口增加我们上面自定义类的特性 .................................................................................. 91 四、优化 ................................................................................................................................................................................. 92 1、解决API的问题 ...................................................................................................................................................... 92 2、解决ajax的问题 .................................................................................................................................................... 93 3、解决特殊不想使用验证的方法 ............................................................................................................................... 94 五、总结 ................................................................................................................................................................................. 95 C#进阶系列——WebApi 跨域问题解决方案:CORS ............................................................................................................. 95 一、跨域问题的由来 ............................................................................................................................................................. 96 二、跨域问题解决原理 ......................................................................................................................................................... 96 三、跨域问题解决细节 ......................................................................................................................................................... 96 1、场景描述 ................................................................................................................................................................... 97 2、场景测试 ................................................................................................................................................................... 99 1)我们不做任何的处理,直接将两个项目运行起来。看效果如何 ............................................................... 99 2)使用CORS跨域 ................................................................................................................................................ 99 3)CORS的具体参数设置。 ............................................................................................................................... 103 四、总结 ............................................................................................................................................................................... 104 C#进阶系列——WebApi 接口测试工具:WebApiTestClient ........................................................................................ 105 一、WebApiTestClient介绍 ........................................................................................................................................... 106 二、WebApiTestClient展示 ........................................................................................................................................... 106 三、WebApiTestClient使用 ........................................................................................................................................... 116 1、如何引入组件 ......................................................................................................................................................... 116 2、如何使用组件 ......................................................................................................................................................... 118 1、修改Api.cshtml文件 ................................................................................................................................. 118 2、配置读取注释的xml路径 ............................................................................................................................ 119 3、测试接口 ......................................................................................................................................................... 121 四、总结 ............................................................................................................................................................................... 123

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值