2010-11-16 30 views
3

我有一個ViewModel像這樣:如何在ASP.NET MVC中的POST請求之間傳輸ViewModel數據?

public class ProductEditModel 
{ 
    public string Name { get; set; } 
    public int CategoryId { get; set; } 
    public SelectList Categories { get; set; } 

    public ProductEditModel() 
    { 
     var categories = Database.GetCategories(); // made-up method 
     Categories = new SelectList(categories, "Key", "Value"); 
    } 
} 

然後我有一個使用此模型中的兩個控制器的方法:

public ActionResult Create() 
{ 
    var model = new ProductEditModel(); 
    return View(model); 
} 

[HttpPost] 
public ActionResult Create(ProductEditModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     // convert the model to the actual entity 
     var product = Mapper.Map(model, new Product()); 
     Database.Save(product); 
     return View("Success"); 
    } 
    else 
    { 
     return View(model); // this is where it fails 
    } 
} 

的用戶第一次進入到Create視圖,它們都帶有一個類別列表。但是,如果它們未通過驗證,則將視圖發回給它們,但這次Categories屬性爲空。這是可以理解的,因爲ModelBinder不持續Categories如果在POST請求是沒有。我的問題是,保持Categories的最佳方式是什麼?我可以這樣做:

[HttpPost] 
public ActionResult Create(ProductEditModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     // convert the model to the actual entity 
     var product = Mapper.Map(model, new Product()); 
     Database.Save(product); 
     return View("Success"); 
    } 
    else 
    { 
     // manually populate Categories again if validation failed 
     model.Categories = new SelectList(categories, "Key", "Value"); 
     return View(model); // this is where it fails 
    } 
} 

但這是一個醜陋的解決方案。我還能堅持嗎?我不能使用隱藏字段,因爲它是一個集合。

回答

2

我通常實現我的列表(下拉菜單)爲只讀屬性。當視圖獲取值時,該屬性自包含它需要返回值的內容。

public SelectList Categories 
{ 
    get 
    { 
     var categories = Database.GetCategories(); // made-up method 
     return new SelectList(categories, "Key", "Value"); 
    } 
} 

如果有必要,你可以抓住當前選擇的項目從屬性包含被張貼並綁定到你的類的實例ID(即驗證失敗)。

0

在我來說,我有一個BaseModel類,我把所有的財產清單作爲類屬性。

類似於下面的示例中:

public IEnumerable<SelectListItem> CountryList 
{ 
    get 
    { 
     return GetCountryList().Select(
      t => new SelectListItem { Text = t.Name, Value = Convert.ToString(t.CountryID) }); 
    } 
} 

GetCountryList()是問一個Singleton的數據的功能。這僅會在應用程序生命週期

另一種方式這樣做一次,並且如果這些名單是相當大的,將有一個返回SelectListItem查找表中的靜態實用工具類。

如果您需要訪問從不時更改然後只需一個列表不使用Singleton類。

+0

所以,換句話說,手動重新填充列表? – 2010-11-16 03:15:05

+0

你是什麼意思手動? – Lorenzo 2010-11-16 03:15:42

+0

哦,哎呀,我以爲你說'BaseController',而不是'BaseModel'。 – 2010-11-16 03:17:45

2

我會使用存儲庫來獲取任何數據需要,並且不認爲這是一個醜陋的解決方案:

[HttpPost] 
public ActionResult Create(ProductEditModel model) 
{ 
    if (!ModelState.IsValid) 
    { 
     // manually populate Categories again if validation failed 
     model.Categories = Repository.GetCategories(); 
     return View(model); 
    } 

    // convert the model to the actual entity 
    var product = Mapper.Map(model, new Product()); 
    Database.Save(product); 

    // I would recommend you to redirect here 
    return RedirectToAction("Success"); 
} 

爲了進一步重構這個我建議你看吉米·博加德優秀Putting Your Controllers on a Diet視頻演示。

+0

我之所以說這是醜陋的原因是因爲它違反了單一責任原則:ViewModel應該知道如何獲得它需要發送到視圖的數據。如果你需要在外部設置,那麼它只是一個DTO。 – 2010-11-16 19:18:50

相關問題