在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 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' });
UPDATE
我试图用模型绑定器做一些实验,我出来了这个似乎可以使用可空类型的解决方案.
我创建了一个自定义模型binder:
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); }