ASP.NET Core应用的错误处理[4]:StatusCodePagesMiddleware中间件如何针对响应码呈现错误页面

本文涉及的产品
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
性能测试 PTS,5000VUM额度
云原生网关 MSE Higress,422元/月
简介:

StatusCodePagesMiddleware中间件与ExceptionHandlerMiddleware中间件比较类似,它们都是在后续请求处理过程中“出错”的情况下利用一个错误处理器来完成最终的请求处理与响应的任务。它们之间的差异在于对“错误”的界定上,对于ExceptionHandlerMiddleware中间件来说,它所谓的错误就是抛出异常,但是对于StatusCodePagesMiddleware中间件来说,则将介于400~599之间的响应状态码视为错误。如下面的代码片段所示,StatusCodePagesMiddleware中间件也采用“标准”的定义方式,针对它的配置选项通过一个对应的对象以Options模式的形式提供给它。 [本文已经同步到《ASP.NET Core框架揭秘》之中]

   1: public class StatusCodePagesMiddleware
   2: {
   3:     public StatusCodePagesMiddleware(RequestDelegate next, IOptions<StatusCodePagesOptions> options);
   4:     public Task Invoke(HttpContext context);
   5: }

除了针对错误的界定,StatusCodePagesMiddleware和ExceptionHandlerMiddleware这两个中间件对于错误处理器的表达也不相同。我们知道ExceptionHandlerMiddleware中间件使用的错误处理器实际上就是一个类型为RequestDelegate的委托对象,但是错误处理器之于StatusCodePagesMiddleware中间件来说则是一个类型为Func<StatusCodeContext, Task>的委托对象。如下面的代码片段所示,为StatusCodePagesMiddleware中间件提供配置选项的StatusCodePagesOptions对象的唯一目的就是提供这个作为错误处理器的委托对象。

   1: public class StatusCodePagesOptions
   2: {
   3:     public Func<StatusCodeContext, Task> HandleAsync { get; set; }
   4: }

我们知道一个RequestDelegate对象相当于一个类型为Func<HttpContext, Task>类型的委托对象,而一个StatusCodeContext对象实际上也是对一个HttpContext对象的封装,所以StatusCodePagesMiddleware中间件和ExceptionHandlerMiddleware中间件所使采用的错误处理器并没有本质上的不同。如下面的代码片段所示,除了从StatusCodeContext对象中获取代表当前请求上下文的HttpContext对象之外,我们还可以通过其Next属性得到一个RequestDelegate对象,它代表由后续中间件组成的请求处理管道。至于另一个属性Options,很明显它返回我们在创建StatusCodePagesMiddleware中间件所指定的StatusCodePagesOptions对象。

   1: public class StatusCodeContext
   2: {    
   3:     public HttpContext             HttpContext { get; }
   4:     public RequestDelegate         Next { get; }
   5:     public StatusCodePagesOptions  Options { get; }
   6:  
   7:     public StatusCodeContext(HttpContext context, StatusCodePagesOptions options, RequestDelegate next);
   8: }

一、针对响应状态码的错误处理

由于采用了针对响应状态码的错误处理策略,所以实现在StatusCodePagesMiddleware中间件中的所有错误处理操作只会发生在当前响应状态码在400~599之间的情况,如下所示的代码片段体现了这一点。从下面给出的代码片段可以看出,StatusCodePagesMiddleware中间件在决定是否执行错误处理操作时除了会查看当前响应状态码之外,还会查看响应内容以及媒体类型,如果已经包含了响应内容或者设置了媒体类型,该中间件将不会执行任何操作。

   1: public class StatusCodePagesMiddleware
   2: {
   3:     private  RequestDelegate            _next;
   4:     private  StatusCodePagesOptions     _options;
   5:  
   6: public StatusCodePagesMiddleware(RequestDelegate next, 
   7:     IOptions<StatusCodePagesOptions> options)
   8:     {
   9:         _next         = next;
  10:         _options      = options.Value;
  11:     }
  12:  
  13:     public async Task Invoke(HttpContext context)
  14:     {          
  15:         await _next(context);
  16:         var response = context.Response;
  17:         if ((response.StatusCode >= 400 && response.StatusCode <= 599) &&!response.ContentLength.HasValue && string.IsNullOrEmpty(response.ContentType))
  18:         {
  19:             await _options.HandleAsync(new StatusCodeContext(context, _options, _next));
  20:         }
  21:     }
  22: }

