WebAPI笔记:初识WebAPI

代码链接

什么是Web API?

简单地说,API是一种具有一组函数的接口,允许程序员访问应用程序、操作系统或其他服务的特定特性或数据。
Web API是一种可以使用HTTP协议访问的Web API。它是一种概念而不是一种技术。
我们可以使用不同的技术来构建Web API,如Java .net等。
例如Twitter的REST api提供了对读和写数据的编程访问,我们可以使用它将Twitter的功能集成到我们自己的应用程序中。

Web API特性

是构建RESTful服务的理想平台。
将HTTP动词映射到方法名。
支持不同格式的响应数据。内置支持JSON, XML, BSON格式。
可以托管在IIS、自托管或其他支持。
Web API框架包括新的HttpClient与Web API服务器通信。HttpClient可以在ASP.MVC服务器端中使用,Windows窗体应用程序,控制台应用程序或其他应用程序。

Web API Controller

Web API控制器类似于asp.net MVC控制器。它处理传入的HTTP请求并将响应发送回调用者。并且必须派生自System.Web.Http.ApiController类。控制器的所有公共方法都称为动作方法。
根据传入的请求URL和HTTP动词(GET/POST/PUT/PATCH/DELETE),Web API决定执行哪些Web API控制器和操作方法如 GET()方法将处理HTTP GET请求,POST()方法将处理HTTP POST请求,PUT()方法将处理HTTP PUT请求和DELETE()方法将为上述Web API处理HTTP DELETE请求。
如果你想写的方法不是以HTTP动词开始,那么你可以应用适当的HTTP动词属性在方法上,如HttpGet, HttpPost, HttpPut等,就像MVC控制器一样。
Web API控制器特性
它必须派生自System.Web.Http.ApiController类。
它可以在项目根文件夹的任何文件夹下创建。但是,建议按照约定在Controllers文件夹中创建controller类。
动作方法名称可以与HTTP动词名称相同,或者它可以以带有任何后缀的HTTP动词开头(大小写敏感),或者您可以将HTTP动词属性应用于方法。
操作方法的返回类型可以是任何基本类型或复杂类型。
Web API控制器中的操作方法名称扮演着重要的角色。动作方法名可以与HTTP动词(如Get、Post、Put、Patch或Delete)相同。但是,您可以使用HTTP动词附加任何后缀以提高可读性。例如,Get方法可以是GetAllNames()、GetStudents()或以Get开头的任何其他名称。

配置Web API

Web API支持基于代码的配置。不能在web.config中配置。我们可以配置Web API来定制Web API托管基础设施和组件的行为,如路由、格式化程序、过滤器、依赖解析器、消息处理程序、参数、属性、服务等。
Web API项目在App_Start文件夹中包含默认的WebApiConfig类,还包含Global.asax

Web API的路由Routing

Web API路由类似于ASP.net MVC路由。它将传入的HTTP请求路由到Web API控制器上的特定操作方法。
Web API支持两种路由:传统路由;特性路由。
传统路由:Web API使用路由模板来确定要执行哪个控制器和操作方法。为了处理各种HTTP请求,必须在路由表中添加至少一个路由模板。
可以使用HttpConfiguration对象在Web API中配置多个路由。
特性路由:使用[Route()]属性来定义路由。Route属性可以应用于任何控制器或操作方法。

参数绑定

Web API控制器中的操作方法可以有一个或多个不同类型的参数。它可以是基本类型,也可以是复杂类型。
Web API根据参数类型将操作方法参数绑定到URL的查询字符串或请求主体。
默认情况下,如果参数类型是.net基本类型,比如int、bool、double、string、GUID、DateTime、decimal或任何其他可以从string类型转换的类型,那么它将设置查询字符串中的参数值。
如果参数类型是复杂类型,那么默认情况下,Web API尝试从请求体获取值。

查询字符串参数名和操作方法参数名必须相同(不区分大小写)。如果名称不匹配,则不会设置参数的值。参数的顺序可以不同。

Web API将从请求主体中提取JSON对象,并自动将其转换为复杂对象,因为JSON对象属性的名称与Student类属性的名称相匹配(不区分大小写)。
控制器方法包含了基本类型参数和复杂类型参数。因此,在默认情况下,Web API将从查询字符串中获取基本数据类型参数,从请求主体中获取复杂类型参数。
Post操作方法不能包含多个复杂类型参数,因为最多允许从请求主体读取一个参数。

[FromUri] and [FromBody]

在默认情况下,Web API从查询字符串中获取原语参数的值,从请求主体中获取复杂类型参数。但是,如果我们想要改变这种默认行为呢?
使用[FromUri]属性强制Web API从查询字符串中获取复杂类型的值,使用[FromBody]属性从请求主体中获取原始类型的值,与默认规则相反。
使用[FromUri]属性时复杂类型属性的名称和查询字符串参数必须匹配。
使用[FromBody]属性只能应用于操作方法的一个基本参数。它不能应用于同一动作方法的多个基本参数。

