【问题标题】:How to retrieve two model from a form in MVC?如何从 MVC 中的表单中检索两个模型?
【发布时间】:2015-05-19 06:33:50
【问题描述】:

假设以下领域模型。

public class SystemRequirement
{
   public int SystemRequirementID { get; set; }
   public Platforms Platform { get; set; }
   public string CPU { get; set; }
   public string RAM { get; set; }
   public string Dsiplay { get; set; }
   public string Discription { get; set; }

   public int GameID { get; set; }
   public virtual Game Game { get; set; }
}


public class Game
{
    public int GameID { get; set; }
    public string Name { get; set; }
    public Genres Genre { get; set; }
    public DateTime ReleaseDate { get; set; }
    public bool Multiplay { get; set; }
    public string About { get; set; }

    public virtual List<SystemRequirement> SystemRequirements { get; set; }
}

public class GameSystemViewModel
{
    public Game Game { get; set; }
    public SystemRequirement SystemRequirement { get; set; }
}

我想制作一个表格,允许添加一个包含其系统要求的新游戏。

@model KeyStore.WebUI.Models.GameSystemViewModel

@{
    ViewBag.Title = "Add";
    Layout = "~/Views/Shared/_AdminLayout.cshtml"; 
}


<div class="container">
    @using (Html.BeginForm("Add", "GameAdmin", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <div class="panel">
            <div class="panel-heading">
                <h3>Add New Game</h3>
            </div>

            <div class="panel-body">

                @Html.LabelFor(m => m.Game.Name)
                @Html.TextBoxFor(m => m.Game.Name)

                @Html.LabelFor(m => m.Game.Genre)
                @Html.TextBoxFor(m => m.Game.Genre)

                @Html.LabelFor(m => m.Game.ReleaseDate)
                @Html.TextBoxFor(m => m.Game.ReleaseDate)

                @Html.LabelFor(m => m.Game.Multiplay)
                @Html.CheckBoxFor(m => m.Game.Multiplay)

                @Html.LabelFor(m => m.Game.About)
                @Html.TextAreaFor(m => m.Game.About)


            </div>
        </div>

        <div class="panel">
            <div class="panel-heading">
                <h3>System Requirements</h3>
            </div>

            <div class="panel-body">

                @Html.LabelFor(m => m.SystemRequirement.Platform)
                @Html.TextBoxFor(m => m.SystemRequirement.Platform)

                @Html.LabelFor(m => m.SystemRequirement.CPU)
                @Html.TextBoxFor(m => m.SystemRequirement.CPU)

                @Html.LabelFor(m => m.SystemRequirement.RAM)
                @Html.TextBoxFor(m => m.SystemRequirement.RAM)

                @Html.LabelFor(m => m.SystemRequirement.Dsiplay)
                @Html.TextBoxFor(m => m.SystemRequirement.Dsiplay)


                @Html.LabelFor(m => m.SystemRequirement.Discription)
                @Html.TextAreaFor(m => m.SystemRequirement.Discription)


            </div>
        </div>

        <div class="panel-footer">
            <input type="submit" value="Save" class="btn btn-primary" />
        </div>

    }
</div>

我的控制器类有这三个动作。

  1. 添加:制作游戏视图
  2. [HttpPost]添加:获取对象并使用 linq 将它们保存在数据库中

控制器代码:

public ViewResult Add()
{
  GameSystemViewModel g = new GameSystemViewModel();
  g.Game = new Game();
  g.SystemRequirement = new SystemRequirement();
  return View(g);
}


[HttpPost]
public ActionResult Add(GameSystemViewModel g)
{
  Game mygame = new Game();
  mygame = g.Game;
  mygame.SystemRequirements.Add(g.SystemRequirement);
  gameRepository.Save(mygame);
  return RedirectToAction("Add");
}

但是当表单被发布时,会发生以下错误。正如您在 Locals 中看到的,SystemRequirement 不是 NULL。

问题是什么,我该如何解决?

【问题讨论】:

  • 你可能需要创建一个 ViewModel 来组合这两个模型,然后在你的 View 和 Controller 中使用它
  • @foreach (var property in ViewData.ModelMetadata.Properties)?为每个属性使用强类型帮助器,以便获得正确的 2-way 模型绑定! (无论如何,如果你做得正确,你实际上会写出更多糟糕的代码)
  • 感谢您的精彩回答。也许我没有提到我的主要问题是发布模型时如何使用 LINQ 保存游戏及其系统要求是我的错?为什么我得到 NullReferenceExeption ?
  • 你得到一个NullReferenceExeption,因为SystemRequirements的值是null

标签: asp.net-mvc


【解决方案1】:

您需要创建一个包含 (SystemRequirement) 和 (Game) 类的复合视图模型,如下所示:

public class CombinedViewModel{

public SystemRequirement { get; set; }
public Game { get; set; }

}

和你的控制器:

public ViewResult Add(){
    CombinedViewModel MyModel = new CombinedViewModel();
    MyModel.SystemRequirement = new SystemRequirement();
    MyModel.Game = new Game();
    return View(MyModel);
}


    [HttpPost]
    public ActionResult Add(CombinedViewModel pModel){
        Game game = new Game();
        game = pModel.Game;
        game.SystemRequirements = new List<SystemRequirement>();
        game.SystemRequirements.Add(pModel.SystemRequirement);
        gameRepository.Save(game);
        return RedirectToAction("Add");
    }

视图将是:

@model CombinedViewModel

@{
    ViewBag.Title = "Add";
    Layout = "~/Views/Shared/_AdminLayout.cshtml"; }


<div class="container">
    @using (Html.BeginForm("Add", "GameAdmin", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <div class="panel">
            <div class="panel-heading">
                <h3>Add New Game</h3>
            </div>

            <div class="panel-body">

                @Html.LabelFor(m => m.Game.Name)
                @Html.TextBoxFor(m => m.Game.Name)

                @Html.LabelFor(m => m.Game.Genre)
                @Html.TextBoxFor(m => m.Game.Genre)

                @Html.LabelFor(m => m.Game.ReleaseDate)
                @Html.TextBoxFor(m => m.Game.ReleaseDate)

                @Html.LabelFor(m => m.Game.Multiplay)
                @Html.CheckBoxFor(m => m.Game.Multiplay)

                @Html.LabelFor(m => m.Game.About)
                @Html.TextAreaFor(m => m.Game.About)


            </div>
        </div>

        <div class="panel">
            <div class="panel-heading">
                <h3>System Requirements</h3>
            </div>

            <div class="panel-body">

                @Html.LabelFor(m => m.SystemRequirements.Platform)
                @Html.TextBoxFor(m => m.SystemRequirements.Platform)

                @Html.LabelFor(m => m.SystemRequirements.CPU)
                @Html.TextBoxFor(m => m.SystemRequirements.CPU)

                @Html.LabelFor(m => m.SystemRequirements.RAM)
                @Html.TextBoxFor(m => m.SystemRequirements.RAM)

                @Html.LabelFor(m => m.SystemRequirements.Dsiplay)
                @Html.TextBoxFor(m => m.SystemRequirements.Dsiplay)


                @Html.LabelFor(m => m.SystemRequirements.Discription)
                @Html.TextAreaFor(m => m.SystemRequirements.Discription)


            </div>
        </div>

        <div class="panel-footer">
            <input type="submit" value="Save" class="btn btn-primary" />
        </div>

    } </div>

【讨论】:

  • 我完全按照你说的做了,我的观点很干净。但我的问题是模型发布时如何使用 LINQ 保存游戏及其系统要求?为什么我得到 NullReferenceExeption ?
  • 您的意思是您在控制器中 (Add) 函数的 POST 操作中获得了 nullRefrence 异常?我已经编辑了控制器中的(添加)功能,所以你没有空异常
  • game.SystemRequirements.Add(pModel.SystemRequirement)出现异常
  • 我已经在控制器中编辑了(添加)函数,所以你没有空异常:)
  • 感谢您花时间提供帮助。但再次看到问题,我按照您所说的更改了所有内容,但发生了错误。
猜你喜欢
  • 2020-02-03
  • 1970-01-01
  • 1970-01-01
  • 2017-03-29
  • 2019-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多