2013-10-10 128 views
1

我有一個用戶界面,看起來像這樣:JSON和ASP.NET MVC模型綁定

enter image description here

我想新創建的行的數據到服務器,使服務器可以保存它。

我以JSON格式從客戶端向我的MVC應用程序發送數據。這裏是我的Ajax請求:

var values = []; // an array with each item being an object/associative array 

// more code to get values into variables 

for (var i = 0; i < cultures.length; i++) { 
    var cultureName = cultures[i]; 
    var valueTextBox = $(row).find(...); 
    var value = $(valueTextBox).val(); 

    var cultureNameAndValue = { 'CultureShortName' : cultureName, 'StringValue' : value }; 

    values.push(cultureNameAndValue); 
} 

var stringTableRow = 
    { 
    'ResourceKeyId': resourceKeyId, 
    'Key': resourceKeyName, 
    'CategoryId': categoryId, 
    'CategoryName': categoryName, 
    'StringValues': values 
    }; 

var stringified = JSON.stringify({ StringTableRow: stringTableRow }); 

$.ajax('/Strings/JsonCreateNew', 
     { 
     cache: false, 
     async: false, 
     type: 'POST', 
     contentType: 'application/json; charset=UTF-8', 
     data: stringified, 
     dataType: 'json', 
     error: SaveNewResourceClientSideHandler.OnError, 
     success: SaveNewResourceClientSideHandler.OnSuccess 
     }); 

這裏的發送(如在Firebug看到的)數據:

{"StringTableRow":{"ResourceKeyId":"","Key":"Foo", 
"CategoryId":"1","CategoryName":"JavaScript", 
"StringValues":[ 
{"CultureShortName":"en-US","StringValue":"Something"}, 
{"CultureShortName":"fr-FR","StringValue":""}] 
}} 

這裏是我的服務器端代碼:

public ActionResult JsonCreateNew(StringTableRow row) 
{ 
    // CreateNewStringTableRow(row); 

    // return a success code, new resource key id, new category id 
    // return Json(
       new { Success = true, ResourceKeyId = row.ResourceKeyId, 
        CategoryId = row.CategoryId }, 
       JsonRequestBehavior.AllowGet); 

    return new EmptyResult(); 
} 

而這裏的業務對象我希望我的傳入POST'ed數據被綁定到:

public class StringTableRow 
{ 
    public StringTableRow() 
    { 
     StringValues = new List<CultureNameAndStringValue>(); 
    } 

    public long ResourceKeyId { get; set; } 

    public string Key { get; set; } 

    public long CategoryId { get; set; } 

    public string CategoryName { get; set; } 

    public IList<CultureNameAndStringValue> StringValues { get; set; } 
} 


public class CultureNameAndStringValue 
{ 
    public string CultureShortName { get; set; } 

    public string StringValue { get; set; } 
} 

的Global.asax

public class MvcApplication : System.Web.HttpApplication 
    { 
     protected void Application_Start() 
     { 
      AreaRegistration.RegisterAllAreas(); 

      WebApiConfig.Register(GlobalConfiguration.Configuration); 
      FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
      RouteConfig.RegisterRoutes(RouteTable.Routes); 
      BundleConfig.RegisterBundles(BundleTable.Bundles); 

      ValueProviderFactories.Factories.Add(new JsonValueProviderFactory()); 
     } 
    } 

問題:

動作JsonCreateNew接收的對象不爲空,但是具有未初始化的所有屬性,即所有空的屬性都爲空和value屬性處於它們的缺省值。因此,即使客戶端發送完全有效的Json字符串,我也無法獲得任何數據。

我需要做自定義模型綁定嗎?

回答

1

好的,我解決了我的問題,這也可能是其他程序員的重要見解,因爲我在解決自己的問題的同時學到了一些東西。

我的解決辦法: 我使出不使用JSON,而是使用了HTTP編碼形式張貼值使用的默認編碼,然後我用一些自定義的模型綁定的那個嫌(而不實際創建模型的粘合劑) 。

說明: 通常,當你做一個Ajax請求,並從客戶端傳遞數據到任何服務器平臺上,如果不指定編碼,即jQuery的AJAX方法的設定對象contentType參數(或如果您使用任何其他方式創建除jQuery以外的其他ajax請求,那麼該事件會設置ContentType HTTP標頭是您所追求的),HTTP會使用其默認編碼對您的發佈數據進行編碼,這非常類似於您發佈的內容在查詢字符串後面有一個GET請求,只有它是二進制編碼的並且不作爲URL的一部分發送。

如果是這樣的話,而你發佈任何類型(IListIEnumerableICollectionIDictionary等),ASP.NET MVC的集合,那麼就不要在JavaScript中創建關聯數組體現採集。甚至不要創建一個數組。不要創造任何東西。

其實,只是把它傳遞使用約定的主要大對象中:

data = 
{ /*scalar property */ Gar: 'har', 
    /* collection */ 'Foo[index++].Bar' : 'value1', 
    'Foo[index++].Bar' : 'value2' 
} 

,不使用JSON。這將解決你的問題的一半。

在服務器端,接收FormCollection中的發佈數據並使用其IValueProvider方法(GetValue)挖掘出您需要的數據。您不必顯式創建模型聯編程序來執行此操作。你可以用你的控制器本身的私有方法來完成它。

我會稍後改進這個答案,當我可以找到更多的時間。

+0

我也是在一個類似的情況下,當我發佈數據到服務器使用ajax請求,然後我必須綁定所有的表單值到json格式,如var name = $(「Name」)。 var age = $(「Age」)。val(); // build json object var squirrel = { 姓名:姓名, 年齡:年齡, }; 是否有任何其他方式,我不必手動將值綁定到json.Means有什麼可以直接將我的viewmodel轉換爲json,然後我可以將它作爲一個對象在控制器中? – Dragon

-2

使用Backbone或KnockoutJs進行數據綁定。

+0

謝謝,塔倫。作爲最後的手段,我一直保持淘汰賽。我只是不想將我的問題委託給抽象,因爲我會失去控制權。我在jQuery中構建用戶界面,因爲我剛剛離開使用DevExpress控件,另一個抽象。我知道這個問題與自定義模型綁定有關,並且不想像淘汰賽那樣抽象(除非我沒有別的選擇)。我已經解決了我的問題,並會很快發佈解決方案。 –