MVC中的“母版页”逻辑应该放在哪里?

时间:2009-03-07 18:29:16

标签: asp.net-mvc model-view-controller session webforms master-pages

我正在尝试使用MVC,我的问题是 - 我在使用WebForms的母版页中有Page_Load逻辑,它应该放在MVC中吗?以下是商业案例:

  • 不同的主机标题应该导致不同的页面标题显示在网站的(一个)母版页上,因此显示所有页面。例如,如果主机头是hello.mydomain.com,则所有页面/视图的页面标题应为“Hello World”,而所有页面/视图的goodbye.mydomain.com应为“Goodbye World”。
  • 如果主机标头与列表中的任何标头不同,无论应用程序在何处,它都应重定向到/ Error / NoHostHeader。

以前,我将它放在MasterPage Load()事件中,看起来在MVC中,我可以在每个控制器中执行此操作(在每个控制器中都不必调用此功能),或者在Global.asax的某个地方(看起来太......全球?)。

编辑:我已经使用Global.asax方法与Controller结合使用来实际处理数据。此时唯一的问题是,所有主机头信息都在数据库中。我通常会存储“租户”信息,如果你将在一个Session变量中,并且只在不存在时才进行数据库调用;有更好的方法吗?

4 个答案:

答案 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"]; }
}

优点:

  • 您已分离原因(主机标题)和效果(呈现页面标题),提高可维护性和可测试性
  • 因此,您可以根据此状态轻松地向域模型添加其他行为,例如根据当前租户从数据库加载内容。
  • 您可以根据租户轻松制作视图的更多部分,例如您包含的CSS文件,徽标图像等。
  • 您可以稍后更改控制器逻辑,以便在模型中设置租户,不仅可以基于子域,还可以基于cookie,引荐来源,搜索词,用户代理的语言或任何您可以考虑的内容,根据模型修改任何代码。

更新您的编辑:我不喜欢在会话中保持状态的想法,特别是如果您的会话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)

相关问题