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として発生し、次にコントローラはそれらをtrycatchでキャプチャし、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()が返される可能性があります。最初の項目を「---1つ選んでください---」などにするなど、他にも考慮すべき考慮事項があります。

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 に答える