asp.net mvc-在工作流中重用页面/控制器
我有两个工作流: 1) 用户第一次注册。他们看到3个不同的屏幕,他们的基本用户信息,他们的信用卡,和一些额外的个人资料信息。他们以类似向导的方式完成这3个步骤,每次点击“提交”按钮,他们都会离开当前屏幕,进入下一个屏幕 2) 用户已注册。他在导航中有指向这3个独立页面的链接。他可以按任何顺序更新它们。当他点击save时,他不会离开他所在的页面,它只是在顶部显示“信用卡信息已保存…”之类的内容。可能使用ajax,也可能是整页刷新 我想在两个工作流之间重用这3个屏幕的代码,不仅是视图,而且是控制器中的代码,但不需要大量的if…then逻辑来确定下一步要去哪里,这取决于它是在向导中首次注册还是更新配置文件的各个部分 有什么想法吗 以下是我尝试重用的代码类型:asp.net mvc-在工作流中重用页面/控制器,asp.net,asp.net-mvc,Asp.net,Asp.net Mvc,我有两个工作流: 1) 用户第一次注册。他们看到3个不同的屏幕,他们的基本用户信息,他们的信用卡,和一些额外的个人资料信息。他们以类似向导的方式完成这3个步骤,每次点击“提交”按钮,他们都会离开当前屏幕,进入下一个屏幕 2) 用户已注册。他在导航中有指向这3个独立页面的链接。他可以按任何顺序更新它们。当他点击save时,他不会离开他所在的页面,它只是在顶部显示“信用卡信息已保存…”之类的内容。可能使用ajax,也可能是整页刷新 我想在两个工作流之间重用这3个屏幕的代码,不仅是视图,而且是控制器中
public ActionResult Index()
{
var model = this.GetModel();
return this.View(Views.Index, model);
}
public ActionResult Save()
{
var model = this.GetModel();
this.TryUpdateModel(model);
this.UserAccountRepository.Save(model.CurrentUser);
return this.RedirectToAction<EditCreditCardController>(c => c.Index());
}
private EditCreditCardModel GetModel()
{
var model = new EditCreditCardModel();
model.CCTypes = ModelHelper.PopulateDropDownWithModel(this.CardTypeRepository, this.CurrentUser.CreditCard.CardType);
model.States = ModelHelper.PopulateDropDownWithModel(this.StateRepository, this.CurrentUser.BillingAddress.State);
model.CurrentUser = this.CurrentUser;
return model;
}
public ActionResult Index()
{
var model=this.GetModel();
返回此.View(Views.Index,model);
}
公共操作结果保存()
{
var model=this.GetModel();
此.TryUpdateModel(model);
这个.UserAccountRepository.Save(model.CurrentUser);
返回这个.RedirectToAction(c=>c.Index());
}
私有EditCreditCardModel GetModel()
{
var模型=新的EditCreditCardModel();
model.CCTypes=ModelHelper.PopulateDropDownWithModel(this.CardTypeRepository,this.CurrentUser.CreditCard.CardType);
model.States=ModelHelper.PopulatedDropDownWithModel(this.StateRepository,this.CurrentUser.BillingAddress.State);
model.CurrentUser=此.CurrentUser;
收益模型;
}
作为一般经验法则,控制器方法应该非常精简,类似于:
public ActionResult SomeAction(int foo, string bar)
{
MyViewModel model = repository.GetData(foo, bar);
return View("SomeView", model);
}
所以,当您谈论控制器重用时,您不应该真正需要或使用它。如果重用控制器逻辑似乎很困难,那么这可能意味着您的控制器太胖了,它们做的太多了
至于重用视图,您只需要明智地使用局部视图。我想说得更具体一些,但如果不知道这些视图中的细节,就很难做到这一点。类似于一组用户配置文件字段的内容很容易放在局部视图中
在查看您的编辑之后,我能说的最好的一点是
GetModel()
方法不应该是控制器的一部分,它应该是模型的一部分(即某个地方的存储库或服务),因此您不必继续重写这5行代码
至于其余的,尽管。。。我真的看不出你会从任何进一步的抽象中得到什么。Index
方法只有两行代码,技术上可以简化为一行,而Save
方法只有三行(第四行是重定向,每个控制器的重定向可能不同)
我完全赞成抽象和代码重用,但对于两个不同的控制器,尝试做比您看起来已经拥有的更多的事情(基于更新的代码示例)可能是过火了(除了
GetModel
部分,可以移动)。如果有5个或20个控制器都重复此代码,那么我可能实现CreditCardController
基类或creditcardheloper
实用程序类。但现在还没有,这将进一步模糊控制器逻辑。基本上,解决方案非常简单,包括创建一个名为“CommonController”(或XController,或您喜欢的任何控制器)的新抽象控制器类,并将代码放在其中,而不是放在实际控制器中。
正常创建控制器时,使用以下代码:
public class HomeController : Controller
创建一个新控制器,并改用此控制器:
public abstract class CommonController : Controller
注意这里的“abstract”关键字,这是唯一的区别。
现在,在实际控制器中,您需要它们继承此CommonController而不是普通控制器,因此,不要使用:
public class HomeController : Controller
您需要使用:
public class HomeController : CommonController
现在,在这个类中,您将有一个如下设置的void方法,而不是通常的ActionResult方法:
public void CommonController() {
ViewData["MyVariable"] = value;
}
至此,CommonController中设置的所有ViewData变量将可用于从控制器返回的视图
总之:
设置一个名为“CommonController”的新控制器,如下所示:
public abstract class CommonController : Controller {
public void CommonController() {
// PUT ALL OF YOUR COMMON VARIABLES AND STUFF
// IN HERE!
ViewData["MyVariable"] = "BOB THE BUILDER!";
if(isLoggedIn) {
ViewData["User"] = "BOB";
}else{
ViewData["User"[ = "Unknown User";
}
// Etc, etc, etc.
}
}
然后使现有控制器使用CommonController作为其基本控制器类:
public class HomeController : CommonController {
public ActionResult Index() {
return View();
}
}
在您看来,您应该能够编写,并且“BOB THE BUILDER!”将出现!
}也许我做错了什么,但我确实发现我的控制器在逻辑上变得更加丰富,即使只是从存储库获取数据、填充下拉列表的selectlist对象等简单的事情。下面是一个例子:
public ActionResult Save(){var model=this.GetModel();this.TryUpdateModel(model);this.UserAccountRepository.Save(model.CurrentUser);返回this.View(Views.Index,model);}私有EditCreditCardModel GetModel(){var model=new EditCreditCardModel();model.CCTypes=ModelHelper.PopulateDropDownWithModel(this.CardTypeRepository,this.CurrentUser.CreditCard.CardType);model.States=ModelHelper.PopulateDropDownWithModel(this.StateRepository,this.CurrentUser.BillingAddress.State);model.CurrentUser=this.CurrentUser;return model;}
@fregas:抱歉,我无法真正理解这一点。。。你可能想把它添加到你的问题中。是的,我考虑过使用继承,但是我有一个基类中所有3个屏幕的全部责任。这似乎不是一个很好的关注点分离…也许不是,但至少您可以将所有的向导逻辑放在一个地方,它可以放在WizardController中—应用程序的其余部分