Центральная проверка модели запроса [дубликат]

У меня была такая же ошибка, когда я захотел запустить мой проект WinForms (который включает в себя работу с базой данных SQL Server и отлично работающую на моем ПК) на другом ПК. Проблема была в брандмауэре Windows на моем ПК. Я решил это, добавив два правила. Это вся процедура, позволяющая SQL Server через брандмауэр Windows:

  1. Откройте «Выполнить» и введите services.msc
  2. . Найдите службу для SQL Server (имя экземпляра) и SQL Server Browser. По одному за раз щелкните правой кнопкой мыши, выберите «Свойства», скопируйте путь к файлу exe
  3. . Затем откройте firewall.cpl, нажмите «Разрешить приложение» или добавить правило, добавить ранее скопированный путь (есть процедура вам нужно следовать), проверьте Домен и Частный, снимите флажок Public.

Это ссылка YouTube, где вы можете увидеть эту процедуру: Разрешить SQL Server через брандмауэр Windows

7
задан Camilo Terevinto 26 January 2017 в 13:06
поделиться

6 ответов

Вы можете использовать ActionFilter . Это не глобально, но оно перемещает проблему из вашего тела метода в атрибут. Я понимаю, что он полностью не решает вашу проблему, но может быть лучше, чем ничего.

public class ModelStateValidationActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var modelState = actionContext.ModelState;

        if (!modelState.IsValid)
            actionContext.Response = actionContext.Request
                 .CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
    }
}

И в вашем контроллере:

[HttpPost]
[ModelStateValidationActionFilter]
public IHttpActionResult Post(object model)
{

}

Я считаю, что вы можете установите его и на контроллер. Я действительно не пробовал это, но в соответствии с этим он мог работать.

[ModelStateValidationActionFilter]
public class MyApiController : ApiController
{

}

EDIT:

As @Camilo Terevinto упомянул, что для Core немного отличается. Просто используйте этот ActionFilter, если вы хотите использовать Core.

public class ModelStateValidationActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {    
        var modelState = context.ModelState;

        if (!modelState.IsValid)
            context.Result = new ContentResult()
            {
                Content = "Modelstate not valid",
                StatusCode = 400
            };
        base.OnActionExecuting(context);
    }
}
8
ответ дан Community 19 August 2018 в 17:02
поделиться
  • 1
    ApiController из Web Api 2, он больше не существует в ASP.NET Core. Помимо этого, вы не должны добавлять к своим фильтрам ActionFilterAttribute, а просто Attribute. Еще больше намерений было бы ValidateModelStateAttribute – Camilo Terevinto 26 January 2017 в 13:08
  • 2
    Кроме того, фильтры действий могут регистрироваться глобально в Startup – Camilo Terevinto 26 January 2017 в 13:10
  • 3
    @CamiloTerevinto, да, вы правы. Я пропустил основную часть. Я обновил свой ответ с помощью соответствующего ActionFilterAttribute, который будет работать с Core. – smoksnes 26 January 2017 в 13:23
  • 4
    Почему вы вызываете base.OnAction Выполнение (контекст) дважды в вашем примере кода? – Sam 26 January 2017 в 13:34
  • 5
    @Sam, copy-paste-error. Я удалил его. – smoksnes 26 January 2017 в 13:35

Существующие ответы до сих пор предназначены для ASP.NET Web API, а не для ASP.NET Core. Фактический способ сделать это в ASP.NET Core:

public class SampleActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // do something before the action executes
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // do something after the action executes
    }
}

И вы можете зарегистрировать этот фильтр по всему миру в Startup.cs, так что это будет выполняться в каждом отдельном вызове, и вам не нужно повторять он в каждом Action / Controller:

options.Filters.Add(typeof(SampleActionFilter));

См. больше в официальной документации .

6
ответ дан Camilo Terevinto 19 August 2018 в 17:02
поделиться

