巧用ExceptionFilter筛选器

异常筛选器

异常筛选器怎么使用我就不说了。

主要记录两点:

1、如何在开发环境和生产环境提示不同的异常信息?
		因为我们知道,项目在开发期间是需要将异常完整信息展示方便开发人员排错,而正式上线时候就不应该完全展现了,因为太详细容易被恶意攻击。(利用IWebHostEnvironment获取环境)

2、存在多个异常筛选器如何排序?
	  虽然一个项目使用多个异常筛选器不太可能,但还是值得记录一下。	

第一点

1、创建异常类

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Cache.Api
{
    public class MyExceptionFilter : IAsyncExceptionFilter
    {
        //获取当前环境
        private readonly IWebHostEnvironment _hostEnvironment;

        public MyExceptionFilter(IWebHostEnvironment hostEnvironment)
        {
            _hostEnvironment = hostEnvironment;
        }

        public Task OnExceptionAsync(ExceptionContext context)
        {

            string msg;
            if(_hostEnvironment.IsDevelopment())
            {
                msg = context.Exception.ToString();
            }
            else
            {
                msg = "服务器端发生未处理异常";
            }

            ObjectResult objectResult = new ObjectResult(new {code = 500,message = msg});
            context.Result = objectResult;
            
            //这个设置true,后面再细说
            context.ExceptionHandled = false;

            return Task.CompletedTask;
        }
    }
}

2、在Progame.cs中注入服务

using Cache.Api;
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<MvcOptions>(opt=>{
    opt.Filters.Add<MyExceptionFilter>();
});

var app = builder.Build();

3、查看launchsettings.json文件此时ASPNETCORE_ENVIRONMENT都为Development

{
  "profiles": {
    "Cache.Api": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "swagger",
      "applicationUrl": "http://localhost:5024",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

4、控制器模拟异常

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace Cache.Api.Controllers;

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [HttpGet("GetException")]
    public dynamic GetException()
    {
        string n = null;
        return n.ToString();
    }
}

5、终端运行并请求接口(注意:当使用终端运行程序时候获取的环境是launchsettings.json文件profiles中Development值,当使用IIS Express则获取IIS Express的Development值)

PS C:\Users\张跑跑\Desktop\net\Cache\Cache.Api> dotnet run
正在生成...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5024
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: nononoDevelopment
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\Users\张跑跑\Desktop\net\Cache\Cache.Api\

可以看到在Development情况下走的是 msg = context.Exception.ToString();

修改Development后走的是 msg = "服务器端发生未处理异常";

  "profiles": {
    "Cache.Api": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "swagger",
      "applicationUrl": "http://localhost:5024",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "nonononoDevelopment"
      }
    }

成功!



第二点

1、我们创建两个异常类,它们context.ExceptionHandled分别为true,false

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Cache.Api
{
    public class MyExceptionFilter2 : IAsyncExceptionFilter
    {
        public Task OnExceptionAsync(ExceptionContext context)
        {

            context.Result = new ObjectResult(new 
            {
                code = 500,
                message = "我先处理"
            });

            context.ExceptionHandled = false;

            return Task.CompletedTask;
        }   
    }
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Cache.Api
{
    public class MyExceptionFilter3 : IAsyncExceptionFilter
    {
        public Task OnExceptionAsync(ExceptionContext context)
        {

            context.Result = new ObjectResult(new 
            {
                code = 500,
                message = "我为什么还要处理啊!"
            });

            context.ExceptionHandled = true;

            return Task.CompletedTask;
        }   
    }
}

2、然后注册这两个,注意把为false的先注册

using Cache.Api;
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<MvcOptions>(opt=>{
    opt.Filters.Add<MyExceptionFilter2>();
    opt.Filters.Add<MyExceptionFilter3>();
});

var app = builder.Build();

3、浏览器查看会发现异常居然一直走到第二个异常上

这是因为context.ExceptionHandled = false;表示我处理的异常还将传给在我后面注册的异常筛选器。

4、现在我们将值改为true

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Cache.Api
{
    public class MyExceptionFilter2 : IAsyncExceptionFilter
    {
        public Task OnExceptionAsync(ExceptionContext context)
        {

            context.Result = new ObjectResult(new 
            {
                code = 500,
                message = "我先处理"
            });

            context.ExceptionHandled = true;

            return Task.CompletedTask;
        }   
    }
}

成功!

posted @ 2023-01-28 22:32  long-livece  阅读(74)  评论(0编辑  收藏  举报