【问题标题】:How to deserialize parameter from json in webapi controller如何从 webapi 控制器中的 json 反序列化参数
【发布时间】:2016-08-31 07:12:27
【问题描述】:

似乎我遇到了最基本的问题,但我找不到解决它所需的文档。

我有一个 mvc webapi 控制器:

public class TestController : ApiController
{
    [HttpGet]
    public MyClass Other([FromUri]MyClass id)
    {
        id.Value++;
        return id;
    }        
}

public class MyClass
{
    public int Value {get;set;}
}

我正在从 HttpClient 执行:

using (var client = new System.Net.Http.HttpClient())
{
    client.BaseAddress = new System.Uri("http://localhost:31573/api/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    var obj = new MyClass { Value = 3 };
    var data = JsonConvert.SerializeObject(obj);
    StringContent queryString = new StringContent(data, Encoding.UTF8, "application/json");
    var paramsValue = queryString.ReadAsStringAsync().Result;
    var response = client.GetAsync("Test/?id="+ paramsValue).Result;                    
    var textResponse = response.Content.ReadAsStringAsync().Result;
    var result = JsonConvert.DeserializeObject<MyClass>(textResponse);                    
 }

问题是控制器接收到的参数id是MyClass的默认实例(即Value = 0)。如果我将方法的原型更改为接受字符串:

[HttpGet]
public MyClass Other([FromUri]string id)
{
    var val = JsonConvert.DeserializeObject<MyClass>(id);
    val.Value++;
    return val; 
}    

一切正常,但我宁愿不必在每个控制器方法中手动进行反序列化。

我已经尝试了很多如何创建查询字符串的组合,到目前为止都没有运气。

似乎数据正确地到达了webApi,但没有发生反序列化,所以我怀疑我没有正确配置webApi以使用json形式的请求参数。

我的 webapiconfig 看起来像:

public static void Register(HttpConfiguration config)
        {
            if (config == null)
                throw new ArgumentNullException(nameof(config));

            // Web API configuration and services
            config.Formatters.Clear();
            config.Formatters.Add(new JsonMediaTypeFormatter());

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional });
        }

所以它返回的json正确,但是传入的参数没有正确反序列化。

谁能帮忙??

【问题讨论】:

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


    【解决方案1】:

    感谢@Mostafizur Ra​​hman 的帮助,我得出的结论是get 方法在这里不合适,因此我已更改为Post 方法并在body 中传递数据:

    public class TestController : ApiController
    {
        public MyClass PostMethod([FromBody]MyClass id)
        {            
            id.Value++;
            return id;
        }
    }
    
    public class MyClass
    {
        public int Value {get;set;}
    }
    

    随着客户端变成:

    using (var client = new System.Net.Http.HttpClient())
    {
        client.BaseAddress = new System.Uri("http://localhost:31573/api/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        var obj = new MyClass { Value = 3 };
        var data = JsonConvert.SerializeObject(obj);
        StringContent queryString = new StringContent(data, Encoding.UTF8, "application/json");
        var paramsValue = queryString.ReadAsStringAsync().Result;
        var response = client.PostAsync("Test/PostMethod",  queryString).Result;
        var textResponse = response.Content.ReadAsStringAsync().Result;
        var result = JsonConvert.DeserializeObject<MyClass>(textResponse);
    }
    

    【讨论】:

    • 正确。当您向 API 发送数据时 - FromBody 将无法通过 GET 请求工作。您需要使用 POST 或在您的操作中将 MyClass 参数化到与 MyClass 属性对应的参数列表中
    【解决方案2】:

    这是您需要形成的查询字符串 -

    http://localhost:61817/api/Test?Value=3
    

    然后代码更改为 -

    var response = client.GetAsync("Test?Value="+ obj.Value).Result;
    

    【讨论】:

    • 这对于MyClass 的简单情况来说很容易,但是对于具有数十个属性的对象,我将如何生成查询字符串?
    • 您需要将它们作为键值附加到查询字符串中,或​​者最好发出HTTP POST,在这种情况下,请求正文包含所有这些属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多