StatusCodePagesMiddleware中间件针对错误的处理非常简单,它只需要从StatusCodePagesOptions对象中提取出作为错误处理器的这个Func<StatusCodeContext, Task>对象,然后创建一个StatusCodeContext对象作为输入参数调用这个委托对象即可。

二、阻止异常处理

如果当前响应已经被写入了内容,或者响应的媒体类型已经被预先设置,那么StatusCodePagesMiddleware中间件将不会再执行任何的错误处理操作。这种情况实际上代表由后续中间件构成的管道可能需要自行控制当前的响应,所以StatusCodePagesMiddleware中间件不应该再做任何的干预。从这个意义上来讲,StatusCodePagesMiddleware中间件仅仅是作为一种后备的错误处理机制而已。

更进一步来将,如果后续的某个中间件返回了一个状态码在400~599之间的响应,并且这个响应只有报头集合没有主体(媒体类型自然也不会设置),那么按照我们在上面给出的错误处理逻辑,StatusCodePagesMiddleware中间件还是会按照自己的策略来处理并响应请求。为了解决这种情况下,我们必须赋予后续中间件一个能够阻止StatusCodePagesMiddleware中间件进行错误处理的能力。

阻止StatusCodePagesMiddleware中间件进行错误处理的机制是借助于一个名为StatusCodePagesFeature的特性来实现的。StatusCodePagesFeature对应如下这个IStatusCodePagesFeature接口,它具有唯一的布尔类型的属性成员Enabled。默认使用的StatusCodePagesFeature类型实现了这个接口,默认情况下这个开关是开启的。

   1: public interface IStatusCodePagesFeature
   2: {
   3:     bool Enabled { get; set; }
   4: }
   5:  
   6: public class StatusCodePagesFeature : IStatusCodePagesFeature
   7: {
   8:     public bool Enabled { get; set; } = true ;
   9: }

StatusCodePagesMiddleware中间件在将请求交付给后续管道之前,它会创建一个StatusCodePagesFeature特性对象并将其添加到当前HttpContext之中。当最终决定是否执行错误处理操作的时候,它还会通过这个特性检验是否某个后续的中间件不希望自己“画蛇添足”地进行不必要的错误处理,如下的代码片段很好的体现了这一点。

   1: public class StatusCodePagesMiddleware
   2: {
   3:
   4:     public async Task Invoke(HttpContext context)
   5:     {
   6:         StatusCodePagesFeature feature = new StatusCodePagesFeature();
   7:         context.Features.Set<IStatusCodePagesFeature>(feature);
   8:  
   9:         await _next(context);
  10:         var response = context.Response;
  11:         if ((response.StatusCode >= 400 && response.StatusCode <= 599) && !response.ContentLength.HasValue &&string.IsNullOrEmpty(response.ContentType) &&
  12:             feature.Enabled)
  13:         {
  14:             await _options.HandleAsync(new StatusCodeContext(context, _options, _next));
  15:         }
  16:     }
  17: }

我们通过一个简单的实例来演示如果利用这个StatusCodePagesFeature特性来屏蔽StatusCodePagesMiddleware中间件。在下面这个应用中,我们将针对请求的处理定义在Invoke方法中,该方法会返回一个状态码为“401 Unauthorized”的响应。我们通过随机数让这个方法会在50%的情况下利用StatusCodePagesFeature特性来阻止StatusCodePagesMiddleware中间件自身对错误的处理。我们通过调用扩展方法UseStatusCodePages注册的StatusCodePagesMiddleware中间件会直接响应一个内容为“Error occurred!”的字符串。

   1: public class Program
   2: {
   3:     public static void Main()
   4:     {
   5:         new WebHostBuilder()
   6:             .UseKestrel()
   7:             .Configure(app => app
   8:                 .UseStatusCodePages(async context => await context.HttpContext.Response.WriteAsync("Error occurred!"))
   9:                 .Run(Invoke))
  10:             .Build()
  11:             .Run();
  12:     }
  13:  
  14:     private static Random _random = new Random();
  15:     private static Task Invoke(HttpContext context)
  16:     {
  17:         context.Response.StatusCode = 401;
  18:  
  19:         if (_random.Next() % 2 == 0)
  20:         {
  21:             context.Features.Get<IStatusCodePagesFeature>().Enabled = false;
  22:         }
  23:         return Task.CompletedTask;
  24:     }
  25: }

