/// <inheritdoc /> public async Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } // Special logic for body, treat the model name as string.Empty for the top level // object, but allow an override via BinderModelName. The purpose of this is to try // and be similar to the behavior for POCOs bound via traditional model binding. string modelBindingKey; if (bindingContext.IsTopLevelObject) { modelBindingKey = bindingContext.BinderModelName ?? string.Empty; } else { modelBindingKey = bindingContext.ModelName; } var httpContext = bindingContext.HttpContext; var formatterContext = new InputFormatterContext( httpContext, modelBindingKey, bindingContext.ModelState, bindingContext.ModelMetadata, _readerFactory); var formatter = (IInputFormatter)null; for (var i = 0; i < _formatters.Count; i++) { if (_formatters[i].CanRead(formatterContext)) { formatter = _formatters[i]; break; } } if (formatter == null) { var message = Resources.FormatUnsupportedContentType(httpContext.Request.ContentType); var exception = new UnsupportedContentTypeException(message); bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata); return; } try { var previousCount = bindingContext.ModelState.ErrorCount; var result = await formatter.ReadAsync(formatterContext); var model = result.Model; if (result.HasError) { // Formatter encountered an error. Do not use the model it returned. return; } bindingContext.Result = ModelBindingResult.Success(model); return; } catch (Exception ex) { bindingContext.ModelState.AddModelError(modelBindingKey, ex, bindingContext.ModelMetadata); return; } }
/// <inheritdoc /> public async Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } // Special logic for body, treat the model name as string.Empty for the top level // object, but allow an override via BinderModelName. The purpose of this is to try // and be similar to the behavior for POCOs bound via traditional model binding. string modelBindingKey; if (bindingContext.IsTopLevelObject) { modelBindingKey = bindingContext.BinderModelName ?? string.Empty; } else { modelBindingKey = bindingContext.ModelName; } var httpContext = bindingContext.OperationBindingContext.HttpContext; var formatterContext = new InputFormatterContext( httpContext, modelBindingKey, bindingContext.ModelState, bindingContext.ModelMetadata, _readerFactory); var formatters = bindingContext.OperationBindingContext.InputFormatters; var formatter = formatters.FirstOrDefault(f => f.CanRead(formatterContext)); if (formatter == null) { var message = Resources.FormatUnsupportedContentType( bindingContext.OperationBindingContext.HttpContext.Request.ContentType); var exception = new UnsupportedContentTypeException(message); bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata); // This model binder is the only handler for the Body binding source and it cannot run twice. Always // tell the model binding system to skip other model binders and never to fall back i.e. indicate a // fatal error. bindingContext.Result = ModelBindingResult.Failed(modelBindingKey); return; } try { var previousCount = bindingContext.ModelState.ErrorCount; var result = await formatter.ReadAsync(formatterContext); var model = result.Model; if (result.HasError) { // Formatter encountered an error. Do not use the model it returned. As above, tell the model // binding system to skip other model binders and never to fall back. bindingContext.Result = ModelBindingResult.Failed(modelBindingKey); return; } bindingContext.Result = ModelBindingResult.Success(modelBindingKey, model); return; } catch (Exception ex) { bindingContext.ModelState.AddModelError(modelBindingKey, ex, bindingContext.ModelMetadata); // This model binder is the only handler for the Body binding source and it cannot run twice. Always // tell the model binding system to skip other model binders and never to fall back i.e. indicate a // fatal error. bindingContext.Result = ModelBindingResult.Failed(modelBindingKey); return; } }
/// <inheritdoc /> public async Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } // Special logic for body, treat the model name as string.Empty for the top level // object, but allow an override via BinderModelName. The purpose of this is to try // and be similar to the behavior for POCOs bound via traditional model binding. string modelBindingKey; if (bindingContext.IsTopLevelObject) { modelBindingKey = bindingContext.BinderModelName ?? string.Empty; } else { modelBindingKey = bindingContext.ModelName; } var httpContext = bindingContext.OperationBindingContext.HttpContext; var formatterContext = new InputFormatterContext( httpContext, modelBindingKey, bindingContext.ModelState, bindingContext.ModelMetadata, _readerFactory); var formatters = bindingContext.OperationBindingContext.InputFormatters; var formatter = formatters.FirstOrDefault(f => f.CanRead(formatterContext)); if (formatter == null) { var message = Resources.FormatUnsupportedContentType( bindingContext.OperationBindingContext.HttpContext.Request.ContentType); var exception = new UnsupportedContentTypeException(message); bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata); // This model binder is the only handler for the Body binding source and it cannot run twice. Always // tell the model binding system to skip other model binders and never to fall back i.e. indicate a // fatal error. bindingContext.Result = ModelBindingResult.Failed(modelBindingKey); return; } try { var previousCount = bindingContext.ModelState.ErrorCount; var result = await formatter.ReadAsync(formatterContext); var model = result.Model; if (result.HasError) { // Formatter encountered an error. Do not use the model it returned. As above, tell the model // binding system to skip other model binders and never to fall back. bindingContext.Result = ModelBindingResult.Failed(modelBindingKey); return; } bindingContext.Result = ModelBindingResult.Success(modelBindingKey, model); return; } catch (Exception ex) { bindingContext.ModelState.AddModelError(modelBindingKey, ex, bindingContext.ModelMetadata); // This model binder is the only handler for the Body binding source and it cannot run twice. Always // tell the model binding system to skip other model binders and never to fall back i.e. indicate a // fatal error. bindingContext.Result = ModelBindingResult.Failed(modelBindingKey); return; } }
/// <inheritdoc /> public async Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } // Special logic for body, treat the model name as string.Empty for the top level // object, but allow an override via BinderModelName. The purpose of this is to try // and be similar to the behavior for POCOs bound via traditional model binding. string modelBindingKey; if (bindingContext.IsTopLevelObject) { modelBindingKey = bindingContext.BinderModelName ?? string.Empty; } else { modelBindingKey = bindingContext.ModelName; } var httpContext = bindingContext.HttpContext; var allowEmptyInputInModelBinding = _options?.AllowEmptyInputInBodyModelBinding == true; var formatterContext = new InputFormatterContext( httpContext, modelBindingKey, bindingContext.ModelState, bindingContext.ModelMetadata, _readerFactory, allowEmptyInputInModelBinding); var formatter = (IInputFormatter)null; for (var i = 0; i < _formatters.Count; i++) { if (_formatters[i].CanRead(formatterContext)) { formatter = _formatters[i]; _logger?.InputFormatterSelected(formatter, formatterContext); break; } else { _logger?.InputFormatterRejected(_formatters[i], formatterContext); } } if (formatter == null) { _logger?.NoInputFormatterSelected(formatterContext); var message = Resources.FormatUnsupportedContentType(httpContext.Request.ContentType); var exception = new UnsupportedContentTypeException(message); bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata); return; } try { var result = await formatter.ReadAsync(formatterContext); var model = result.Model; if (result.HasError) { // Formatter encountered an error. Do not use the model it returned. return; } if (result.IsModelSet) { bindingContext.Result = ModelBindingResult.Success(model); } else { // If the input formatter gives a "no value" result, that's always a model state error, // because BodyModelBinder implicitly regards input as being required for model binding. // If instead the input formatter wants to treat the input as optional, it must do so by // returning InputFormatterResult.Success(defaultForModelType), because input formatters // are responsible for choosing a default value for the model type. var message = bindingContext .ModelMetadata .ModelBindingMessageProvider .MissingRequestBodyRequiredValueAccessor(); bindingContext.ModelState.AddModelError(modelBindingKey, message); } } catch (Exception exception) when(exception is InputFormatterException || ShouldHandleException(formatter)) { bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata); } }