Action Method Return Type

Web API操作方法可以有以下返回类型。
Void
Primitive type :基本数据类型
Complex type :自定义复杂数据类型
HttpResponseMessage:Web API控制器总是向托管基础结构返回一个HttpResponseMessage对象。从动作方法发送HttpResponseMessage的好处是,您可以按照自己的方式配置响应。您可以根据需要设置状态码、内容或错误消息(如果有的话)。return Request.CreateResponse(HttpStatusCode.OK, stud);
IHttpActionResult:您可以创建自己的实现IHttpActionResult的类,或者使用ApiController类的各种方法来返回实现IHttpActionResult的对象。return Ok(stud);
下面列出了ApiController类的所有方法,这些方法返回实现IHttpActionResult接口的类的对象。
BadRequest()创建一个状态代码为400的BadRequestResult对象。
Conflict()创建一个状态代码为409的ConflictResult对象。
Content()创建一个具有指定状态代码和数据的NegotiatedContentResult。
Created()创建一个状态代码201 Created的CreatedNegotiatedContentResult。
CreatedAtRoute()创建一个状态码为201的createdatrouteneatedcontentresult。
InternalServerError()创建一个状态码为500内部服务器错误的内部服务器错误。
NotFound()创建一个状态代码为404的NotFoundResult。
Ok()创建一个状态码为200的OkResult。
Redirect()创建一个状态代码为302的重定向RedirectResult 。
RedirectToRoute()创建一个状态码为302的RedirectToRouteResult。
ResponseMessage()使用指定的HttpResponseMessage创建一个ResponseMessageResult。
StatusCode()使用指定的http状态代码创建一个StatusCodeResult。
Unauthorized()创建一个UnauthorizedResult,状态代码401。

Web API Request/Response Data Formats

Web API请求/响应数据格式
在HTTP请求中,MIME类型使用Accept和Content-Type属性在请求头中指定。Accept头属性指定客户端期望的响应数据的格式,Content-Type头属性指定请求体中的数据格式,以便接收方能够将其解析为适当的格式。
Web API将请求数据转换为CLR对象,并将CLR对象序列化为基于接受头和内容类型头的响应数据。Web API包括对JSON、XML、BSON和form-urlencoded数据的内置支持。这意味着它自动将请求/响应数据转换为这些格式OOB(开箱即用)。

ASP.NET Web API: Media-Type Formatters 媒体类型格式器
Web API基于接受头和内容类型头(Accept and Content-Type headers)处理JSON和XML格式。但是,它如何处理这些不同的格式呢?答案是:通过使用媒体类型格式化器。
媒体类型格式化器是负责序列化请求/响应数据的类,以便Web API能够理解请求数据格式并以客户端期望的格式发送数据。

Web API包括以下内置媒体类型格式化程序。
Media Type Formatter Class --MIME Type --Description
JsonMediaTypeFormatter --application/json, text/json --Handles JSON format
XmlMediaTypeFormatter --application/xml, text/json --Handles XML format
FormUrlEncodedMediaTypeFormatter --application/x-www-form-urlencoded --Handles HTML form URL-encoded data
JQueryMvcFormUrlEncodedFormatter --application/x-www-form-urlencoded --Handles model-bound HTML form URL-encoded data

Web API Filters

Web API包括过滤器,用于在操作方法执行之前或之后添加额外的逻辑。过滤器可用于提供横切特性,如日志记录、异常处理、性能度量、身份验证和授权。
下表列出了可用于创建Web API过滤器的重要接口和类。
Filter Type --Interface --Class --Description
Simple Filter --IFilter — --Defines the methods that are used in a filter
Action Filter --IActionFilter --ActionFilterAttribute --Used to add extra logic before or after action methods execute.
Authentication Filter --IAuthenticationFilter — --Used to force users or clients to be authenticated before action methods execute.
Authorization Filter --IAuthorizationFilter --AuthorizationFilterAttribute --Used to restrict access to action methods to specific users or groups.
Exception Filter --IExceptionFilter --ExceptionFilterAttribute --Used to handle all unhandled exception in Web API.
Override Filter --IOverrideFilter — --Used to customize the behaviour of other filter for individual action method.

Webapi中EF如何加载相关实体

在EntityRelationsController中介绍Webapi中EF如何加载相关实体,以及如何在模型类中处理循环导航属性
使用fiddler对api进行测试,再输出日志中查看sql语句验证预先加载、延迟加载和显式加载
有三种方法可以在实体框架中加载相关数据:预先加载、延迟加载和显式加载。

预先加载,则 EF 会将相关实体加载到初始数据库查询中。 若要执行预先加载,请使用system.web.Include扩展方法

