在ASP.NET MVC中,在控制器的操作方法之前或之中反序列化JSON

wei*_*in8 20 c# asp.net-mvc jquery json

我正在开发一个将JSON对象(使用jQuery Post方法)发布到服务器端的网站.

{ 
    "ID" : 1,
    "FullName" : {
       "FirstName" : "John",
       "LastName" : "Smith"
    }
}
Run Code Online (Sandbox Code Playgroud)

同时,我在服务器端为这个数据结构编写了类.

public class User
{
    public int ID { get; set; }
    public Name FullName { get; set;}
}

public class Name
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当我在我的控制器类中使用以下代码运行网站时,FullName属性不会反序列化.我究竟做错了什么?

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Submit(User user)
{
    // At this point, user.FullName is NULL. 

    return View();
}
Run Code Online (Sandbox Code Playgroud)

wei*_*in8 23

我通过实现动作过滤器解决了我的问题; 代码示例如下.从研究中我了解到,还有另一种解决方案,模型粘合剂,如上所述的takepara.但我真的不知道这两种方法的优点和缺点.

感谢Steve Gentile 关于此解决方案的博客文章.

public class JsonFilter : ActionFilterAttribute
    {
        public string Parameter { get; set; }
        public Type JsonDataType { get; set; }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Request.ContentType.Contains("application/json"))
            {
                string inputContent;
                using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream))
                {
                    inputContent = sr.ReadToEnd();
                }

                var result = JsonConvert.DeserializeObject(inputContent, JsonDataType);
                filterContext.ActionParameters[Parameter] = result;
            }
        }
    }

[AcceptVerbs(HttpVerbs.Post)]
[JsonFilter(Parameter="user", JsonDataType=typeof(User))]
public ActionResult Submit(User user)
{
    // user object is deserialized properly prior to execution of Submit() function

    return View();
}
Run Code Online (Sandbox Code Playgroud)

  • 与定制的ModelBinder相比,此方法具有明显的优势,因为您可以定义要反序列化的类型.使用自定义ModelBinder,它是硬编码的,因此仅适用于一种类型. (3认同)
  • awww snap,weilin拥有133t MVC技能,你最好在星期一教我; ) (2认同)

小智 11

1.创建自定义模型绑定器

  public class UserModelBinder : IModelBinder
  {
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
      User model;

      if(controllerContext.RequestContext.HttpContext.Request.AcceptTypes.Contains("application/json"))
      {
        var serializer = new JavaScriptSerializer();
        var form = controllerContext.RequestContext.HttpContext.Request.Form.ToString();
        model = serializer.Deserialize<User>(HttpUtility.UrlDecode(form));
      }
      else
      {
        model = (User)ModelBinders.Binders.DefaultBinder.BindModel(controllerContext, bindingContext);
      }

      return model;
    }
  }
Run Code Online (Sandbox Code Playgroud)

2.在application_start事件中添加模型绑定器

  ModelBinders.Binders[typeof(User)] = new UserModelBinder();
Run Code Online (Sandbox Code Playgroud)

3.使用jQuery $ .get/$.发布视图客户端JavaScript代码.

  <% using(Html.BeginForm("JsonData","Home",new{},FormMethod.Post, new{id="jsonform"})) { %>

    <% = Html.TextArea("jsonarea","",new {id="jsonarea"}) %><br />

    <input type="button" id="getjson" value="Get Json" />
    <input type="button" id="postjson" value="Post Json" />
  <% } %>
  <script type="text/javascript">
    $(function() {
      $('#getjson').click(function() {
        $.get($('#jsonform').attr('action'), function(data) {
          $('#jsonarea').val(data);
        });
      });

      $('#postjson').click(function() {
        $.post($('#jsonform').attr('action'), $('#jsonarea').val(), function(data) {
          alert("posted!");
        },"json");
      });
    });
  </script>
Run Code Online (Sandbox Code Playgroud)


Rya*_*lor 5

你可以尝试Json.NET.该文档是相当不错的,它应该能够做你的需要.您还需要抓取JsonNetResult,因为它返回可以在ASP.NET MVC应用程序中使用的ActionResult.它很容易使用.

Json.NET也适用于日期序列化.有关这方面的更多信息可以在这里找到.

希望这可以帮助.


Cmd*_*len 5

尝试这个;

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Submit(FormCollection collection)
{
    User submittedUser = JsonConvert.DeserializeObject<User>(collection["user"]); 
    return View();
}
Run Code Online (Sandbox Code Playgroud)