我正在尝试使用MVC,我的问题是 - 我在使用WebForms的母版页中有Page_Load逻辑,它应该放在MVC中吗?以下是商业案例:
以前,我将它放在MasterPage Load()事件中,看起来在MVC中,我可以在每个控制器中执行此操作(在每个控制器中都不必调用此功能),或者在Global.asax的某个地方(看起来太......全球?)。
编辑:我已经使用Global.asax方法与Controller结合使用来实际处理数据。此时唯一的问题是,所有主机头信息都在数据库中。我通常会存储“租户”信息,如果你将在一个Session变量中,并且只在不存在时才进行数据库调用;有更好的方法吗?
答案 0 :(得分:9)
MVC中没有1:1的等价原因,让我们概括一下如何以MVC的方式思考它:
模型:“此网站的页面始终在特定上下文中被请求,我们称之为租户(或用户,主题或您的子域所代表的任何内容)。域模型具有表示的属性当前要求的承租人。“
查看:“根据模型中设置的租户呈现页面标题。”
控制器:“根据主机标头设置模型中的租户”。
请记住,我们要避免的是混合控制器,视图和业务逻辑。将控制器逻辑放在多个地方或一个地方,不称为“控制器”不是问题,只要它保持分离。
现在好了:你甚至可以使用Web Forms 来实现这个“MVC风格”,而且该解决方案仍适用于ASP.NET MVC!
您仍然拥有请求生命周期(而不是页面生命周期),因此您可以实现一个自定义HttpModule,其中包含所有请求的控制器逻辑的这一部分。它处理BeginRequest事件,检查主机头,并将租户存储到HttpContext.Current.Items [“tenant”]之类的东西。 (当然,你可以为这个字典条目提供一个静态的,类型化的包装器。)
然后,所有模型对象(或模型基类,或适合您的解决方案的任何对象)都可以访问HttpContext以提供对此信息的访问,如下所示:
public string Tenant
{
get { return HttpContext.Current.Items["tenant"]; }
}
优点:
更新您的编辑:我不喜欢在会话中保持状态的想法,特别是如果您的会话cookie不仅适用于每个子域,而且适用于所有域。在这种情况下,如果用户之前访问过另一个子域,则可能会提供不一致的内容。数据库中将主机头映射到租户的信息可能不会经常更改,因此您可以缓存它,并且不需要为每个请求进行数据库查找。
答案 1 :(得分:3)
您可以创建一个基本控制器,为MVC主页面视图提供正确的ViewData,然后从该控制器派生每个实际控制器。如果将逻辑放入ActionExecuting方法,则应该能够生成异常或在必要时重定向到错误页面。
答案 2 :(得分:3)
你也在想“WebForms”而不是MVC。母版页只是视图的包装器,它应该只包含布局html。你可以把东西发送给你的主人,但这是一条单行道,你应该争取不可知论的观点。底线:忘记WebForms所具有的事件,因为它们不会在这里使用。
由于你正在处理Host头文件,我想你可以把它放在Global.asax中...好了我现在很困惑:P
来自http://forums.asp.net/t/1226272.aspx
的被盗代码protected void Application_BeginRequest(object sender, EventArgs e)
{
string host = string.Empty;
if (this.Request.ServerVariables["HTTP_HOST"] == this.Request.Url.DnsSafeHost)
{
host = this.Request.Url.DnsSafeHost;
}
else
{
Regex regex = new Regex("http://[^/]*.host/([^/]*)(/.*)");
Match match = regex.Match(this.Request.Url.AbsoluteUri);
if (match.Success)
{
host = match.Groups[1].Value;
Context.RewritePath(match.Groups[2].Value);
}
}
// Match the host with the portal in the database
...
}
答案 3 :(得分:2)