对于针对该应用的请求来说,我们会得到如下两种不同的响应。没有主体内容响应是通过Invoke方法产生的,这种情况下发生在StatusCodePagesMiddleware中间件通过StatusCodePagesFeature特性被屏蔽的时候。具有主体内容的响应则来源于StatusCodePagesMiddleware中间件。

   1: HTTP/1.1 401 Unauthorized
   2: Date: Sun, 18 Dec 2016 01:59:37 GMT
   3: Server: Kestrel
   4: Content-Length: 15
   5:  
   6: Error occurred!
   7:  
   8:  
   9: HTTP/1.1 401 Unauthorized
  10: Date: Sun, 18 Dec 2016 01:59:38 GMT
  11: Content-Length: 0
  12: Server: Kestrel

三、注册StatusCodePagesMiddleware中间件

我们在大部分情况下都会调用ApplicationBuilder相应的扩展方法来注册StatusCodePagesMiddleware中间件。对于StatusCodePagesMiddleware中间件的注册来说,除了我们已经很熟悉的UseStatusCodePages方之外,还具有额外一些扩展方法供我们选择。

UseStatusCodePages

我们可以调用如下三个UseStatusCodePages方法重载来注册StatusCodePagesMiddleware中间件。不论我们调用那个重载,系统最终都会根据提供的StatusCodePagesOptions对象调用构造函数来创建这个中间件对象,而且这个StatusCodePagesOptions必须具有一个作为错误处理器的Func<StatusCodeContext, Task>对象。如果没有指定任何参数,StatusCodePagesOptions对象需要以Options模式的形式注册为服务。

   1: public static class StatusCodePagesExtensions
   2: {   
   3:     public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app)
   4:     {      
   5:         return app.UseMiddleware<StatusCodePagesMiddleware>();
   6:     }
   7:  
   8:     public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, StatusCodePagesOptions options)
   9:     {
  10:         return app.UseMiddleware<StatusCodePagesMiddleware>(Options.Create(options));
  11:     }  
  12:     
  13:     public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, Func<StatusCodeContext, Task> handler)
  14:     {       
  15:         return app.UseStatusCodePages(new StatusCodePagesOptions
  16:         {
  17:             HandleAsync = handler
  18:         });
  19:     }
  20: }

由于StatusCodePagesMiddleware中间件最终的目的还是将定制的错误信息响应给客户端,所以我们可以在注册该中间件的时候直接指定响应的内容和媒体类型,这样的注册方式可以通过调用如下这个UseStatusCodePages方法来完成。从如下所示的代码片段我们不难看出,我们通过bodyFormat方法指定的实际上是一个模板,它可以包含一个表示响应状态的占位符(“{0}”)。

   1: public static class StatusCodePagesExtensions
   2: {   
   3:     public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, string contentType, string bodyFormat)
   4:     {
   5:         return app.UseStatusCodePages(context =>
   6:         {
   7:             var body = string.Format(CultureInfo.InvariantCulture, bodyFormat, context.HttpContext.Response.StatusCode);
   8:             context.HttpContext.Response.ContentType = contentType;
   9:             return context.HttpContext.Response.WriteAsync(body);
  10:         });
  11:     }
  12: }

UseStatusCodePagesWithRedirects

