【问题标题】:ASP.NET MVC3 JSON Model-binding with nested classASP.NET MVC3 JSON 模型绑定与嵌套类
【发布时间】:2011-09-27 17:17:43
【问题描述】:

在 MVC3 中,如果模型具有嵌套对象,是否可以自动将 javascript 对象绑定到模型?我的模型如下所示:

 public class Tweet
 {
    public Tweet()
    {
         Coordinates = new Geo();
    }
    public string Id { get; set; }
    public string User { get; set; }
    public DateTime Created { get; set; }
    public string Text { get; set; }
    public Geo Coordinates { get; set; } 

}

public class Geo {

    public Geo(){}

    public Geo(double? lat, double? lng)
    {
        this.Latitude = lat;
        this.Longitude = lng;
    }

    public double? Latitude { get; set; }
    public double? Longitude { get; set; }

    public bool HasValue
    {
        get
        {
            return (Latitude != null || Longitude != null);
        }
    }
}

当我将以下 JSON 发布到我的控制器时,除“坐标”之外的所有内容均成功绑定:

{"Text":"test","Id":"testid","User":"testuser","Created":"","Coordinates":{"Latitude":57.69679752892457,"Longitude":11.982091465576104}}

这是我的控制器动作的样子:

    [HttpPost]
    public JsonResult ReTweet(Tweet tweet)
    {
        //do some stuff
    }

我在这里遗漏了什么还是新的自动绑定功能只支持原始对象?

【问题讨论】:

    标签: asp.net json asp.net-mvc-3 model-binding


    【解决方案1】:

    是的,您可以使用 ASP.NET MVC3 绑定复杂的 json 对象。

    Phil Haack 写了关于它recently.
    您的 Geo 课程有问题。
    不要使用可为空的属性:

    public class Geo
    {
    
        public Geo() { }
    
        public Geo(double lat, double lng)
        {
            this.Latitude = lat;
            this.Longitude = lng;
        }
    
        public double Latitude { get; set; }
        public double Longitude { get; set; }
    
        public bool HasValue
        {
            get
            {
                return (Latitude != null || Longitude != null);
            }
        }
    }
    

    这是我用来测试它的 javascript 代码:

    var jsonData = { "Text": "test", "Id": "testid", "User": "testuser", "Created": "", "Coordinates": { "Latitude": 57.69679752892457, "Longitude": 11.982091465576104} };
    var tweet = JSON.stringify(jsonData);
    $.ajax({
        type: 'POST',
        url: 'Home/Index',
        data: tweet,
        success: function () {
            alert("Ok");
        },
        dataType: 'json',
        contentType: 'application/json; charset=utf-8'
    });
    

    更新

    我尝试使用模型绑定器进行一些实验,并提出了这个解决方案,它似乎适用于可空类型。

    我创建了一个自定义模型绑定器:

    using System;
    using System.Web.Mvc;
    using System.IO;
    using System.Web.Script.Serialization;
    
    public class TweetModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var contentType = controllerContext.HttpContext.Request.ContentType;
            if (!contentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
                return (null);
    
            string bodyText;
    
            using (var stream = controllerContext.HttpContext.Request.InputStream)
            {
                stream.Seek(0, SeekOrigin.Begin);
                using (var reader = new StreamReader(stream))
                    bodyText = reader.ReadToEnd();
            }
    
            if (string.IsNullOrEmpty(bodyText)) return (null);
    
            var tweet = new JavaScriptSerializer().Deserialize<Models.Tweet>(bodyText);
    
            return (tweet);
        }
    }
    

    我已经为所有类型的推文注册了它:

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
    
            ModelBinders.Binders.Add(typeof(Models.Tweet), new TweetModelBinder());
    
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }
    

    【讨论】:

    • 删除 nullable 确实有效,但会弄乱模型,因为发送空白值将导致 0,这是一个有效的 lat/lng 值。猜猜唯一的方法是手动反序列化我的 json。
    • 我刚刚注意到,如果我将值放在引号中,它可以很好地与可为空的属性绑定。这肯定是一个错误?
    • @jul:你说得对。我做了一些实验,试图使用自定义模型绑定器(ActionResult InsertTweet([ModelBinder(typeof(TweetModelBinder))] Models.Tweet tweet))绑定你的操作值在那里,在 DictionaryValueProvider 中。
    • @jul:我已经用新的解决方案更新了我的答案。这次它工作正常。希望对您有所帮助。
    【解决方案2】:

    我遇到了同样的问题,但在我的情况下,这与从客户端传输数据的方式有关。确保 AJAX 请求使用正确的标头和格式。例如:

        dataType: 'json',
        contentType: 'application/json; charset=UTF-8',
        data: JSON.stringify({
            MemberId : '123',
            UserName: '456',
            Parameters: [
                { Value : 'testing' },
                { Value : 'test2' }
            ]
        }),
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多