环境.Net 7.0
项目ASP.NET Core WebAPI
筛选器、过滤器、拦截器介绍
创建统一返回值基类
public class BaseResultModel
{
public int? Code { get; set; }
public string Message { get; set; }
public object? Data { get; set; }
public int ReturnStatus { get; set; }
}
拦截特性验证过滤器
IActionFilter 接口
编号 | 方法 | 说明 |
---|---|---|
1 | OnActionExecuted(ActionExecutedContext)) | 在操作执行后调用,然后执行操作结果。 |
2 | OnActionExecuting(ActionExecutingContext)) | 在操作执行之前调用,模型绑定完成后。 |
自定义验证过滤器
/// <summary>
/// 验证过滤器
/// </summary>
public class MyValidationFilterAttribute : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid) // 是否通过验证
{
var result = context.ModelState.Keys
.SelectMany(key => context.ModelState[key]!.Errors.Select(x => new ValidationError(key, x.ErrorMessage)))
.ToList();
context.Result = new ObjectResult(new BaseResultModel
{
Code = 400,
Message = "error",
Data = result,
ReturnStatus = 0
});
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
// throw new NotImplementedException();
}
}
添加过滤器
解除默认限制
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
创建业务
// Person类用于接口请求数据
public class Person
{
[Range(1,10,ErrorMessage = "范围1-10")]
public int Age { get; set; }
[MinLength(2,ErrorMessage = "名称不能低于2个字符")]
public string Name { get; set; } = String.Empty;
}
// API接口
[HttpPost]
public Person AddPerson(Person input)
{
return input;
}
事例
拦截异常过滤器
IExceptionFilter 接口
编号 | 方法 | 说明 |
---|---|---|
1 | OnException(ExceptionContext)) | 在操作引发后 Exception调用 |
自定义异常过滤器
/// <summary>
/// 异常过滤器
/// </summary>
public class MyExceptionFilterAttribute : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
var exception = context.Exception;
context.ExceptionHandled = true;
context.Result = new ObjectResult(new BaseResultModel()
{
Code = 400,
Message = exception.InnerException != null ? exception.InnerException.Message : exception.Message,
Data = exception.Message, // 可改为其他值
ReturnStatus = 3
});
}
}
创建业务
[HttpGet]
public void ThrowException()
{
throw new Exception("抛出了一个异常");
}
添加过滤器
事例
操作筛选器
IActionFilter 接口
编号 | 方法 | 说明 |
---|---|---|
1 | OnActionExecuted(ActionExecutedContext)) | 在操作执行后调用,然后执行操作结果。 |
2 | OnActionExecuting(ActionExecutingContext)) | 在操作执行之前调用,模型绑定完成后。 |
自定义操作筛选器
/// <summary>
/// 操作拦截器
/// </summary>
public class MyActionFilterAttribute : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// throw new NotImplementedException();
}
public void OnActionExecuted(ActionExecutedContext context)
{
var result = context.Result as ObjectResult;
context.Result = new OkObjectResult(new BaseResultModel
{
Code = 200,
Message = "success",
Data = result?.Value,
ReturnStatus = 1
});
}
}
创建业务
[HttpPost]
public DateTime GetNowTime()
{
return DateTime.Now;
}
添加过滤器
事例
使用拦截器统一返回值,将三个过滤器添加到配置中
builder.Services.AddMvc(options =>
{
options.Filters.Add<MyActionFilterAttribute>();
options.Filters.Add<MyExceptionFilterAttribute>();
options.Filters.Add<MyValidationFilterAttribute>();
});
优化
原因
由于【特性拦截器】和【操作拦截器】都继承了IActionFilter接口,但拦截位置不同所以会出现异常信息包含在操作拦截器内(套娃现象),所以要修改两个拦截器内逻辑
解决一
取消特性验证拦截器,在操作拦截器内进行验证判断
/// <summary>
/// 操作拦截器
/// </summary>
public class MyActionFilterAttribute : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// throw new NotImplementedException();
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (!context.ModelState.IsValid)
{
var result = context.ModelState.Keys
.SelectMany(key => context.ModelState[key]!.Errors.Select(x => new ValidationError(key, x.ErrorMessage)))
.ToList();
context.Result = new ObjectResult(new BaseResultModel
{
Code = 400,
Message = "error",
Data = result,
ReturnStatus = ReturnStatus.Fail
});
}
else
{
var statusCode = HttpStatusCode.OK;
var result = context.Result as ObjectResult;
context.Result = new OkObjectResult(new BaseResultModel
{
Code = (int)statusCode,
Message = "success",
Data = result?.Value,
ReturnStatus = ReturnStatus.Success
});
}
}
}
解决二
/// <summary>
/// 操作拦截器
/// </summary>
public class MyActionFilterAttribute : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
var result = context.ModelState.Keys
.SelectMany(
key => context.ModelState[key]!.Errors.Select(x => new ValidationError(key, x.ErrorMessage)))
.ToList();
context.Result = new ObjectResult(new BaseResultModel
{
Code = 400,
Message = "error",
Data = result,
ReturnStatus = ReturnStatus.Fail
});
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
var statusCode = HttpStatusCode.OK;
var result = context.Result as ObjectResult;
context.Result = new OkObjectResult(new BaseResultModel
{
Code = (int)statusCode,
Message = "success",
Data = result?.Value,
ReturnStatus = ReturnStatus.Success
});
}
}
完整代码
/// <summary>
/// 异常过滤器
/// </summary>
public class MyExceptionFilterAttribute : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
var exception = context.Exception;
context.ExceptionHandled = true;
context.Result = new ObjectResult(new BaseResultModel()
{
Code = 400,
Message = exception.InnerException != null ? exception.InnerException.Message : exception.Message,
Data = exception.Message,
ReturnStatus = ReturnStatus.Error
});
}
}
/// <summary>
/// 操作拦截器/特性拦截器
/// </summary>
public class MyActionFilterAttribute : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
var result = context.ModelState.Keys
.SelectMany(
key => context.ModelState[key]!.Errors.Select(x => new ValidationError(key, x.ErrorMessage)))
.ToList();
context.Result = new ObjectResult(new BaseResultModel
{
Code = 400,
Message = "error",
Data = result,
ReturnStatus = ReturnStatus.Fail
});
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
var statusCode = HttpStatusCode.OK;
var result = context.Result as ObjectResult;
context.Result = new OkObjectResult(new BaseResultModel
{
Code = (int)statusCode,
Message = "success",
Data = result?.Value,
ReturnStatus = ReturnStatus.Success
});
}
}
此处评论已关闭