我正在进入使用MVC4进行Web开发的第一次尝试,我遇到了一个问题,我只知道它是Web开发中的核心问题之一,但似乎无法包装我的想法围绕着它。
所以我有两个模型:Employee
和Company
。 Employee
有Company
,因此/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的最基本的问题。
答案 0 :(得分:2)
所以看起来你的主要问题是缺乏数据源,如第42条所述,或者更普遍的某种持久性。这可以通过将数据库作为数据源来支持您的模型来完成,这可能是您在永久解决方案中所需要的。另一种选择是使用会话。如果这不是生产代码并且您需要“工作”的东西,那么会话将是一个快速的解决方案。我倾向于让您研究实体框架代码优先方法(因为它相对简单,可以根据您当前的模型创建数据库)。
你提到你是MVC的新手,所以我建议[介绍ASP.NET MVC 4] [1] 对于初学者来说,这是一个非常容易学习的教程。我甚至从那个开始。
修改强>
我同意在数据库中创建一种“临时”条目很奇怪,如果用户放弃该页面,以后需要清理它。我有一个想法是使用ajax(通常我喜欢在jQuery库的帮助下这样做)。我不确定你对图书馆的了解是什么,但我的基本前提是如下......
如果您不熟悉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" />
<% } %>
然后,您只需根据您的情况构建EditorFor
和DisplayFor
控件。如果您不想在公司创建期间显示员工,那么您只需使用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)
你必须做出这样的解决方法:
当用户选择“创建公司”时,请确保调用名为的Action,例如:“CreateCompanyFirst”。此操作将如下所示:
public ActionResult CreateCompanyFirst(Employee emp)
{
string jsonemp = Json(emp);
Company emptyCompany = new Company{};
emptyCompany.EncodedEmployee = jsonemp ;
return View(emptyCompany);
}
当渲染“创建公司视图”时,请确保将EncodedEmployee属性保存在隐藏字段中。
我猜你已经实施了一项创建公司的行动。现在需要稍微修改此代码:
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")
}
您将返回到员工屏幕,并填写以前填写的字段。
显然这意味着视图/动作/路线是功能性的,并没有期待或做任何魔术调整,否则它将不起作用。