我正在尝试使用MVC,我的问题是 - 我在使用WebForms的Master Pages中有Page_Load逻辑,它应该放在MVC中?这是商业案例:
不同的主机标题应该导致不同的页面标题显示在网站的(一个)母版页上,因此显示所有页面.例如,如果主机头是hello.mydomain.com,则所有页面/视图的页面标题应为"Hello World",而所有页面/视图的goodbye.mydomain.com应为"Goodbye World".
如果主机头与列表中的任何内容不同,无论应用程序在何处,它都应重定向到/ Error/NoHostHeader.
以前,我将它放在MasterPage Load()事件中,它看起来像在MVC中,我可以在每个控制器中执行此操作(感觉不适合在每个控制器中调用此功能),或者在某处Global.asax(似乎太......全球?).
编辑:我已经使用Global.asax方法与Controller结合使用来实际处理数据.此时唯一的问题是,所有主机头信息都在数据库中.我通常会存储"租户"信息,如果你将在一个Session变量中,并且只在不存在时才进行数据库调用; 有一个更好的方法吗?
MVC中没有1:1的等价原因,让我们概括一下如何以MVC的方式思考它:
模型:"此网站的页面始终在特定上下文中请求,我们称之为租户(或用户,主题或您的子域所代表的任何内容).域模型具有表示当前请求的租户的属性."
查看:"根据模型中设置的租户渲染页面标题."
控制器:"根据主机头设置模型中的租户".
请记住,我们要避免的是混合控制器,视图和业务逻辑.将控制器逻辑放在多个地方或地方,不称为"控制器"不是问题,只要它保持分离即可.
现在好消息:即使使用Web窗体,您也可以使用"MVC样式",该解决方案仍然适用于ASP.NET MVC!
您仍然拥有请求生命周期(而不是页面生命周期),因此您可以实现一个自定义HttpModule,它包含所有请求的控制器逻辑的这一部分.它处理BeginRequest事件,检查主机头,并将租户存储到HttpContext.Current.Items ["tenant"]之类的东西.(当然,你可以为这个字典条目提供一个静态的,类型化的包装器.)
然后,所有模型对象(或模型基类,或适合您的解决方案的任何对象)都可以访问HttpContext以提供对此信息的访问,如下所示:
public string Tenant { get { return HttpContext.Current.Items["tenant"]; } }
好处:
您具有分离的原因(主机头)和效果(呈现页面标题),从而提高了可维护性和可测试性
因此,您可以根据此状态轻松地向域模型添加其他行为,例如根据当前租户从数据库加载内容.
您可以轻松地根据租户制作视图的更多部分,例如您包含的CSS文件,徽标图像等.
您可以稍后更改控制器逻辑以在模型中设置租户,不仅基于子域,还可以基于cookie,引用者,搜索词,用户代理的语言或您可以考虑的任何内容,而无需修改任何你的代码取决于模型.
更新您的编辑:我不喜欢在会话中保持状态的想法,特别是如果您的会话cookie不仅适用于每个子域,而且适用于所有域.在这种情况下,如果用户之前访问过另一个子域,则可能会提供不一致的内容.数据库中将主机头映射到租户的信息可能不会经常更改,因此您可以缓存它,并且不需要为每个请求进行数据库查找.