У меня была такая же ошибка, когда я захотел запустить мой проект WinForms (который включает в себя работу с базой данных SQL Server и отлично работающую на моем ПК) на другом ПК. Проблема была в брандмауэре Windows на моем ПК. Я решил это, добавив два правила. Это вся процедура, позволяющая SQL Server через брандмауэр Windows:
services.msc
firewall.cpl
, нажмите «Разрешить приложение» или добавить правило, добавить ранее скопированный путь (есть процедура вам нужно следовать), проверьте Домен и Частный, снимите флажок Public. Это ссылка YouTube, где вы можете увидеть эту процедуру: Разрешить SQL Server через брандмауэр Windows
Вы можете использовать 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);
}
}
Существующие ответы до сих пор предназначены для 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));
См. больше в официальной документации .
В качестве продолжения этого: в ASP.NET Core 2.1 существует атрибут контроллера, называемый [ApiController]
. Если вы включите этот атрибут, он автоматически использует встроенный ActionFilter
, называемый ModelStateInvalidFilter
, то есть любой настраиваемый фильтр действий, который проверяет ModelState, никогда не будет достигнут, поскольку атрибут [ApiController]
уже регистрирует свой собственный фильтр.
Чтобы подавить поведение, текущие документы предоставляют эту опцию:
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true; // This is the setting
});
Для 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());
});
}
Для методов async
фильтр должен реализовать IAsyncActionFilter
. Я собрал этот фильтр, который:
ИЛИ
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);
}
}
Использовать HandleInvalidModelState
PM> Install-Package HandleInvalidModelState
example
[HttpPost]
[TypeFilter(typeof(HandleInvalidModelWithViewActionFilterAttribute))]
public IHttpActionResult Post(object model)
{}
Кроме сценария основных случаев (возврат с недопустимой моделью ) поддерживает возвраты Json и Перенаправление запроса.
отказ от ответственности: автор пакета
ApiController
из Web Api 2, он больше не существует в ASP.NET Core. Помимо этого, вы не должны добавлять к своим фильтрамActionFilterAttribute
, а простоAttribute
. Еще больше намерений было быValidateModelStateAttribute
– Camilo Terevinto 26 January 2017 в 13:08Startup
– Camilo Terevinto 26 January 2017 в 13:10