【问题标题】:Web Api FromBody is null from web clientWeb Api FromBody 从 Web 客户端为空
【发布时间】:2014-04-17 14:06:01
【问题描述】:

您好,我想通过我的 web api 控制器中的 body 变量从 C# 客户端调用 Web Api 方法一直为空。 如何正确设置? 客户端:

IFileService imgService = new ImageServiceBll();
var image = System.Drawing.Image.FromFile(serverFile);
var dataImage = imgService.ImageToBase64(image, System.Drawing.Imaging.ImageFormat.Png);

using (var client = new HttpClient())
{
    client.BaseAddress = new Uri("http://site.local/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    // HTTP POST
    var data = new
    {
        imageData = dataImage,
        version = version
    };

    HttpResponseMessage response = await client.PostAsJsonAsync("api/contenttool/SaveImage", data);
    if (response.IsSuccessStatusCode)
    {
        Uri gizmoUrl = response.Headers.Location;
    }
}

服务器端:

public class ContentToolController : ApiController
{
    public IFileService FileService { get; set; }
    // POST api/contenttool
    public string SaveImage([FromBody]string data)
    {
        JObject jObject = JObject.Parse(data);
        JObject version = (JObject)jObject["version"];

        return "-OK-" + version;
    }
}

【问题讨论】:

    标签: c# asp.net-mvc-4 asp.net-web-api asp.net-mvc-5


    【解决方案1】:

    我认为这与您在技术上没有传递字符串这一事实有关。您正在传递匿名类型的 JSON 序列化字符串表示形式,因此 Web Api 中的反序列化过程对您不利。当您的请求到达控制器和该方法时,它不再是字符串了。尝试将 SavImage 方法的类型更改为动态的。像这样:

    public string SavImage([FromBody]dynamic data)
    {
          JObject jObject = JObject.Parse(data);
          JObject version = (JObject)jObject["version"];
    
          return "-OK-" + version;
    }
    

    不幸的是,此时您将无法使用智能感知来获取您的属性。您必须通过字典从动态类型中获取数据。

    Dictionary<string, object> obj = JsonConvert.DeserializeObject<Dictionary<string, object>>(Convert.ToString(data));
    

    当然,您的另一个选择是使用在客户端和服务器之间共享的实际类型。这样会更容易一些。

    【讨论】:

    • 好点,但我发现如果将参数像字符串一样发送到 PostAsJsonAsync 它会正常工作。
    • 您确实在与系统作对。要么将数据作为字符串发送并作为字符串绑定,要么作为 JSON 发送并绑定到 WebAPI 端的相同数据对象。第二种方法是正确的方法。因此,您可以避免在您的操作方法中编写特定的 json 操作代码,框架可以为您完成。
    • @YishaiGalatzer 我在很大程度上同意这一点,但如果我想序列化一个对象列表,它会迫使我创建一个新模型来保存一个列表!这看起来很疯狂不是吗?
    • 您在哪里看到我的回答中暗示的内容?您应该能够绑定到 webapi 中的列表,而无需创建包含列表的类型
    【解决方案2】:

    正文中传递的字符串值可能需要以=符号为前缀。

    【讨论】:

    • 如果要在正文中传递一个字符串Hello World,请将其传递为=Hello World
    • 您似乎正试图将 JSON 对象传递给该方法。更好的方法是将强类型对象作为 SavImage 方法的参数,而没有 [FromBody] 属性(它实际上是为传递简单值而设计的)。 Web API 应该负责序列化。
    猜你喜欢
    • 1970-01-01
    • 2015-08-07
    • 2012-07-28
    • 2015-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多