public ClientErrorResultFilter( ApiBehaviorOptions apiBehaviorOptions, ILogger <ClientErrorResultFilter> logger) { _clientErrorFactory = apiBehaviorOptions?.ClientErrorFactory ?? throw new ArgumentNullException(nameof(apiBehaviorOptions)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); }
public DefaultProblemDetailsFactory( IOptions <ApiBehaviorOptions> options, IOptions <ProblemDetailsOptions>?problemDetailsOptions = null) { _options = options?.Value ?? throw new ArgumentNullException(nameof(options)); _configure = problemDetailsOptions?.Value?.CustomizeProblemDetails; }
public void When_CreatingValidationProblemDetailsWithClientErrorMapping_Expect_ValidationProblemDetailsWithClientErrorNotMapped() { // Arrange ApiBehaviorOptions apiBehaviorOptions = new ApiBehaviorOptions(); int status = new Random().Next(int.MaxValue); apiBehaviorOptions.ClientErrorMapping[status] = new ClientErrorData { Title = Guid.NewGuid().ToString(), Link = Guid.NewGuid().ToString(), }; IOptions <ApiBehaviorOptions> options = Options.Create(apiBehaviorOptions); ProblemDetailsFactory factory = new CustomProblemDetailsFactory(options); string title = Guid.NewGuid().ToString(); string type = Guid.NewGuid().ToString(); // Act ValidationProblemDetails result = factory.CreateValidationProblemDetails(new DefaultHttpContext(), new ModelStateDictionary(), status, title, type); // Assert Assert.NotEqual(apiBehaviorOptions.ClientErrorMapping[status].Title, title); Assert.NotEqual(apiBehaviorOptions.ClientErrorMapping[status].Link, type); Assert.Equal(status, result.Status); Assert.Equal(title, result.Title); Assert.Equal(type, result.Type); }
private static ServiceCollection MockMvcServices() { var services = new ServiceCollection(); services.TryAddSingleton <IFileProvider, InMemoryFileProvider>(); services.AddSingleton(Mock.Of <IWebHostEnvironment>()); services.AddSingleton(Mock.Of <ILoggerFactory>()); services.AddTransient(typeof(IActionInvokerFactory), (s) => Mock.Of <IActionInvokerFactory>()); services.AddTransient(typeof(IActionSelector), (s) => Mock.Of <IActionSelector>()); services.AddTransient(typeof(DiagnosticSource), (s) => Mock.Of <DiagnosticSource>()); services.TryAddSingleton <IOptions <ApiBehaviorOptions> >(x => { var options = new ApiBehaviorOptions(); options.InvalidModelStateResponseFactory = (a) => null; return(new OptionsWrapper <ApiBehaviorOptions>(options)); }); var roMock = new Mock <IOptions <RouteOptions> >(); roMock.SetupGet(x => x.Value).Returns(new RouteOptions() { AppendTrailingSlash = true, ConstraintMap = new Dictionary <string, Type>() }); services.AddTransient(typeof(IOptions <RouteOptions>), (s) => roMock.Object); var optsMock = new Mock <IOptions <MvcOptions> >(); optsMock.SetupGet(x => x.Value).Returns(Mock.Of <MvcOptions>()); services.AddTransient(typeof(IOptions <MvcOptions>), (s) => optsMock.Object); services.AddMvcCore(); services.AddOneScript(); return(services); }
public ConvertViewResultToObjectResultAttributeImpl(OutputFormatterSelector formatterSelector, ILoggerFactory loggerFactory, IOptions <MvcOptions> mvcOptions, IOptions <ApiBehaviorOptions> apiBehaviorOptions, bool enabled) { _logger = loggerFactory.CreateLogger <ConvertViewResultToObjectResultAttribute>(); _mvcOptions = mvcOptions.Value; _apiBehaviorOptions = apiBehaviorOptions.Value; _enabled = enabled; }
public ApiBehaviorApplicationModelProvider( IOptions <ApiBehaviorOptions> apiBehaviorOptions, IModelMetadataProvider modelMetadataProvider, IClientErrorFactory clientErrorFactory, ILoggerFactory loggerFactory) { _apiBehaviorOptions = apiBehaviorOptions.Value; _modelMetadataProvider = modelMetadataProvider; _logger = loggerFactory.CreateLogger <ApiBehaviorApplicationModelProvider>(); if (!_apiBehaviorOptions.SuppressModelStateInvalidFilter && _apiBehaviorOptions.InvalidModelStateResponseFactory == null) { throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( typeof(ApiBehaviorOptions), nameof(ApiBehaviorOptions.InvalidModelStateResponseFactory))); } _modelStateInvalidFilter = new ModelStateInvalidFilter( apiBehaviorOptions.Value, loggerFactory.CreateLogger <ModelStateInvalidFilter>()); _clientErrorResultFilter = new ClientErrorResultFilter( clientErrorFactory, loggerFactory.CreateLogger <ClientErrorResultFilter>()); }
public void OnProvidersExecuting_SkipsAddingFilterToActionIfFeatureIsDisabledUsingOptions() { // Arrange var context = GetContext(typeof(SimpleController)); var options = new ApiBehaviorOptions { SuppressModelStateInvalidFilter = true, }; var provider = GetProvider(options); // Act provider.OnProvidersExecuting(context); // Assert Assert.Collection( Assert.Single(context.Result.Controllers).Actions.OrderBy(a => a.ActionName), action => { Assert.DoesNotContain(typeof(ModelStateInvalidFilter), action.Filters.Select(f => f.GetType())); }, action => { Assert.DoesNotContain(typeof(ModelStateInvalidFilter), action.Filters.Select(f => f.GetType())); }); }
private static ApiBehaviorOptions GetOptions() { var apiBehaviorOptions = new ApiBehaviorOptions(); apiBehaviorOptions.ClientErrorFactory[404] = _ => Result; return(apiBehaviorOptions); }
private static ClientErrorResultFilter GetFilter(ApiBehaviorOptions options = null) { var apiBehaviorOptions = options ?? GetOptions(); var filter = new ClientErrorResultFilter(apiBehaviorOptions, NullLogger <ClientErrorResultFilter> .Instance); return(filter); }
private static ProblemDetailsFactory GetProblemDetails() { var options = new ApiBehaviorOptions(); new ApiBehaviorOptionsSetup().Configure(options); return(new DefaultProblemDetailsFactory(Options.Create(options))); }
public static void UseCustomInvalidModelUnprocessableEntityResponse(this ApiBehaviorOptions options) { options.InvalidModelStateResponseFactory = (actionContext) => { ProblemDetailsFactory problemFactory = actionContext.HttpContext.RequestServices.GetRequiredService <ProblemDetailsFactory>(); ProblemDetails problemDetails = problemFactory.CreateValidationProblemDetails(actionContext.HttpContext, actionContext.ModelState); problemDetails.Instance = actionContext.HttpContext.Request.Path; problemDetails.Detail = "See errors property for additional details."; var actionExecutingContext = actionContext as ActionExecutingContext; if (actionContext.ModelState.ErrorCount != 0 && (actionContext is ControllerContext || actionContext.ActionDescriptor.Parameters.Count == actionExecutingContext.ActionArguments.Count)) { problemDetails.Title = "One or more validation errors occured."; problemDetails.Status = StatusCodes.Status422UnprocessableEntity; problemDetails.Instance = $"{actionContext.HttpContext.Request.PathBase}/modelvalidationerror"; return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); } problemDetails.Title = "One or more errors occured on the input"; problemDetails.Status = StatusCodes.Status400BadRequest; return(new BadRequestObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }
public void BlogApiBehavior_OK() { var target = new ApiBehaviorOptions(); ConfigureApiBehavior.BlogApiBehavior(target); Assert.IsNotNull(target.InvalidModelStateResponseFactory); }
public static void UseVirgoApiOptions(this ApiBehaviorOptions options) { options.SuppressModelStateInvalidFilter = true; options.InvalidModelStateResponseFactory = (a) => { return(new BadRequestObjectResult(a.ModelState.GetErrorJson())); }; }
public ProblemDetailsSetup( IHostingEnvironment environment, IHttpContextAccessor httpContextAccessor, IOptions <ApiBehaviorOptions> apiOptions) { Environment = environment; HttpContextAccessor = httpContextAccessor; ApiOptions = apiOptions.Value; }
private static void ConfigureApiBehaviorOptions(ApiBehaviorOptions options) { options.SuppressMapClientErrors = true; options.SuppressModelStateInvalidFilter = false; #if NETSTANDARD2_0 options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true; #endif options.InvalidModelStateResponseFactory = (actionContext) => HandleInvalidModelStateResponse(actionContext); }
public static void ConfigureApiBehaviour(ApiBehaviorOptions apiBehaviorOptions) { apiBehaviorOptions.InvalidModelStateResponseFactory = context => { var payload = Common.ProcessInvalidModelState(context.ModelState); return(new BadRequestObjectResult(payload)); }; }
/// <summary> /// Instantiates a new <see cref="WebHookFilterProvider"/> instance with the given /// <paramref name="behaviorOptions"/> and <paramref name="loggerFactory"/>. /// </summary> /// <param name="behaviorOptions">The <see cref="ApiBehaviorOptions"/> accessor.</param> /// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param> public WebHookFilterProvider(IOptions <ApiBehaviorOptions> behaviorOptions, ILoggerFactory loggerFactory) { _behaviorOptions = behaviorOptions.Value; _loggerFactory = loggerFactory; var logger = loggerFactory.CreateLogger <ModelStateInvalidFilter>(); _modelStateInvalidFilter = new ModelStateInvalidFilter(_behaviorOptions, logger); }
public static ApiBehaviorOptions UseFailureProblemDetailResponseFactory(this ApiBehaviorOptions options) { options.InvalidModelStateResponseFactory = context => { var detail = FailureProblemDetail.FromHttpContext(context.HttpContext) .WithFailures(context.ModelState.ToSerializable()); return(new BadRequestObjectResult(detail)); }; return(options); }
public static void ControllerConfiguration(ApiBehaviorOptions options) => options.InvalidModelStateResponseFactory = context => { //var dict = context.ModelState; //var errors = new List<string>(); //foreach (var key in dict.Keys) // errors.AddRange(dict[key].Errors.Select(x => x.ErrorMessage)); //return new BadRequestObjectResult(ApiResponse.ModelStateErrors(errors)); return(new BadRequestObjectResult(context.ModelState)); };
public void Configure_AssignsInvalidModelStateResponseFactory() { // Arrange var optionsSetup = new ApiBehaviorOptionsSetup(); var options = new ApiBehaviorOptions(); // Act optionsSetup.Configure(options); // Assert Assert.Same(ApiBehaviorOptionsSetup.DefaultFactory, options.InvalidModelStateResponseFactory); }
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)); }
//Needs to be after AddMvc or use ConfigureApiBehaviourOptions public static void ConfigureProblemDetailsInvalidModelStateFactory(this ApiBehaviorOptions options, ProblemDetailsInvalidModelStateFactoryOptions problemDetailsInvalidModelStateFactoryOptions) { //.Net Core 2.2 //400 //401 //403 //404 //406 //409 //415 //422 //.Net Core 3.0 //400 //401 //403 //404 //406 //409 //415 //422 //500 options.ClientErrorMapping[StatusCodes.Status422UnprocessableEntity] = new ClientErrorData { Link = "https://tools.ietf.org/html/rfc4918#section-11.2", Title = "One or more validation errors occurred.", //Unprocessable Entity }; options.ClientErrorMapping[499] = new ClientErrorData { Link = "about:blank", Title = "The request was cancelled.", }; options.ClientErrorMapping[StatusCodes.Status500InternalServerError] = new ClientErrorData { Link = "https://tools.ietf.org/html/rfc7231#section-6.6.1", Title = "An error occurred while processing your request.", }; options.ClientErrorMapping[StatusCodes.Status504GatewayTimeout] = new ClientErrorData { Link = "about:blank", Title = "The request timed out.", }; #if NETCOREAPP3_0 options.InvalidModelStateResponseFactory = problemDetailsInvalidModelStateFactoryOptions.InvalidModelStateResponseAbstractFactory(); #else options.InvalidModelStateResponseFactory = problemDetailsInvalidModelStateFactoryOptions.InvalidModelStateResponseAbstractFactory(problemDetailsInvalidModelStateFactoryOptions.EnableAngularErrors); #endif }
public void PostConfigure_SetProblemDetailsModelStateResponseFactory() { // Arrange var optionsSetup = new ApiBehaviorOptionsSetup(); var options = new ApiBehaviorOptions(); // Act optionsSetup.Configure(options); optionsSetup.PostConfigure(string.Empty, options); // Assert Assert.Same(ApiBehaviorOptionsSetup.ProblemDetailsFactory, options.InvalidModelStateResponseFactory); }
/// <summary> /// Adds the invalid model state exception. /// </summary> /// <param name="options">Options.</param> public static void UseInvalidModelStateException(this ApiBehaviorOptions options) { options.InvalidModelStateResponseFactory += (ActionContext arg) => { var state = arg.ModelState; var ie = state as IEnumerable <KeyValuePair <string, ModelStateEntry> >; var sb = new StringBuilder(); foreach (var item in ie) { sb.Append($"{item.Key}:{item.Value.Errors[0].ErrorMessage};"); } throw new ParameterException(sb.ToString()); }; }
public void Configure_AddsClientErrorMappings() { // Arrange var expected = new[] { 400, 401, 403, 404, 405, 406, 409, 415, 422, 500, }; var optionsSetup = new ApiBehaviorOptionsSetup(); var options = new ApiBehaviorOptions(); // Act optionsSetup.Configure(options); // Assert Assert.Equal(expected, options.ClientErrorMapping.Keys); }
public static void UseInvalidModelStateToError(this ApiBehaviorOptions options) { options.InvalidModelStateResponseFactory = context => { var errorsWithMessage = context.ModelState .Where(x => x.Value.ValidationState == ModelValidationState.Invalid).ToDictionary( x => string.Join('.', x.Key.Split('.').Select(StringExtensions.ToCamelCase)), x => x.Value.Errors.First().ErrorMessage); var fieldValidationError = new FieldValidationError(errorsWithMessage); return(new BadRequestObjectResult(fieldValidationError)); }; }
private static ProblemDetailsFactory GetProblemDetailsFactory(Action <ApiBehaviorOptions> configure = null) { var options = new ApiBehaviorOptions(); var setup = new ApiBehaviorOptionsSetup(); setup.Configure(options); if (configure != null) { configure(options); } return(new DefaultProblemDetailsFactory(Options.Options.Create(options))); }
public static void CustomInvalidModelStateResponse(this ApiBehaviorOptions apiBehaviorOptions) { apiBehaviorOptions.InvalidModelStateResponseFactory = actionContext => { OperationResult result = new OperationResult(false, new List <string>()); foreach (var modelState in actionContext.ModelState) { result.Messages.AddRange(modelState.Value.Errors.Select(error => error.ErrorMessage).ToList()); } return(new BadRequestObjectResult(result)); }; }
public ApiBehaviorApplicationModelProvider(IOptions <ApiBehaviorOptions> apiBehaviorOptions, ILoggerFactory loggerFactory) { _apiBehaviorOptions = apiBehaviorOptions.Value; if (_apiBehaviorOptions.EnableModelStateInvalidFilter && _apiBehaviorOptions.InvalidModelStateResponseFactory == null) { throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( typeof(ApiBehaviorOptions), nameof(ApiBehaviorOptions.InvalidModelStateResponseFactory))); } _modelStateInvalidFilter = new ModelStateInvalidFilter( apiBehaviorOptions.Value, loggerFactory.CreateLogger <ModelStateInvalidFilter>()); }
public void Configure_AssignsInvalidModelStateResponseFactory() { // Arrange var optionsSetup = new ApiBehaviorOptionsSetup( NullLoggerFactory.Instance, Options.Options.Create(new MvcCompatibilityOptions())); var options = new ApiBehaviorOptions(); // Act optionsSetup.Configure(options); // Assert Assert.Same(ApiBehaviorOptionsSetup.DefaultFactory, options.InvalidModelStateResponseFactory); }