/src/System.Web.Http/ModelBinding/FormatterParameterBinding.cs

http://aspnetwebstack.codeplex.com · C# · 107 lines · 89 code · 11 blank · 7 comment · 9 complexity · e6d406f12290c540004b37e39be29ded MD5 · raw file

  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. using System.Collections.Generic;
  3. using System.Net.Http;
  4. using System.Net.Http.Formatting;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using System.Web.Http.Controllers;
  8. using System.Web.Http.Metadata;
  9. using System.Web.Http.Properties;
  10. using System.Web.Http.Validation;
  11. namespace System.Web.Http.ModelBinding
  12. {
  13. /// <summary>
  14. /// Parameter binding that will read from the body and invoke the formatters.
  15. /// </summary>
  16. public class FormatterParameterBinding : HttpParameterBinding
  17. {
  18. private IEnumerable<MediaTypeFormatter> _formatters;
  19. private string _errorMessage;
  20. public FormatterParameterBinding(HttpParameterDescriptor descriptor, IEnumerable<MediaTypeFormatter> formatters, IBodyModelValidator bodyModelValidator)
  21. : base(descriptor)
  22. {
  23. if (descriptor.IsOptional)
  24. {
  25. _errorMessage = Error.Format(SRResources.OptionalBodyParameterNotSupported, descriptor.Prefix ?? descriptor.ParameterName, GetType().Name);
  26. }
  27. Formatters = formatters;
  28. BodyModelValidator = bodyModelValidator;
  29. }
  30. public override bool WillReadBody
  31. {
  32. get { return true; }
  33. }
  34. public override string ErrorMessage
  35. {
  36. get
  37. {
  38. return _errorMessage;
  39. }
  40. }
  41. public IEnumerable<MediaTypeFormatter> Formatters
  42. {
  43. get { return _formatters; }
  44. set
  45. {
  46. if (value == null)
  47. {
  48. throw Error.ArgumentNull("formatters");
  49. }
  50. _formatters = value;
  51. }
  52. }
  53. public IBodyModelValidator BodyModelValidator
  54. {
  55. get;
  56. set;
  57. }
  58. public virtual Task<object> ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable<MediaTypeFormatter> formatters, IFormatterLogger formatterLogger)
  59. {
  60. HttpContent content = request.Content;
  61. if (content == null)
  62. {
  63. object defaultValue = MediaTypeFormatter.GetDefaultValueForType(type);
  64. if (defaultValue == null)
  65. {
  66. return TaskHelpers.NullResult();
  67. }
  68. else
  69. {
  70. return TaskHelpers.FromResult(defaultValue);
  71. }
  72. }
  73. return content.ReadAsAsync(type, formatters, formatterLogger);
  74. }
  75. public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
  76. {
  77. HttpParameterDescriptor paramFromBody = this.Descriptor;
  78. Type type = paramFromBody.ParameterType;
  79. HttpRequestMessage request = actionContext.ControllerContext.Request;
  80. IFormatterLogger formatterLogger = new ModelStateFormatterLogger(actionContext.ModelState, paramFromBody.ParameterName);
  81. Task<object> task = ReadContentAsync(request, type, _formatters, formatterLogger);
  82. return task.Then(
  83. (model) =>
  84. {
  85. // Put the parameter result into the action context.
  86. SetValue(actionContext, model);
  87. // validate the object graph.
  88. // null indicates we want no body parameter validation
  89. if (BodyModelValidator != null)
  90. {
  91. BodyModelValidator.Validate(model, type, metadataProvider, actionContext, paramFromBody.ParameterName);
  92. }
  93. });
  94. }
  95. }
  96. }