Asp.net

ASP.NET MVC3 JSON 模型綁定與嵌套類

  • October 3, 2013

在 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最近寫了一篇關於它的文章。

您的 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);
   }

引用自:https://stackoverflow.com/questions/6564599