ASP.NET Web API 细节

作者:vkvi 来源:ITPOW(原创) 日期:2022-4-19

准备工作

Visual Studio 新建一个“ASP.NET Web 应用程序(.NET Framework)”,最后一步选择模板时,选择“空”,然后在右边勾上“Web API”。

Web API

我们可以看到 App_Start/WebApiConfig.cs 中配置了路由,我们保持默认不变:

public static void Register(HttpConfiguration config)
{
	// Web API 配置和服务

	// Web API 路由
	config.MapHttpAttributeRoutes();

	config.Routes.MapHttpRoute(
		name: "DefaultApi",
		routeTemplate: "api/{controller}/{id}",
		defaults: new { id = RouteParameter.Optional }
	);
}

在 Controllers 上新建一个“Web API 2 控制器 - 空”,我们取名:BookController,自动派生自 ApiController,代码如下:

public class BookController : ApiController
{
	public string Get()
	{
		return "itpow";
	}
}

Ctrl + F5 运行。

基本细节

忽略大小写

根据路由规则,我们在浏览器中输入 xxx/api/book,即可得到 itpow。关于此,请继续阅读.NET Web API 如何输出字符串、XML、JSON

这是忽略大小写的,xxx/aPI/boOk,效果是一样的。

最后加不加斜杠也是一样的。

Get、Post 不会相互“串”

使用 Postman 一类的调试功能,以 POST 方式提交上述网址,会发现:

{
    "Message": "请求的资源不支持 http 方法“POST”。"
}

因为我们只写了 Get 方法,没写 Post 方法,它们之间并不会串,不存在说 Post 不存在,交给 Get 处理的情况。

反过来也是一样的。

Get 参数可用路由,也可用 QueryString

public class BookController : ApiController
{
	public string Get(int id)
	{
		return "itpow" + id;
	}
}

现在我们加了个参数,id。访问有两种形式:

  • xxx/api/book/2 或 xxx/api/book/2/

  • xxx/api/book?id=2 或 xxx/api/book/?id=2

得到的结果都是 itpow2。

参数匹配

调用参数多得少不得(重要)

如上,假如我们访问:

xxx/api/book?id=2&name=b 或 xxx/api/book/?id=2&name=b

得到的结果和上面是一样的。

不过要注意,不能这样访问:

xxx/api/book/2/b 或 xxx/api/book/2/b/

因为我们前面没有这样配路由(我们使用默认路由:api/{controller}/{id}),所以会报 404 错误。

同样,对 Get() 方法(不带参数),我们用带了 id 的 Url 去访问,是不会出错的,因为参数多得少不得嘛。

如果参数少了,会报什么错误呢?

  • 比如要求 1 个参数,但是没提供参数(注意:id= 不叫没参数,它叫参数没值)。

  • 或者要求 id 参数,但是我们 QueryString 中不叫 id,叫 id1。

是会报错的:

{
    "Message": "找不到与请求 URI“http://localhost:57762/api/book?id1=2”匹配的 HTTP 资源。",
    "MessageDetail": "在控制器“Book”上找不到与该请求匹配的操作。"
}

支持重载

public class BookController : ApiController
{
	public string Get()
	{
		return "itpow";
	}

	public string Get(int id)
	{
		return "itpow" + id;
	}
}

根据有没有传 id 参数,来决定调哪个。

路由中 id 和参数中 id 不一样时

Get 方法中的参数 id 名字,与 QueryString 中的 id 应该一样。

路由仅仅是帮助我们构造 QueryString比如我把路由中 id 改为 id1,xxx/api/book/2 实际上是 xxx/api/book?id1=2,至于什么效果,根据前面的总结就知道了。

QueryString 的参数顺序,不需要与 Get 方法的参数顺序一致。因为它是看名称来匹配的,不是看顺序来匹配的。

Post

Post 方法的参数,也可能是 QueryString(重要)

public class BookController : ApiController
{
	public string Post(int id)
	{
		return "itpow" + id;
	}
}

如上是 Post 方法了,我们应该 POST 提交,这个 id 是不是 POST 项的一部分呢?错,它仍然应该由 QueryString 指定。

Json 参数不是 QueryString

public class BookController : ApiController
{
	public string Post(RequestJson requestJson)
	{
		return "itpow" + requestJson.id;
	}
}


public class RequestJson
{
	public int id;
}

如上,是不是通过 QueryString 提交一个名称为 requestJson 的数据呢?

错!这里就不再是 QueryString 了,而是 POST,并且是不带参数名称的 POST。

如下:

Post Json

这里还有一点说明:利用 x-www-form-urlencoded(就是普通 POST)提交一个任意名称的值,它不会报错,虽然 JSON 不存在,但是它以默认值来赋,此时 id 作为 int 默认值是 0。(看完本文,就更能理解了)

不支持 Json 内容级别的重载(重要)

public class BookController : ApiController
{
	public string Post(RequestJson1 requestJson)
	{
		return "itpow" + requestJson.id;
	}
	public string Post(RequestJson2 requestJson)
	{
		return "itpow" + requestJson.name;
	}
}


public class RequestJson1
{
	public int id;
}

public class RequestJson2
{
	public string name;
}

以上程序编译不出错,我们在想,是不是会根据不同的 Json 格式,调用不同的方法呢?

其实还实现不到这么细,它暂时还无法根据内容分辨是 RequestJson1,还是 RequestJson2。

会出现“找到了与该请求匹配的多个操作”的错误。

QueryString 与 Json 混合

public string Post(int type, RequestJson1 requestJson)

它会知道 type 来自于 QueryString,requestJson 来自于 POST。

FromBody

前面说,Post 方法:

  • JSON 以外的参数,来自于 QueryString。

  • JSON 参数来自于 Post。

但是我看到有一个 FromBody,FromBody 是不是指不让其来自于 QueryString 呢?

public class BookController : ApiController
{
	public string Post([FromBody]int id)
	{
		return "itpow" + id;
	}
}

我们是不是 POST id=1,就可以调用它了呢?

不对!

FromBody,是指整个 Post 内容,如上的话,调用时,我们就直接 POST id 的值,不要写 id 名称。

FromBody

所以我们继续总结应该是这样的:

  • 普通参数,没标明 FromBody,来自于 QueryString。

  • 普通参数,标题了 FromBody,来自于整个 Post 内容区。

  • JSON 参数,来自于整个 POST 内容区。

如果我们不要取整个 POST 内容区,就要用普通的提交项,可用 Request.Form,比如:

public class BookController : ApiController
{
	public string Post()
	{
		return "itpow" + HttpContext.Current.Request.Form["id"];
	}
}

相关阅读

相关文章