【问题标题】:Passing models between controllers in MVC4在 MVC4 中的控制器之间传递模型
【发布时间】:2012-11-16 18:23:18
【问题描述】:

我正在第一次尝试使用 MVC4 进行 Web 开发,我遇到了一个问题,我只知道这是 Web 开发中的核心问题之一,但似乎无法解决我的想法。

所以我有两个模型:EmployeeCompanyEmployee 有一个Company,因此/Employee/Create 包含一个字段,该字段要么是用于选择现有Company 的下拉列表,要么是ActionLink/Company/Create(如果不存在)。 但问题是:如果用户必须创建一个Company,我需要在两个视图中保留现有的Employee 模型——转移到/Company/Create,然后返回到/Employee/Create

所以我的第一种方法是通过@Html.ActionLink("Add...", "Create", "Organization", Model , null)Employee 模型传递给/Company/Create,但是当我到达CompanyCreate(Employee emp) 时,所有emp 的值都是@ 987654339@.

第二个问题是,如果我尝试返回 /Employee/Create,我将传回 Employee,这将解析为 POST 操作。

基本上,整个想法是保存/Employee/Create 页面的状态,跳转到/Company/Create 以创建Company 记录,然后返回/Employee/Create 以完成Employee 的创建。 我知道有一个很好理解的解决方案,因为 ,但我似乎无法很好地分阶段来获得一个好的谷歌结果。

我曾考虑过使用 Session,但这样做似乎有点麻烦。我真的很想要一个优雅的解决方案。

编辑:很难相信这个问题没有规范的解决方案。感觉这应该是使用 HTTP 的一个最基本的问题。