如果我们调用UseStatusCodePagesWithRedirects方法,可以让注册的StatusCodePagesMiddleware中间件向指定的路径发送一个客户端重定向。从如下所示的实现代码可以看出,这个作为参数locationFormat的重定向地址也是一个模板,它可以包含一个表示响应状态的占位符(“{0}”)。我们可以指定一个完整的地址,也可以指定一个相对于PathBase的相对路径,后者需要包含表示基地址的“~/”前缀。

   1: public static class StatusCodePagesExtensions
   2: {       
   3:     public static IApplicationBuilder UseStatusCodePagesWithRedirects(this IApplicationBuilder app, string locationFormat)
   4:     {
   5:         if (locationFormat.StartsWith("~"))
   6:         {
   7:             locationFormat = locationFormat.Substring(1);
   8:             return app.UseStatusCodePages(context =>
   9:             {
  10:                 var location = string.Format(CultureInfo.InvariantCulture, locationFormat, context.HttpContext.Response.StatusCode);
  11:                 context.HttpContext.Response.Redirect(context.HttpContext.Request.PathBase + location);
  12:                 return Task.CompletedTask;
  13:             });
  14:         }
  15:         else
  16:         {
  17:             return app.UseStatusCodePages(context =>
  18:             {
  19:                 var location = string.Format(CultureInfo.InvariantCulture, locationFormat, context.HttpContext.Response.StatusCode);
  20:                 context.HttpContext.Response.Redirect(location);
  21:                 return Task.CompletedTask;
  22:             });
  23:         }
  24:     }
  25: }

我们通过一个简单的应用来演示针对客户端重定向的错误页面呈现方式。我们在如下这个应用中注册了一个路由模板为“error/{statuscode}”的路由,路由参数“statuscode”自然代表响应的状态码。在作为路由处理器的HandleError方法中,我们会直接响应一个包含响应状态码的字符串。我们调用UseStatusCodePagesWithRedirects方法注册StatusCodePagesMiddleware中间件的时候将重定义路径设置为“error/{0}”。

   1: public class Program
   2: {
   3:     private static Random _random = new Random();
   4:     public static void Main()
   5:     {
   6:         new WebHostBuilder()
   7:             .UseKestrel()
   8:             .ConfigureServices(svcs => svcs.AddRouting())
   9:             .Configure(app => app
  10:                 .UseStatusCodePagesWithRedirects("~/error/{0}")
  11:                 .UseRouter(builder=>builder.MapRoute("error/{statuscode}", HandleError))
  12:                 .Run(context=>Task.Run(()=>context.Response.StatusCode = _random.Next(400,599))))
  13:             .Build()
  14:             .Run();
  15:     }
  16:         
  17:     private async static Task HandleError(HttpContext context)
  18:     {
  19:         var statusCode = context.GetRouteData().Values["statuscode"];
  20:         await context.Response.WriteAsync($"Error occurred ({statusCode})");
  21:     }
  22: }

针对该应用的请求总是会得到一个状态码在400~599之间的响应, StatusCodePagesMiddleware在此情况下会向我们指定的路径(“~/error/{statuscode}”)发送一个客户端重定向。由于重定向请求的路径与注册的路由相匹配,所以作为路由处理器的HandleError方法会响应如图11所示的这个错误页面。

11

UseStatusCodePagesWithReExecute

除了采用客户端重定向的方式来呈现错误页面之外,我们还可以调用UseStatusCodePagesWithReExecute方法注册StatusCodePagesMiddleware中间件并让它采用服务端重定向的方式来处理错误请求。如下面的代码片段所示,当我们调用这个方法的时候不仅可以指定重定向的路径,还可以指定指定查询字符串。这里作为重定向地址的参数pathFormat依旧是一个路径模板,它可以包含一个表示响应状态的占位符(“{0}”)。

   1: public static class StatusCodePagesExtensions
   2: {
   3:     public static IApplicationBuilder UseStatusCodePagesWithReExecute(this IApplicationBuilder app, string pathFormat, string queryFormat = null);
   4: }

