2009-04-23 95 views
0

我有其中有一个功能叫GetSiteMap()母版页,此功能用于定制呈现基于当前位置的地图。我的问题是,在MVC中,你没有模型背后的代码,因此没有公开这种功能。ASP.NET MVC函数调用

什么是做正确的方法是什么?我应该有一个与其中定义的功能的主控页面控制器?

Public Function GetSitemap() As String 
    Dim s As New SiteNavigation 
    Dim siteMapNodeCollection As SiteMapNodeCollection 

    If Not SiteMap.CurrentNode.Equals(SiteMap.RootNode) Then 
     If Not SiteMap.CurrentNode.HasChildNodes Then 
     ' otherwise it'll go to the pseudo-current directory, which is wrong 
     Dim parentNode As SiteMapNode = SiteMap.CurrentNode.ParentNode.ParentNode 
     s.AddBackLink(parentNode.Url, parentNode.Title) 
     Else 
     Dim parentNode As SiteMapNode = SiteMap.CurrentNode.ParentNode 
     s.AddBackLink(parentNode.Url, parentNode.Title) 
     End If 
    End If 

    If Not SiteMap.CurrentNode.HasChildNodes Then 
     siteMapNodeCollection = SiteMap.CurrentNode.ParentNode.ChildNodes 
    Else 
     siteMapNodeCollection = SiteMap.CurrentNode.ChildNodes 
    End If 

    For Each siteMapNode As SiteMapNode In siteMapNodeCollection 
     GenerateLinks(siteMapNode, s) 
    Next 

    Return s.GetSiteNavigation() 
    End Function 

    Private Sub GenerateLinks(ByRef siteMapNode As SiteMapNode, ByRef siteNavigation As SiteNavigation) 
    If siteMapNode.Url.Length = 0 And siteMapNode.Description = "separator" Then 
     siteNavigation.AddSeparator() 
    ElseIf siteMapNode.Url.Length = 0 And siteMapNode.Description = "heading" Then 
     siteNavigation.AddHeading(siteMapNode.Title) 
    Else 
     siteNavigation.AddLink(siteMapNode.Url, siteMapNode.Description, siteMapNode.Title, siteMapNode.HasChildNodes) 
    End If 
    End Sub 

对不起,这就是我的意思。我前几天写得很快,所以它不完美,但现在它完成了这项工作。我使用的是站点地图,并给出了某些元素没有网址,而是使用“分隔符”等描述来指示<li>元素以不同的方式呈现(将不同的类应用于此HTML元素)。

回答

1

由于该网站地图是可定制的基于用户的位置,我会假设你正在谈论生成用户界面元素,不是搜索引擎映射。为搜索引擎消费生成网站地图可能最好是脱机完成,并且只是定期更新。

生成用户界面我会考虑使用一个ViewUserControl并使其在任何你需要的页面的部分。 ViewUserControl可以更容易地创建和维护与之相关的标记。它也可用于需要它的任何视图(并且可以包含在你的MasterPage中)。正如@Marc Gravell所建议的,它的数据可以使用ActionFilter生成。不过,如果该控件无处不在,可以创建一个基本控制器,控制器可以从该控制器派生并覆盖基本控制器中的OnActionExecuted。您可以检测何时生成ViewResult,然后创建并分配给ViewData用于站点地图控件的数据。

基本控制器:

public override OnActionExecuted(ActionExecutedContext filterContext) 
{ 
    if (filterContext != null && filterContext.Result is ViewResult) 
    { 
     ViewData["siteMap"] = this.GetSiteMap(); 
    } 
} 

母版/查看

<% Html.RenderPartial("SiteMap", ViewData["siteMap"], ViewData) %> 

ViewUserControl

foreach (var elem in Model) 
{ 
    .... render your HTML 
} 
1

这取决于它的功能;如果它只是检查请求,那么你可以在HtmlHelper上编写(例如)扩展方法并从视图中写入;

<%=Html.GetSiteMap()%> 

另一种选择是将其推送到母版页。如果您需要执行数据库查询等,则可以考虑使用“操作过滤器”来完成一半的工作(准备数据),然后(如上所述)在视图中调用HtmlHelper以显示它。有用吗?

+0

啊是的,我还没有实施任何帮手。可能性是它会触发数据库查询的权限。我还不确定。它实际上只是输出一些HTML。我很快就会对HTML助手产生兴趣。 – Kezzer 2009-04-23 11:53:15

+0

我会重构它,以便它不会生成HTML。在MVC中,这最好留给视图,而不是控制器操作。 HtmlHelpers应该对控制器提供的数据进行操作,而不是进行数据库查询。如果您将DB访问权限构建到帮助程序中,您将会破坏关注点。 – tvanfosson 2009-04-23 12:07:50

0

MVC确实有强类型的意见。从您的标记,你可以访问你的模型来确定位置,其basicly替换代码隐藏的逻辑:

<%= Html.Encode(ViewData.Model.GetSiteMap()) %> 

这会使相应的地图。你的模型可能是一个'主表达'类,它揭示了网页常用的不同方法。

我想这是类似于马克提出的解决方案。

0

我的问题是,在MVC你不 有模型背后的代码因此不是 揭露那种功能

这是不正确的。 aspx +后面的代码是默认实现,直到很少发布之前。目前,默认模板没有使用后面的代码,但在运行时内置。

在MVC控制器应该创建您的站点地图的模型和视图(也许一个用户控件)有唯一的责任来呈现它。

也许这可以帮助http://mvcsitemap.codeplex.com/