假设我正在开发一个将由多个部门使用的帮助台应用程序。应用程序中的每个URL都包含一个指示特定部门的密钥。密钥始终是系统中每个操作的第一个参数。例如
http://helpdesk/HR/Members
http://helpdesk/HR/Members/PeterParker
http://helpdesk/HR/Categories
http://helpdesk/Finance/Members
http://helpdesk/Finance/Members/BruceWayne
http://helpdesk/Finance/Categories
问题是,在每个请求的每个操作中,我必须使用此参数,然后根据该密钥从存储库中检索Helpdesk部门模型。从该模型我可以检索成员列表,类别等,这对于每个帮助台部门是不同的。这显然违反了DRY。
我的问题是,如何创建一个基本控制器,它为我这样做,以便URL中指定的特定帮助台部门可用于所有派生控制器,我可以专注于操作?
答案 0 :(得分:2)
我的一个项目中有类似的场景,我倾向于使用ModelBinder而不是使用单独的继承层次结构。您可以创建一个ModelBinder属性来从RouteData获取实体/ entites:
public class HelpdeskDepartmentBinder : CustomModelBinderAttribute, IModelBinder {
public override IModelBinder GetBinder() {
return this;
}
public object GetValue(ControllerContext controllerContext, string modelName, Type modelType, ModelStateDictionary modelState) {
//... extract appropriate value from RouteData and fetch corresponding entity from database.
}
}
...然后您可以使用它来使HelpdeskDepartment适用于您的所有操作:
public class MyController : Controller {
public ActionResult Index([HelpdeskDepartmentBinder] HelpdeskDepartment department) {
return View();
}
}
答案 1 :(得分:0)
免责声明:我目前正在运行MVC Preview 5,因此其中一些可能是新的。
最佳实践方法:只需实现一个静态实用程序类,该实用程序类提供执行模型查找的方法,将ActionData中的RouteData作为参数。然后,从需要该模型的所有操作中调用此方法。
kludgy方式,仅当每个控制器中的每个操作都需要模型时,并且您真的不希望在操作中有额外的方法调用:在Controller-implementation-base-class中,重写ExecuteCore (),使用RouteData填充模型,然后调用base.ExecuteCore()。
答案 2 :(得分:0)
您可以通过普通的C#继承创建基本控制器类:
public abstract class BaseController : Controller
{
}
public class DerivedController : BaseController
{
}
您只能将此基类用于需要部门的控制器。您不必执行任何特殊操作来实例化派生控制器。
从技术上讲,这很好用。然而,从设计的角度来看存在一些风险。如果,如你所说,你的所有控制器都需要一个部门,这很好。如果只有部分人需要部门,那可能还是可以的。但是,如果某些控制器需要一个部门,而其他控制器需要一些其他继承的行为,并且两个子集相交,那么您可能会发现自己陷入了多重继承问题。这表明继承不是解决您所述问题的最佳设计。