现在我们对上面演示的这个实例略作修改来演示采服务端重定向呈现出来的错误页面。如下面的代码片段所示,我们仅仅将针对UseStatusCodePagesWithRedirects方法的调用替换成针对UseStatusCodePagesWithReExecute方法的调用而已。

   1: public class Program
   2: {
   3:     private static Random _random = new Random();
   4:     public static void Main()
   5:     {
   6:         new WebHostBuilder()
   7:             .UseKestrel()
   8:             .ConfigureServices(svcs => svcs.AddRouting())
   9:             .Configure(app => app
  10:                 .UseStatusCodePagesWithReExecute("/error/{0}")
  11:                 .UseRouter(builder=>builder.MapRoute("error/{statuscode}", HandleError))
  12:                 .Run(context=>Task.Run(()=>context.Response.StatusCode = _random.Next(400,599))))
  13:             .Build()
  14:             .Run();
  15:     }
  16:         
  17:     private async static Task HandleError(HttpContext context)
  18:     {
  19:         var statusCode = context.GetRouteData().Values["statuscode"];
  20:         await context.Response.WriteAsync($"Error occurred ({statusCode})");
  21:     }
  22: }

对于前面演示的实例,由于错误页面是通过客户端重定向的方式呈现出来的,所以浏览器地址栏显示的是重定向地址。我们在选择这个实例中采用了服务端重定向,虽然显示的页面内容并没有不同,但是地址栏上的地址是不会发生改变的

12

之所以被命名为UseStatusCodePagesWithReExecute,是因为通过这方法注册的StatusCodePagesMiddleware中间件进行错误处理的时候,它仅仅是提供的重定向路径和查询字符串应用到当前HttpContext,然后递交给后续管道重新执行。UseStatusCodePagesWithReExecute方法中注册StatusCodePagesMiddleware中间件的实现总体上可以由如下所示的代码片段来体现。

   1: public static class StatusCodePagesExtensions
   2: {    
   3:     public static IApplicationBuilder UseStatusCodePagesWithReExecute(this IApplicationBuilder app,string pathFormat,string queryFormat = null)
   4:     {
   5:         return app.UseStatusCodePages(async context =>
   6:         {
   7:             var newPath = new PathString(string.Format(CultureInfo.InvariantCulture, pathFormat, context.HttpContext.Response.StatusCode));
   8:             var formatedQueryString = queryFormat == null ? null :string.Format(CultureInfo.InvariantCulture, queryFormat, context.HttpContext.Response.StatusCode);            
   9:             context.HttpContext.Request.Path = newPath;
  10:             context.HttpContext.Request.QueryString = newQueryString;
  11:             await context.Next(context.HttpContext);
  12:         });
  13:     }
  14: }

与ExceptionHandlerMiddleware中间价类似,StatusCodePagesMiddleware中间件在处理请求的过程中会改变当前请求上下文的状态,具体体现在将指定的请求路径和查询字符串重新应用到当前请求上下文中。为了不影响前置中间件对请求的正常处理,StatusCodePagesMiddleware中间件在完成自身处理流程之后必须将当前请求上下文恢复到原始的状态。StatusCodePagesMiddleware中间件依旧是采用一个特性来保存原始的路径和查询字符串。这个特性对应的接口为具有如下定义的IStatusCodeReExecuteFeature,令人费解的是该接口仅仅包含两个针对路径的属性,并没有我们希望的用于携带原始查询上下文的属性,但是默认实现类型StatusCodeReExecuteFeature包含了这个属性。

   1: public interface IStatusCodeReExecuteFeature
   2: {
   3:     string OriginalPath { get; set; }
   4:     string OriginalPathBase { get; set; }
   5: }
   6:  
   7: public class StatusCodeReExecuteFeature : IStatusCodeReExecuteFeature
   8: {
   9:     public string OriginalPath { get; set; }
  10:     public string OriginalPathBase { get; set; }
  11:     public string OriginalQueryString { get; set; }
  12: }

