BodyOrDefaultModelBinder.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. using Microsoft.AspNetCore.Http;
  2. using Microsoft.AspNetCore.Mvc.ModelBinding;
  3. using Newtonsoft.Json;
  4. using Newtonsoft.Json.Linq;
  5. using System;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace Masuit.Tools.AspNetCore.ModelBinder;
  9. public class BodyOrDefaultModelBinder : IModelBinder
  10. {
  11. private readonly IModelBinder _bodyBinder;
  12. private readonly IModelBinder _complexBinder;
  13. public BodyOrDefaultModelBinder(IModelBinder bodyBinder, IModelBinder complexBinder)
  14. {
  15. _bodyBinder = bodyBinder;
  16. _complexBinder = complexBinder;
  17. }
  18. public async Task BindModelAsync(ModelBindingContext bindingContext)
  19. {
  20. var request = bindingContext.HttpContext.Request;
  21. request.EnableBuffering();
  22. var buffer = new byte[Convert.ToInt32(request.ContentLength)];
  23. _ = await request.Body.ReadAsync(buffer, 0, buffer.Length);
  24. var text = Encoding.UTF8.GetString(buffer);
  25. request.Body.Position = 0;
  26. if (bindingContext.ModelType.IsPrimitive || bindingContext.ModelType == typeof(string) || bindingContext.ModelType.IsEnum || bindingContext.ModelType == typeof(DateTime) || bindingContext.ModelType == typeof(Guid) || (bindingContext.ModelType.IsGenericType && bindingContext.ModelType.GetGenericTypeDefinition() == typeof(Nullable<>)))
  27. {
  28. var parameter = bindingContext.ModelMetadata.ParameterName;
  29. var value = "";
  30. if (request.Query.ContainsKey(parameter))
  31. {
  32. value = request.Query[parameter] + "";
  33. }
  34. else if (request.ContentType is not null && request.ContentType.StartsWith("application/json"))
  35. {
  36. try
  37. {
  38. value = JObject.Parse(text)[parameter] + "";
  39. }
  40. catch
  41. {
  42. value = text.Trim('"');
  43. }
  44. }
  45. else if (request.HasFormContentType)
  46. {
  47. value = request.Form[bindingContext.ModelMetadata.ParameterName] + "";
  48. }
  49. if (value.TryConvertTo(bindingContext.ModelType, out var result))
  50. {
  51. bindingContext.Result = ModelBindingResult.Success(result);
  52. }
  53. return;
  54. }
  55. if (request.HasFormContentType)
  56. {
  57. if (bindingContext.ModelType.IsClass)
  58. {
  59. await DefaultBindModel(bindingContext);
  60. }
  61. else
  62. {
  63. bindingContext.Result = ModelBindingResult.Success(request.Form[bindingContext.ModelMetadata.ParameterName].ToString().ConvertTo(bindingContext.ModelType));
  64. }
  65. return;
  66. }
  67. try
  68. {
  69. bindingContext.Result = ModelBindingResult.Success(JsonConvert.DeserializeObject(text, bindingContext.ModelType) ?? request.Query[bindingContext.ModelMetadata.ParameterName!].ToString().ConvertTo(bindingContext.ModelType));
  70. }
  71. catch
  72. {
  73. await DefaultBindModel(bindingContext);
  74. }
  75. }
  76. private async Task DefaultBindModel(ModelBindingContext bindingContext)
  77. {
  78. await _bodyBinder.BindModelAsync(bindingContext);
  79. if (bindingContext.Result.IsModelSet)
  80. {
  81. return;
  82. }
  83. bindingContext.ModelState.Clear();
  84. await _complexBinder.BindModelAsync(bindingContext);
  85. }
  86. }