| File: Infrastructure\ModelStateInvalidFilter.cs | Web Access |
| Project: src\aspnetcore\src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj (Microsoft.AspNetCore.Mvc.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable enable using Microsoft.AspNetCore.Mvc.Core; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.Infrastructure; /// <summary> /// A <see cref="IActionFilter"/> that responds to invalid <see cref="ActionContext.ModelState"/>. This filter is /// added to all types and actions annotated with <see cref="ApiControllerAttribute"/>. /// See <see cref="ApiBehaviorOptions"/> for ways to configure this filter. /// </summary> public partial class ModelStateInvalidFilter : IActionFilter, IOrderedFilter { internal const int FilterOrder = -2000; private readonly ApiBehaviorOptions _apiBehaviorOptions; private readonly ILogger _logger; /// <summary> /// Initializes a new instance of <see cref="ModelStateInvalidFilter"/>. /// </summary> /// <param name="apiBehaviorOptions">The api behavior options.</param> /// <param name="logger">The logger.</param> public ModelStateInvalidFilter(ApiBehaviorOptions apiBehaviorOptions, ILogger logger) { _apiBehaviorOptions = apiBehaviorOptions ?? throw new ArgumentNullException(nameof(apiBehaviorOptions)); if (!_apiBehaviorOptions.SuppressModelStateInvalidFilter && _apiBehaviorOptions.InvalidModelStateResponseFactory == null) { throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( typeof(ApiBehaviorOptions), nameof(ApiBehaviorOptions.InvalidModelStateResponseFactory))); } _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } /// <summary> /// Gets the order value for determining the order of execution of filters. Filters execute in /// ascending numeric value of the <see cref="Order"/> property. /// </summary> /// <remarks> /// <para> /// Filters are executed in a sequence determined by an ascending sort of the <see cref="Order"/> property. /// </para> /// <para> /// The default Order for this attribute is -2000 so that it runs early in the pipeline. /// </para> /// <para> /// Look at <see cref="IOrderedFilter.Order"/> for more detailed info. /// </para> /// </remarks> public int Order => FilterOrder; /// <inheritdoc /> public bool IsReusable => true; /// <summary> /// Invoked when an action is executed. /// </summary> /// <param name="context">The <see cref="ActionExecutedContext"/>.</param> public void OnActionExecuted(ActionExecutedContext context) { } /// <summary> /// Invoked when an action is executing. /// </summary> /// <param name="context">The <see cref="ActionExecutingContext"/>.</param> public void OnActionExecuting(ActionExecutingContext context) { if (context.Result == null && !context.ModelState.IsValid) { Log.ModelStateInvalidFilterExecuting(_logger); context.Result = _apiBehaviorOptions.InvalidModelStateResponseFactory(context); } } private static partial class Log { [LoggerMessage(1, LogLevel.Debug, "The request has model state errors, returning an error response.", EventName = "ModelStateInvalidFilterExecuting")] public static partial void ModelStateInvalidFilterExecuting(ILogger logger); } }