延迟加载,EF自动加载相关实体时,要启用延迟加载,请将实体对象的属性的导航属性设置为虚拟virtual:public virtual Author Author { get; set; } //Virtual navigation property启用延迟加载
延迟加载需要多个数据库行程,因为在每次检索相关实体时 EF 都会发送一个查询。 通常,您希望为您序列化的对象禁用延迟加载。 序列化程序必须读取模型上的所有属性,这将触发加载相关实体
有时可能需要使用延迟加载。 预先加载可能会导致 EF 生成非常复杂的联接。 或者,可能需要一小部分数据的相关实体,延迟加载会更有效。
避免序列化问题的一种方法是序列化数据传输对象(Dto)而不是实体对象。
为序列化关闭延迟加载
延迟加载和序列化不会很好地混合,如果您不小心,只是因为启用了延迟加载,最终就可以对整个数据库进行查询。 大多数序列化程序通过访问类型实例上的每个属性来工作。 属性访问会触发延迟加载,因此会序列化更多的实体。
在这些实体上,将访问这些实体的属性,甚至还会加载更多实体。 在对实体进行序列化之前,最好关闭延迟加载
延迟加载序列化问题; 会触发延迟加载;Author也将序列化到json中 //可以Author导航属性关闭延迟加载。关闭所有实体的延迟加载:在FirstWebApiEntities上下文对象构造函数中添加this.Configuration.LazyLoadingEnabled = false;

显式加载:即使已禁用延迟加载,仍可能会延迟加载相关实体,但必须通过显式调用来完成此操作。 为此,请对相关实体的条目使用 Load 方法

使用 Query 计算相关实体而不加载它们
有时,了解数据库中与另一个实体相关的实体的数量并不实际产生加载所有这些实体的成本是非常有用的。 带有 LINQ Count 方法的 Query 方法可用于执行此操作

Author和Book属性中存在循环引用时。当 JSON 或 XML 格式化程序尝试序列化时,将引发异常。 这两个格式化程序引发不同的异常消息

web API 将数据库实体公开给客户端。 客户端接收直接映射到数据库表的数据。 但是,这并不总是一个好主意。 有时,您需要更改发送到客户端的数据的形状例如,你可能希望:
删除循环引用(请参阅上一节)。
隐藏客户端不应查看的特定属性。
省略某些属性以减小负载大小。
平展包含嵌套对象的对象图,以使它们更适合客户端。
避免出现 “过度发布” 漏洞。
将服务层与数据库层分离。

若要实现此目的,可以定义数据传输对象(DTO)如Models/DTOs/BookDetailDto 和 Models/DTOs/BookDto

.NET Web应用中为什么要使用async/await异步编程

如:public async Task GetBookDetail(int id)

什么是async/await?
await和async是.NET Framework4.5框架、C#5.0语法里面出现的技术,目的是用于简化异步编程模型。

async和await的关系?
async和await是成对出现的。
async出现在方法的声明里,用于批注一个异步方法。光有async是没有意义的。
await出现在方法内部,Task前面。只能在使用async关键字批注的方法中使用await关键字。

private async Task DoSomething()
{
await Task.Delay(TimeSpan.FromSeconds(10));
}

async/await会创建新的线程吗?
不会。async/await关键字本身是不会创建新的线程的,但是被await的方法内部一般会创建新的线程。

asp.net mvc/webapi action中使用async/await会提高请求的响应速度吗?
不会。

我们都知道web应用不同于winform、wpf等客户端应用,客户端应用为了保证UI渲染的一致性往往都是采用单线程模式,这个UI线程称为主线程,如果在主线程做耗时操作就会导致程序界面假死,所以客户端开发中使用多线程异步编程非常必要。
可web应用本身就是多线程模式,服务器会为每个请求分配工作线程。
既然async/await不能创建新线程,又不能使提高请求的响应速度,那.NET Web应用中为什么要使用async/await异步编程呢?
在 web 服务器上,.NET Framework 维护用于处理 ASP.NET 请求的线程池。 当请求到达时,将调度池中的线程以处理该请求。 如果以同步方式处理请求,则处理请求的线程将在处理请求时处于繁忙状态,并且该线程无法处理其他请求。
在启动时看到大量并发请求的 web 应用中,或具有突发负载(其中并发增长突然增加)时,使 web 服务调用异步会提高应用程序的响应能力。 异步请求与同步请求所需的处理时间相同。 如果请求发出需要两秒钟时间才能完成的 web 服务调用,则该请求将需要两秒钟,无论是同步执行还是异步执行。 但是,在异步调用期间,线程在等待第一个请求完成时不会被阻止响应其他请求。 因此,当有多个并发请求调用长时间运行的操作时,异步请求会阻止请求队列和线程池的增长。

猜你喜欢

转载自blog.csdn.net/qq_39827640/article/details/107216989