2012-07-25 67 views
0

我一直在努力解決這個令人討厭的問題。我有一個模型,編輯器和控制器:如何在調用構造函數之前將表單值分配給模型

public class TeamDetails{ 
    public int SeasonId{get;set;} 

    public TeamDetails() 
    { 
     //need SeasonId to be populated already from form here, but it won't yet. 
    } 

    public TeamDetails(int seasonId) 
     : this() 
    { 
     //load dropdownlist using seasonId from repository 
    } 
} 

//Controller 

//get method gets seasonId from querystring. 
public ViewResult Create(int seasonId) 
{ 
    // calls the parameterized constructor for TeamDetails 
    // which uses seasonId to populate a dropdownlist from db repo. 
    var teamDetails = new TeamDetails(seasonId); 
} 

[HttpPost] 
public PartialViewResult Create(TeamDetails model) 
{ 
    // no such luxury here to call the parameterized 
    // Constructor for model. additional logic. 
} 

//editor 

@using (Ajax.BeginForm("Create", "Team", options)) 
{ 
    @Html.ValidationSummary(true) 
    @Html.HiddenFor(model => model.SeasonId) 
    //additional fields 
} 

我需要有SeasonId從隱藏字段已經被時間TeamDetails構造填充被擊中,因爲我需要在構造函數中。但是,這顯然不會發生,因爲在MVC有機會將SeasonId指定給對象之前調用構造函數。任何方式我可以解決這個問題?

感謝

里茲

+0

GET方法是什麼樣的? – Chris 2012-07-25 19:21:44

+0

我已編輯以包含GET方法。 – Riz 2012-07-25 19:25:16

+0

我編輯了一些更清晰的圖片。 – Riz 2012-07-25 19:28:49

回答

0

我建議不要在你的視圖模型中嵌入像這樣的邏輯(比如從SeasonId中確定團隊數據)。將ViewModel視爲僅具有屬性的純平面對象。在視圖模型上應用所需的任何輸入驗證屬性,然後在處理回發的操作中檢查您的模型狀態是否存在驗證問題。業務規則驗證可能是您無法在控制器中執行的操作,因爲您可能需要來自其他來源(如數據庫等)的信息。這些應該在您的業務層中,我將這些問題作爲DomainException提出,然後在我的控制器在try catch中捕獲它們,並將任何DomainExceptions作爲ModelError添加到ModelState。然後做你的正常測試,如果ModelState.IsValid。一旦你的模型是有效的,你可以創建一個你的TeamDetails類的內部實例,如果你必須在你的完全控制下處理它的內部工作。儘管我會建議保留業務層中的視圖數據的實際業務邏輯,而不是控制器中的業務邏輯。將控制器視爲將信息從視圖模型傳遞到業務/服務層的一種方式,就是這樣。

下面是一些僞代碼,以顯示我的意思,我沒有檢查這是否在語法上正確,但你明白了。

public class TeamsCreateFormModel 
{ 
    public int TeamId { get; set; } 
    [Required] 
    public int SeasonId { get; set; } 
    [Required] 
    public string Name { get; set; } 
    public int Color { get; set; } 
} 

[HttpPost, ValidateAntiForgeryToken] 
public ActionResult Create(TeamsCreateFormModel model) 
{ 
    if (!ModelState.IsValid) 
     return RedirectToAction("Create"); 
    try 
    { 
     Team team = new Team() {Name = model.Name, 
           Color = model.Color, 
           SeasonId = model.SeasonId} 

     var teamService = new TeamService(); //DAL encapsulated in this class 
     team = teamService.Create(team); 
    } 
    catch (DomainException ex) 
    { 
     ModelState.AddModelError(string.Empty, ex.Message); 
     return RedirectToAction("Create"); 
    } 
    return RedirectToAction("Details", new { id = team.TeamId}); 
} 

編輯: 對於處理那些你需要有預填充我也建議使用視圖模式下拉菜單和其他的東西。最簡單的方法就是從您的模型中繼承期望的回發模型,並在視圖中添加您需要的任何屬性,但不要期望在提交時回發到服務器。

public class TeamsCreateViewModel : TeamsCreateFormModel 
{ 
    public IEnumerable<SelectListItem> Seasons 
} 

爲簡單起見,我使用LINQ到從集合GetSeasons()很可能會回到獲得SelectListItem的集合。還有其他因素來看待,以及如具有第一項是這樣的「---請選擇一個---」或類似

public ActionResult Create() 
{ 
    var teamService = new TeamService(); //DAL encapsulated in this class 
    var model = new TeamsCreateViewModel(); 
    model.Seasons = teamService.GetSeasons().Select(x => new SelectListItem() 
            {Text = "TextHere", Value = "ValueHere"}); 
    return View("Create"); 
} 

的觀點將有這樣的事情......

@model TeamsCreateViewModel 
... 
@Html.DropDownListFor(x => x.SeasonId, Model.Seasons) 
+0

感謝您仔細思考的迴應。然而,我遇到的問題是我需要填充作爲TeamsCreateFormModel的一部分的下拉列表,否則我會從MVC獲取有關ViewData的錯誤。原因是在Post上,當動作加載模型時,需要重新填充該下拉列表。這有意義嗎? – Riz 2012-07-25 21:44:58

0

不,構造總是會首先被調用。這不是mvc相關的功能,這是.net功能 - 不調用它的構造函數就不能創建類的實例。

我建議考慮一下,模型內部不應該有邏輯,它們只是包含數據的類。對於操作(包括填充模型)應該使用一個操作。

+0

好的,那麼你會怎麼做我在做什麼? – Riz 2012-07-25 19:38:09

相關問題