【问题讨论】:

    标签: asp.net-mvc-4


    【解决方案1】:

    你必须做一个这样的解决方法:

    1. 向 Company 模型添加一个字符串属性,命名为 EncodedEmployee
    2. 以您现在的方式显示您的创建员工视图。用户可能会点击“创建公司”链接。
    3. 当用户选择“创建公司”时,请确保调用了一个名为“CreateCompanyFirst”的操作。此操作将如下所示:

      public ActionResult CreateCompanyFirst(Employee emp)
      {
          string jsonemp = Json(emp);
      
          Company emptyCompany = new Company{};
      
          emptyCompany.EncodedEmployee =  jsonemp ;
      
          return View(emptyCompany);
      }
      
    4. 渲染“创建公司视图”时,确保将 EncodedEmployee 属性保存在隐藏字段中。

    5. 我猜您已经实施了创建公司的操作。现在这段代码需要稍微修改一下:

      public ActionResult CreateCompany(Company cmp)
      {
          // Save your company
      
          // if cmp.EncodedEmployee  is not null
      
              // De serialize the employee, return View(employee)
      
          // else return what you were returning before
          // (maybe "thanks for creating a company, come back soon")
      }
      
    6. 您将返回到您的员工屏幕,并像以前一样填写字段。

    很明显,这意味着视图/动作/路由是正常工作的,没有期待或做任何神奇的调整,否则它将无法工作。

    【讨论】:

      【解决方案2】:

      因此,您的主要问题似乎是像 42 所说的那样缺乏数据源,或者更普遍地说是某种持久性。这可以通过将数据库作为数据源来支持您的模型来完成,这可能是您在永久解决方案中想要的。另一种选择是使用会话。如果这不是生产代码并且您需要一些东西来“工作”,那么会话将是一个快速的解决方案。我倾向于您研究 Entity Framework Code First 方法(因为它相对简单,并且可以根据您当前的模型创建数据库)。

      您提到您是 MVC 新手,所以我会推荐 [Intro to ASP.NET MVC 4][1] 对于初学者来说,这是一个非常容易遵循的教程。我什至从那个开始。

      编辑

      我同意在数据库中创建一种“临时”条目很奇怪,如果用户放弃该页面,以后需要对其进行清理。我的一个想法是使用 ajax(通常我喜欢在 jQuery 库的帮助下这样做)。我不确定您对图书馆的了解是什么,但我的基本前提如下......

      1. 用户单击其中一个按钮。
      2. 通过对控制器使用异步调用,您可以完成一些所需的工作并返回结果。您的控制器方法可能需要返回 JSONResult。
      3. 使用此结果,您可以更新视图。我的想法是使用结果来填充表单。
      4. 现在用户可以点击“提交”并被发送到一个方法,然后更新/保存到数据库。

      如果您不熟悉 jQuery,您可能想了解一下。

      关于使用 jQuery 和 JsonResult 的帖子:https://stackoverflow.com/a/9463272/1200520

      【讨论】:

      • am 使用 EF Code First。但问题是在用户点击“提交”之前在数据库中创建记录对我来说似乎很疯狂。如果用户开始创建公司,但中途放弃了,那么现在我的数据库中有一个员工半成品的无用记录。
      • 看起来这将是最好的方法。我现在的计划是开始学习 JQuery 和 AJAX 方法,以在“创建员工”页面中显示“创建公司”对话框。谢谢!
      【解决方案3】:

      您是否知道<input type="submit" name"createEmployee" value="Create Employee" /> name 属性在 POST 请求中作为参数传递,并且默认的 ModelBinder 会绑定它?

      这意味着,您可以在一个表单上拥有多个提交按钮。

      假设您有一个 ViewModel,例如:

      public class CreateCompanyWithEmployeeModel
      {
      public Employee Employee { get; set; }
      public Company Company { get; set; }
      
      public string createEmployee { get; set; }
      public string createCompany { get; set; }
      
      public string State { get { return (String.IsNullOrEmpty(createCompany)) ? "createEmployee" : "createCompany"; }}
      }
      

      当然还有那些为您的员工和公司定制的类型,例如:

      public class Employee
      {
         // Employee properties here
      }
      
      public class Company
      {
         // Company properties here
      }
      

      然后你可以有这样的动作:

          public ActionResult CreateCompanyWithEmployee(CreateCompanyWithEmployeeModel model)
          {
              switch (model.State)
              {
                  case "createEmployee":
                      // Do your createEmployee Stuff
                      break;
                  case "createCompany":
                      // Do your createCompany Stuff
                      break;
                  default:
                      throw new NotImplementedException(String.Format("State {0} not implemented", model.State));
              }
              return View();
          }
      

      在视图中,您会有如下形式:

      <% using(Html.BeginForm()) { %>
      
          <%=(Model.State == "createEmployee") ? Html.EditorFor(Model.Employee) : Html.DisplayFor(Model.Employee) %>
          <%=(Model.State == "createCompany") ? Html.EditorFor(Model.Company) : Html.DisplayFor(Model.Company) %>
      
          <input type="submit" name="<%=Model.State%>" value="Submit" />
      
      <% } %>
      

      然后您只需要根据您的情况构建您的EditorForDisplayFor 控件。如果您不想在创建公司期间显示员工,那么您只需使用HiddenFor 将员工数据保存到表单中,直到完成公司编辑。与在员工完全有效之前不显示公司数据相同。

      我知道这个例子并不完全干净,但为了方法的清晰起见,我需要让它保持简单。基本上,如果你经常使用这种方法,你会让 ViewModel 继承一个接口来处理 viewmodel 状态处理,并且你会有自定义的 Html Helpers 来根据状态等呈现表单。

      我们经常使用这种方法。它适用于世界上的所有浏览器。

      【讨论】:

      • 这是我建议的答案。
      【解决方案4】:

      您可以使用 TempData 来存储数据,直到下一次请求。 http://www.devcurry.com/2012/05/what-is-aspnet-mvc-tempdata.html

      您也可以使用 POST 请求,这也是非常好的和常见的解决方案。

      您也可以考虑在 ajax 模式中添加公司并在之后刷新下拉值。

      【讨论】:

      • 在单服务器开发环境中可能工作得很好,但如果生产站点在农场上,它将停止工作。持久化视图上的临时数据将携带请求之间的值。
      【解决方案5】:

      实现这一目标的唯一方法是使用某种类型的持久性策略。采用哪种方法取决于您。如果音量符合要求,我建议使用 InProc 会话。

      这里有很多很棒的建议.. Session variables in ASP.NET MVC

      这也是一个非常好的抽象实现示例。 http://blogs.planetcloud.co.uk/mygreatdiscovery/post/Abstracting-session-in-ASPNET-MVC.aspx

      【讨论】:

        【解决方案6】:

        您不能在 url 中传递对象(GET 请求),这就是为什么在您的第一种方法中这些值都是空的。通常,您会使用 EmployeeId 作为参数传递,然后从控制器中的数据源重新获取 Employee 对象。

        所以你的链接是

        @Html.ActionLink("Add...", "Create", "Organization", new { id = Model.EmployeeId }, null)
        

        以及动作方法

        public ActionResult Create(int id)
        {
          //hit the db to grab the Employee by id
        }
        

        这是在 asp.net mvc 中处理这种情况的典型方式。

        【讨论】:

        • 但仅此而已。在用户单击“创建公司”链接时,Employee 尚未发布,因此没有Id 可输入 URL。整个想法是保存/Employee/Create页面的状态,跳转到/Company/Create创建Company记录,然后返回/Employee/Create完成Employee的创建。
        猜你喜欢
        • 1970-01-01
        • 2010-12-31
        • 1970-01-01
        • 2014-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多