【问题标题】:Json deserialization Mvc 4 Knockout jsJson反序列化Mvc 4 Knockout js
【发布时间】:2012-12-28 23:15:09
【问题描述】:

当我尝试将 json 反序列化为 MVC4 中的对象时遇到问题。

我有一个视图模型:

 public class TestViewModel
{
    public string Code { get; set; }

}

在视图中,我使用 Json.net 获取模型并序列化对象

var Vm = function(data) {
        var self = this;

        ko.mapping.fromJS(data, {}, self);

        self.GetResults = function() {
            $.ajax({
                type: "POST",
                url: '@Url.Action("Action", "Controller")',
                data: ko.mapping.toJSON(self),
                success: function(data) {
                    alert('OK');
                }
            });
        };
    };

    var viewModel = new Vm(@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model)));
    ko.applyBindings(viewModel);

我的问题是当我在控制器中调用 GetResults 动作时,所有属性都是空的。

我的 Json 是:

{"Code":"TestCode"}

我在 MVC3 项目中具有相同的结构并且工作正常。我在 MVC4 中遗漏了什么?

干杯!

【问题讨论】:

  • 您是否尝试过使用 Fiddler 查看请求和响应的样子?
  • 是的,请求看起来不错,它有 Content-Type: application/json Accept: application/json, text/javascript, /; q=0.01,问题中的json {"Code":"TestCode"}

标签: json asp.net-mvc-4 knockout.js knockout-mapping-plugin


【解决方案1】:

我们注意到,在某些情况下,jQuery 会将数据嵌入到请求中的表单中。发生这种情况时,值不会自动映射到 Controller 方法中的对象类型。

要解决这个问题,您需要做两件事:

1) 检查数据是否被序列化。我找到了一种简单的方法,并将其转储到扩展方法中:

public static class WebContextExtensions
{
    public static bool IsDataSerialized(this HttpContext context)
    {
        return context.Request.Params.AllKeys[0] == null;
    }
}

2) 如果 IsDataSerialized 返回 true,则需要将数据反序列化为对象类型。我们也编写了一个 GenericDeserializer 方法来做到这一点:

public class GenericContextDeserializer<T> where T : new()
{
    public T DeserializeToType(HttpContext context)
    {
        T result = new T();
        if (context != null)
        {
            try
            {
                string jsonString = context.Request.Form.GetValues(0)[0].ToString();
                Newtonsoft.Json.JsonSerializer js = new Newtonsoft.Json.JsonSerializer();
                result = js.Deserialize<T>(new Newtonsoft.Json.JsonTextReader(
                               new System.IO.StringReader(jsonString)));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        else
            throw new NullReferenceException();
        return result;
    }
}

现在将它们放在你的 Controller 方法中:

[HttpPost]
[HttpOptions]
public HttpResponseMessage MyAction(JsonData data)
{
    var results = Request.CreateResponse();
    try
    {
        data = new GenericContextDeserializer<JsonData>().DeserializeToType(HttpContext.Current);
        // do stuff with data
        results.StatusCode = HttpStatusCode.OK;
    }
    catch (Exception ex)
    {
        results.StatusCode = HttpStatusCode.InternalServerError;
    }
    return results;
}

如果你想要更多细节,在我写的a blog post的后半部分。

【讨论】:

    猜你喜欢
    • 2012-02-04
    • 2015-10-02
    • 2023-04-10
    • 2019-08-06
    • 1970-01-01
    • 2012-02-15
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    相关资源
    最近更新 更多