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
}

我需要在 TeamDetails 构造函数被击中时已经填充了隐藏字段中的 SeasonId,因为我在构造函数中需要它。但是,这显然不会发生,因为在 MVC 有机会将 SeasonId 分配给对象之前调用了构造函数。有什么办法可以解决这个问题吗?

谢谢

里兹

4

2 回答 2

0

不,构造函数总是首先被调用。这不是 mvc 相关的功能,这是 .net 功能 - 如果不调用它的构造函数,就无法创建类的实例。

我建议考虑一下,模型内部不应该有逻辑,它们只是保存数据的类。对于操作(包括填充模型),应该使用一个动作。

于 2012-07-25T19:34:06.080 回答
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 从集合中获取 SelectListItem 的集合GetSeasons()很可能返回。还有其他需要考虑的因素,例如让第一个项目类似于“---请选择一个---”等

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)
于 2012-07-25T20:30:22.443 回答