3

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

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

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

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

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

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

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

4

6 回答 6

2

所以看起来你的主要问题是像四十二所说的那样缺乏数据源,或者更普遍地说是某种持久性。这可以通过将数据库作为数据源来支持您的模型来完成,这可能是您在永久解决方案中想要的。另一种选择是使用会话。如果这不是生产代码并且您需要一些东西来“工作”,那么会话将是一个快速的解决方案。我倾向于您研究 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

于 2012-12-07T22:55:58.007 回答
1

您是否知道<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 来根据状态等呈现表单。

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

于 2012-12-12T09:53:20.487 回答
0

您不能在 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 中处理这种情况的典型方法。

于 2012-11-29T20:14:40.260 回答
0

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

这里有很多很好的建议.. ASP.NET MVC 中的会话变量

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

于 2012-12-07T22:53:54.960 回答
0

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

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

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

于 2012-12-11T07:20:29.780 回答
0

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

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

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

于 2012-12-13T11:34:40.200 回答