Я попытался заменить валидацию из моего предыдущего проекта на Asp.net MVC 4 на Asp.net Core.И есть некоторые проблемы.Поток в проекте Asp.net Core выглядит так:
Middleware => ControllerCTOR => FluValidator => Filter => Action
Также, когда некоторые из правил в FluValidator не сработали, это просто возвратный ответ с ошибкамичерез Middleware стека к клиенту.Но мне нужно иметь доступ к ModelState в фильтре или в действии.
Почему это не работает правильно?Или, если это действительно правильный поток, как заставить его идти глубже в Action?
Startup
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();
}
Middleware
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);
}
}
Validator
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."
]
}