在MVC4中的控制器之间传递模型

时间:2012-11-28 19:28:47

标签: asp.net-mvc-4

我正在进入使用MVC4进行Web开发的第一次尝试,我遇到了一个问题,我只知道它是Web开发中的核心问题之一,但似乎无法包装我的想法围绕着它。

所以我有两个模型:EmployeeCompanyEmployeeCompany,因此/Employee/Create包含的字段可以是用于选择现有Company的下拉列表,也可以是ActionLink/Company/Create如果不存在。 但问题是:如果用户必须创建Company,我需要在两个视图中保留现有的Employee模型 - 一直到/Company/Create,然后再回到/Employee/Create }。

所以我的第一种方法是将Employee模型传递给/Company/Create @Html.ActionLink("Add...", "Create", "Organization", Model , null),但是当我到达Company的{​​{1}}时, Create(Employee emp)的所有值均为emp

第二个问题是,如果我尝试回到null,我会传回/Employee/Create,这会解析为Employee行动。

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

我虽然关于使用Session,但似乎这样做会有点像kludge。我真的很喜欢这个优雅的解决方案。

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

6 个答案:

答案 0 :(得分:2)

所以看起来你的主要问题是缺乏数据源,如第42条所述,或者更普遍的某种持久性。这可以通过将数据库作为数据源来支持您的模型来完成,这可能是您在永久解决方案中所需要的。另一种选择是使用会话。如果这不是生产代码并且您需要“工作”的东西,那么会话将是一个快速的解决方案。我倾向于让您研究实体框架代码优先方法(因为它相对简单,可以根据您当前的模型创建数据库)。

你提到你是MVC的新手,所以我建议[介绍ASP.NET MVC 4] [1] 对于初学者来说,这是一个非常容易学习的教程。我甚至从那个开始。

修改

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

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

    发布关于使用jQuery和JsonResult:https://stackoverflow.com/a/9463272/1200520

答案 1 :(得分:1)

您是否知道在POST请求中将<input type="submit" name"createEmployee" value="Create Employee" /> name属性作为参数传递,默认的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来根据状态等来呈现表单等等。

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

答案 2 :(得分:0)

您无法在网址中传递对象(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中处理这种情况的典型方法。

答案 3 :(得分:0)

解决这个问题的唯一方法是使用某种类型的持久性策略。通过哪种方法取决于您。如果音量合规,我建议使用InProc会话。

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

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

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

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

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

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

  6. 我猜你已经实施了一项创建公司的行动。现在需要稍微修改此代码:

    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")
    }
    
  7. 您将返回到员工屏幕,并填写以前填写的字段。

  8. 显然这意味着视图/动作/路线是功能性的,并没有期待或做任何魔术调整,否则它将不起作用。