当StatusCodePagesMiddleware中间件在处理异常请求的过程中,在将指定的重定向路径和查询字符串应用到当前请求上下文上之前,它会根据原始的上下文创建一个StatusCodeReExecuteFeature特性对象并将其添加到当前HttpContext之上。当整个请求处理过程结束之后,StatusCodePagesMiddleware中间件还会负责将这个特性从当前HttpContext中移除,并恢复原始的请求路径和查询字符串。如下所示的代码片段体现了UseStatusCodePagesWithReExecute方法的真实逻辑。

   1: public static class StatusCodePagesExtensions
   2: {
   3:     public static IApplicationBuilder UseStatusCodePagesWithReExecute(this IApplicationBuilder app,string pathFormat,string queryFormat = null)
   4:     {    
   5:         return app.UseStatusCodePages(async context =>
   6:         {
   7:             var newPath = new PathString(string.Format(CultureInfo.InvariantCulture, pathFormat, context.HttpContext.Response.StatusCode));
   8:             var formatedQueryString = queryFormat == null ? null :string.Format(CultureInfo.InvariantCulture, queryFormat, context.HttpContext.Response.StatusCode);
   9:             var newQueryString = queryFormat == null ? QueryString.Empty : new QueryString(formatedQueryString);
  10:  
  11:             var originalPath = context.HttpContext.Request.Path;
  12:             var originalQueryString = context.HttpContext.Request.QueryString;
  13:  
  14:             context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(new StatusCodeReExecuteFeature()
  15:             {
  16:                 OriginalPathBase = context.HttpContext.Request.PathBase.Value,
  17:                 OriginalPath = originalPath.Value,
  18:                 OriginalQueryString = originalQueryString.HasValue ? originalQueryString.Value : null,
  19:             });
  20:  
  21:             context.HttpContext.Request.Path = newPath;
  22:             context.HttpContext.Request.QueryString = newQueryString;
  23:             try
  24:             {
  25:                 await context.Next(context.HttpContext);
  26:             }
  27:             finally
  28:             {
  29:                 context.HttpContext.Request.QueryString = originalQueryString;
  30:                 context.HttpContext.Request.Path = originalPath;
  31:                 context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(null);
  32:             }
  33:         });
  34:     }
  35: }

ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式
ASP.NET Core应用的错误处理[2]:DeveloperExceptionPageMiddleware中间件
ASP.NET Core应用的错误处理[3]:ExceptionHandlerMiddleware中间件
ASP.NET Core应用的错误处理[4]:StatusCodePagesMiddleware中间件


作者:蒋金楠
微信公众账号:大内老A
微博: www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
10天前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
32 5
|
2月前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
28天前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
38 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
18天前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
24 3
|
29天前
|
消息中间件 存储 Apache
探索 RocketMQ:企业级消息中间件的选择与应用
RocketMQ 是一个高性能、高可靠、可扩展的分布式消息中间件,它是由阿里巴巴开发并贡献给 Apache 软件基金会的一个开源项目。RocketMQ 主要用于处理大规模、高吞吐量、低延迟的消息传递,它是一个轻量级的、功能强大的消息队列系统,广泛应用于金融、电商、日志系统、数据分析等领域。
59 0
探索 RocketMQ:企业级消息中间件的选择与应用
|
1月前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
27天前
|
Web App开发 JSON JavaScript
Node.js 中的中间件机制与 Express 应用
Node.js 中的中间件机制与 Express 应用
|
1月前
|
JSON 算法 安全
JWT Bearer 认证在 .NET Core 中的应用
【10月更文挑战第30天】JWT(JSON Web Token)是一种开放标准,用于在各方之间安全传输信息。它由头部、载荷和签名三部分组成,用于在用户和服务器之间传递声明。JWT Bearer 认证是一种基于令牌的认证方式,客户端在请求头中包含 JWT 令牌,服务器验证令牌的有效性后授权用户访问资源。在 .NET Core 中,通过安装 `Microsoft.AspNetCore.Authentication.JwtBearer` 包并配置认证服务,可以实现 JWT Bearer 认证。具体步骤包括安装 NuGet 包、配置认证服务、启用认证中间件、生成 JWT 令牌以及在控制器中使用认证信息
|
3月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
3月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
111 3
下一篇
DataWorks