0

我正在尝试创建一个复杂的 ViewModel,它在公司的详细信息页面中同时具有索引页面和公司注释的创建页面,并且想要一些关于我是否正确执行此操作的指导。

我目前的问题是,当我创建一个新的公司说明时,除了我包含在我的 cshtml 中的 EditorFor 字段之外,它在对象中没有任何信息 - 它丢失了 ViewModel 中的所有数据。

我有一个 Company 模型和 CompanyController,在我的 Details 操作中,我填充了与公司相关的所有注释,以及一个允许用户添加新注释的表单。

我的 Company 和 CompanyNotes 模型非常简单:

public class Company
{
    public int CompanyID { get; set; }
    // bunch of fields related to the company

    public virtual ICollection<CompanyNote> CompanyNotes { get; set; }
}


public class CompanyNote
{
    public int CompanyNoteID { get; set; }
    public DateTime Date { get; set; }
    public string Note { get; set; }

    public Company Company { get; set; }
}

我有一个看起来像这样的 ViewModel:

public class CompanyViewModel
{
    public Company Company { get; set; }

    // List of all notes associated with this company
    public IEnumerable<CompanyNote> CompanyNotes { get; set; }

    // A CompanyNote object to allow me to create a new note:
    public CompanyNote CompanyNote { get; set; }
}

这是我的详细信息操作,它填充公司记录,获取相关注释列表,并显示一个带有新的空对象的创建表单:

    public ActionResult Details(int id = 0)
    {
        var viewModel = new CompanyViewModel();

        viewModel.Company = db.Companies.Find(id);

        if (viewModel.Company == null)
        {
            return HttpNotFound();
        }

        viewModel.CompanyNotes = (from a in db.CompanyNotes
                                  where a.Company.CompanyID.Equals(id)
                                  select a).OrderBy(x => x.Date);

        viewModel.CompanyNote = new CompanyNote
            {
                Date = System.DateTime.Now,
                Company = viewModel.Company
            };

        return View(viewModel);
    }

这是我在 CompanyController 中的 CreateNote 操作。(我应该把它分成一个单独的部分视图吗?有什么好处?)

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult CreateNote(CompanyViewModel companyViewModel)
    {
        CompanyNote companyNote = companyViewModel.CompanyNote;

        if (ModelState.IsValid)
        {

            db.CompanyNotes.Add(companyNote);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(companyViewModel);

    }

最后,这是 detail.cshtml 的简化版本:

@model Project.ViewModels.CompanyViewModel

// My company detail display is here, removed for sake of berevity 
@using (Html.BeginForm("CreateNote", "Company"))
{

    @Html.EditorFor(model => model.CompanyNote.Date)
    @Html.TextAreaFor(model => model.CompanyNote.Note})
    <input type="submit" value="Create" />
}

当我发布时,我的 CreateNote 操作有一个基本上是空的 companyViewModel,除了 companyViewModel.CompanyNote.Date 和 companyViewModel.CompanyNote.Note,它们是我的表单中的字段 - ViewModel 中的所有其他数据都是空的,所以我不知道如何甚至包括对母公司的引用。

我什至在正确的道路上吗?

谢谢,罗比

4

1 回答 1

7

当我发布时,我的 CreateNote 操作有一个基本上是空的 companyViewModel,除了 companyViewModel.CompanyNote.Date 和 companyViewModel.CompanyNote.Note,它们是我的表单中的字段 - ViewModel 中的所有其他数据都是空的,所以我不知道如何甚至包括对母公司的引用。

这是完全正常的行为。当您提交表单时,只有作为输入字段包含在表单中的信息才会发送到服务器,这是您希望模型绑定器能够检索的唯一信息。

如果您在 HttpPost 操作中需要 CompanyNotes 集合,只需查询您的后端,就像您在 GET 操作中所做的那样。您可以通过将公司 ID 作为隐藏字段传递来做到这一点:

@Html.HiddenFor(model => model.Company.CompanyID)

所以这个想法是只在表单信息中包含用户应该以某种方式修改的输入字段。对于所有其他信息,您已经在后端拥有它,所以您所要做的就是点击它来获取它。

与经典的 WebForms 不同,在 ASP.NET MVC 中不再有任何 ViewState 的概念。它更接近 HTTP 协议的无状态特性。

于 2013-09-09T11:31:20.297 回答