【发布时间】:2019-07-13 03:16:22
【问题描述】:
我尝试将我之前在 Asp.net MVC 4 上的项目中的验证替换为 Asp.net Core。并且有一些问题。 Asp.net Core 项目中的流程是这样的:
中间件 => ControllerCTOR => FluValidator => 过滤器 => 动作
此外,当 FluValidator 中的某些规则失败时,它只是通过中间件堆栈向客户端返回带有错误的响应。但我需要在 Filter 或 Action 中访问 ModelState。
为什么这不能正常工作?或者,如果它真的是正确的流程,如何让它更深入到Action?
启动
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(typeof(ValidateModelAttribute));
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<Startup>());
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddNLog();
env.ConfigureNLog("nlog.config");
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "CorpLight API V1");
});
app.UseMiddleware<RequestResponseLoggingMiddleware>();
app.UseMiddleware<ErrorHandlingMiddleware>();
app.UseMiddleware<AuthenticateMiddleware>();
app.UseMvc();
}
中间件
private readonly RequestDelegate _next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
验证器
public class CardInformationRequestValidator : AbstractValidator<RequestModel<CardInformationRequest>>
{
public CardInformationRequestValidator()
{
RuleFor(x => x.Request.RU)
.NotNull()
.NotEmpty();
RuleFor(x => x.Request.Currency)
.NotNull()
.NotEmpty();
RuleFor(x => x.Request.AccountNumber)
.NotNull()
.NotEmpty();
}
}
控制器
[Route("api/[controller]")]
[ApiController]
public class CardController : ControllerBase
{
private readonly ICardRepo _cardRepo;
private readonly IMapper _mapper;
public CardController(ICardRepo cardRepo, IMapper mapper)
{
_cardRepo = cardRepo;
_mapper = mapper;
}
[HttpPost]
public async Task<MessageWithElements<CardInformation, CardInfo>> CardInformations(RequestModel<CardInformationRequest> request)
{
if (!ModelState.IsValid)
throw new InvalidParametersException($"can't be empty");
//logic
}
}
过滤器
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
//logic
}
}
}
典型的有效 Json:
{
"request": {
"ru": "string",
"accountNumber": "string",
"currency": 1
}
}
典型的无效 Json:
{
"request": {
"ru": "string",
"accountNumber": "string",
"currency": 0
}
}
当货币不为零时,它是有效的,并到达过滤器。但是当它为零时,NotEmpty 会失败并返回。
有效请求的典型响应:
{
"elements": [
{
<object fields>
}
],
"messageText": "string",
"messageNumber": 1
}
无效请求的典型响应(400 错误请求):
{
"Request.Currency": [
"'Request. Currency' must not be empty."
]
}
【问题讨论】:
-
请说明实际工作不正常的地方。可以访问 ModelState 还是其他东西?更清楚地描述问题,它太宽泛了。问候。
-
例如我开始调试。如果发送有效请求,它将通过中间件到 ControllerCTOR,然后 Fluentvalidator 开始按规则检查模型。由于模型是有效的,ModelState 中的属性 IsValid 变为 true。请求进入过滤器,然后进入操作,我可以在其中检查 ModelState 是否有效并做出一些格式响应。但是如果模型无效。它只是通过失败的规则返回错误的响应,而不到达过滤器或操作。
-
请在
app.UseYourMiddleware的地方添加代码 -
完成。添加启动的配置方法
标签: c# .net-core asp.net-core-2.0 fluentvalidation