namespace MyOffice.Web.Infrastructure.Attributes; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.ModelBinding; [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class DefaultFromBodyAttribute : Attribute { } public class GlobalModelStateValidatorAttribute : ActionFilterAttribute { private readonly ProblemDetailsFactory _problemDetailsFactory; public GlobalModelStateValidatorAttribute(ProblemDetailsFactory problemDetailsFactory) { _problemDetailsFactory = problemDetailsFactory; } public override void OnActionExecuting(ActionExecutingContext context) { if (!context.ModelState.IsValid) { context.Result = new ObjectResult(_problemDetailsFactory.CreateValidationProblemDetails(context.HttpContext, context.ModelState)) { StatusCode = StatusCodes.Status400BadRequest }; } base.OnActionExecuting(context); } } public class DefaultFromBodyBindingConvention : IActionModelConvention { public void Apply(ActionModel action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } if (action.Controller.Attributes.Any(a => a is DefaultFromBodyAttribute)) { foreach (var parameter in action.Parameters) { var paramType = parameter.ParameterInfo.ParameterType; var isSimpleType = paramType.IsPrimitive || paramType.IsEnum || paramType == typeof(string) || paramType == typeof(decimal); if (!isSimpleType) { parameter.BindingInfo = parameter.BindingInfo ?? new BindingInfo(); parameter.BindingInfo.BindingSource = BindingSource.Body; } } } } }