【问题标题】:Web API translate JSON object into simple parametersWeb API 将 JSON 对象转换为简单的参数
【发布时间】:2020-06-21 03:00:24
【问题描述】:

如果我将 JSON 数据(通过 POST)发送到这样的 .Net Core Web API

{ a: "a", b: "b" }

我需要做什么才能拥有这样的控制器方法?

[HttpPost]
public async Task SometMethod(string a, string b) 
{
  return Ok();
}

通常,所有教程和文档都说您需要定义一个类并使用[FromBody] 属性。但是,如果没有我并不真正需要的额外课程,我该怎么办呢?

【问题讨论】:

  • 我知道你不能默认这样做,问题是如何做到这一点,而不创建一个新的类。
  • [FromRoute][FromBody](等)属性仅添加限制。例如,在您的情况下,添加 [FromBody] 属性会阻止用户从查询字符串发送 a 参数。除此之外,我不明白为什么您的代码示例不起作用...

标签: .net-core asp.net-core-webapi


【解决方案1】:

如果您想像这样将数据发布到方法中,则必须先序列化您的数据,然后才能将其发送到服务器。假设您使用的是 JQuery,您可以执行以下操作。

var postData = $.param({ a: "a", b: "b" });
//Then you can send this postData obejct to the server. This should perfectly bound to the parameters. 

您也可以在 Angular 应用程序中使用它。

【讨论】:

    【解决方案2】:

    首先,你的 json 应该是:

    { 
        "a":"a", 
        "b":"b" 
    }
    

    您可以以JObject 的形式接收数据,而不是像下面这样的类:

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        [HttpPost]
        public void Post(JObject data)
        {
            //get the property value like below
            var data1 = data["a"].ToString();
            var data2 = data["b"].ToString();
        }
    }
    

    结果(为了方便区分值和属性名称,我将a更改为aaa,将b更改为bbb):

    【讨论】:

      【解决方案3】:

      经过一些研究,我想出了 ModelBinder 来做到这一点。它不是高性能的,因为它为每个参数重新解析整个请求正文。我以后会改进的。

      https://github.com/egorpavlikhin/JsonParametersModelBinder

      public class JsonBinder : IModelBinder
      {
          public async Task BindModelAsync(ModelBindingContext bindingContext)
          {
              if (bindingContext == null) throw new ArgumentNullException(nameof(bindingContext));
      
              var actionDescriptor = bindingContext.ActionContext.ActionDescriptor as ControllerActionDescriptor;
              if (actionDescriptor.MethodInfo.GetCustomAttributes(typeof(JsonParametersAttribute), false).Length > 0)
              {
                  var context = bindingContext.HttpContext;
                  if (context.Request.ContentType != "application/json")
                  {
                      bindingContext.Result = ModelBindingResult.Failed();
                      return;
                  }
      
      #if (NETSTANDARD2_1 || NETCOREAPP3_0)
                  context?.Request.EnableBuffering();
      #else
              context?.Request.EnableRewind();
      #endif
      
                  using var reader = new StreamReader(context.Request.Body, Encoding.UTF8,
                      false,
                      1024,
                      true); // so body can be re-read next time
      
                  var body = await reader.ReadToEndAsync();
                  var json = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(body);
                  if (json.TryGetValue(bindingContext.FieldName, out var value))
                  {
                      if (bindingContext.ModelType == typeof(string))
                      {
                          bindingContext.Result = ModelBindingResult.Success(value.GetString());
                      }
                      else if (bindingContext.ModelType == typeof(object))
                      {
                          var serializerOptions = new JsonSerializerOptions
                          {
                              Converters = {new DynamicJsonConverter()}
                          };
                          var val = JsonSerializer.Deserialize<dynamic>(value.ToString(), serializerOptions);
                          bindingContext.Result = ModelBindingResult.Success(val);
                      }
                  }
      
                  context.Request.Body.Position = 0; // rewind
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-13
        • 1970-01-01
        • 1970-01-01
        • 2021-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-14
        • 1970-01-01
        相关资源
        最近更新 更多