2011-07-03 54 views
13

在MVC3中,如果模型具有嵌套對象,是否可以自動將javascript對象綁定到模型?我的模型是這樣的:ASP.NET MVC3 JSON與嵌套類的模型綁定

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 
    } 

我在這裏丟失了什麼,或者新的自動綁定功能只支持原始對象嗎?

回答

18

是的,你可以綁定複雜的json對象與ASP.NET MVC3。

菲爾哈克寫了關於它recently
您在這裏遇到了地理課的問題。
不要使用空的屬性:

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

我試着做一些用模型粘合劑進行實驗,然後我提出了這種解決方案,它似乎可以與空類型一起正常工作。

我已經創建了一個自定義的模型綁定:

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); 
    } 
+0

刪除可爲空確實有效,但是由於發送空值會導致0,這是一個有效的經緯度值。猜猜唯一的方法是手動反序列化我的JSON。 – jul

+0

我剛剛注意到,如果我把值放在引號中,它可以與可空屬性結合。當然,這肯定是一個錯誤? – jul

+0

@jul:你是對的。我做了一些試驗,試圖使用自定義模型綁定器綁定你的動作(ActionResult InsertTweet([ModelBinder(typeof(TweetModelBinder))] Models.Tweet tweet))和值在那裏,在DictionaryValueProvider。 – LeftyX

0

我經歷了同樣的問題,但在我的情況,這是與客戶端傳輸數據有關。確保AJAX請求使用正確的標題和格式。例如:

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