В качестве продолжения этого: в ASP.NET Core 2.1 существует атрибут контроллера, называемый [ApiController]. Если вы включите этот атрибут, он автоматически использует встроенный ActionFilter, называемый ModelStateInvalidFilter, то есть любой настраиваемый фильтр действий, который проверяет ModelState, никогда не будет достигнут, поскольку атрибут [ApiController] уже регистрирует свой собственный фильтр.

Чтобы подавить поведение, текущие документы предоставляют эту опцию:

services.Configure<ApiBehaviorOptions>(options =>
{
   options.SuppressModelStateInvalidFilter = true; // This is the setting
});
1
ответ дан Jason 19 August 2018 в 17:02
поделиться

Для ASP.NET Core 2.0, чтобы не применять атрибуты ко всем Controllers или Actions индивидуально;

Определить фильтр:

namespace Test
{
    public sealed class ModelStateCheckFilter : IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context) { }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            if (!context.ModelState.IsValid)
            {
                context.Result = new BadRequestObjectResult(context.ModelState);
            }
        }
    }
}

Затем в вашем Startup.cs, добавьте его как фильтр:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(config =>
        {
            config.Filters.Add(new ModelStateCheckFilter());
        });
    }
2
ответ дан Mert Akcakaya 19 August 2018 в 17:02
поделиться

Для методов async фильтр должен реализовать IAsyncActionFilter. Я собрал этот фильтр, который:

  • ничего не делает, если ModelState действителен

ИЛИ

  • устанавливает Результат BadRequestObjectResult с некоторыми подробностями о том, что не удалось
  • записывает ModelState с более подробной информацией

public class ValidModelStateAsyncActionFilter : IAsyncActionFilter
{
    // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/loggermessage?view=aspnetcore-2.1
    private static readonly Action<ILogger, IList<(string Key, string ErrorMessage, string ExceptionMessage)>, Exception> ModelStateLoggerAction;

    private readonly ILogger<ValidModelStateAsyncActionFilter> logger;

    static ValidModelStateAsyncActionFilter()
    {
        ModelStateLoggerAction = LoggerMessage.Define<IList<(string Key, string ErrorMessage, string ExceptionMessage)>>(LogLevel.Warning, new EventId(1, nameof(ValidModelStateAsyncActionFilter)), "{ModelState}");
    }

    public ValidModelStateAsyncActionFilter(ILogger<ValidModelStateAsyncActionFilter> logger)
    {
        this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        if (context.ModelState.IsValid)
            await next();

        this.LogModelState(context);

        context.Result = new BadRequestObjectResult(GetErrorResponse(context));
    }

    private static ErrorResponse GetErrorResponse(ActionContext context)
    {
        return new ErrorResponse
        {
            ErrorType = ErrorTypeEnum.ValidationError,
            Message = "The input parematers are invalid.",
            Errors = context.ModelState.Values.SelectMany(x => x.Errors)
                .Select(x => x.ErrorMessage)
                .Where(x => !string.IsNullOrEmpty(x))
                .ToList()
        };
    }

    private void LogModelState(ActionContext context)
    {
        // credit: https://blogs.msdn.microsoft.com/mazhou/2017/05/26/c-7-series-part-1-value-tuples/
        var items = from ms in context.ModelState
                    where ms.Value.Errors.Any()
                    let fieldKey = ms.Key
                    let errors = ms.Value.Errors
                    from error in errors
                    select (Key: fieldKey, ErrorMessage: error.ErrorMessage, ExceptionMessage: error.Exception.Message);

        ModelStateLoggerAction(this.logger, items.ToList(), null);
    }
}
0
ответ дан Skorunka František 19 August 2018 в 17:02
поделиться

Использовать HandleInvalidModelState

PM> Install-Package HandleInvalidModelState

example

[HttpPost]
[TypeFilter(typeof(HandleInvalidModelWithViewActionFilterAttribute))]
public IHttpActionResult Post(object model)
{}

Кроме сценария основных случаев (возврат с недопустимой моделью ) поддерживает возвраты Json и Перенаправление запроса.

отказ от ответственности: автор пакета

0
ответ дан tchelidze 19 August 2018 в 17:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: