Reputation: 18220
I've got a master page which has a function in it called GetSiteMap()
, this function is used to custom render a sitemap based on the current location. My problem is that in MVC you don't have the code behind model thus not exposing that kind of functionality.
What's the correct way to do it? Should I have a master page controller of some sort with that function defined in it?
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
Sorry, this is what I meant. I wrote this very quickly the other day so it's not perfect, but for now it does the job. I'm using sitemap and giving certain elements no URL and instead a description such as "separator" to indicate that the <li>
element is rendered in a different way (a different class is applied to this HTML element).
Upvotes: 0
Views: 1277
Reputation: 2852
My problem is that in MVC you don't have the code behind model thus not exposing that kind of functionality
That's not true. aspx + code behind was the default implementation until few releases ago. Currently the default template make no use of code behind but is builtin in the runtime.
In MVC the Controller should create the Model of your sitemap and the View (maybe an usercontrol) has the only responsibility to render it.
Maybe this can help http://mvcsitemap.codeplex.com/
Upvotes: 0
Reputation: 532465
Since the site map is customizable based on the user's location, I'm going to assume that you are talking about generating a user interface element, not a search engine mapping. Generating a sitemap for search engine consumption is probably best done off-line and simply updated periodically.
To generate the user interface I would consider using a ViewUserControl and rendering it as a partial in whatever pages you need. The ViewUserControl will make it much easier to create and maintain the mark up associated with it. It will also be available to any view (and can be included on your MasterPage) that needs it. As @Marc Gravell suggests, the data for it can be generated using an ActionFilter. It would probably be easiest, though, if the control is ubiquitous to create a base controller from which your controllers can derive and override OnActionExecuted in the base controller. You can detect when a ViewResult has been generated, then create and assign to ViewData the data for the sitemap control.
Base Controller:
public override OnActionExecuted( ActionExecutedContext filterContext )
{
if (filterContext != null && filterContext.Result is ViewResult)
{
ViewData["siteMap"] = this.GetSiteMap();
}
}
MasterPage/View
<% Html.RenderPartial( "SiteMap", ViewData["siteMap"], ViewData ) %>
ViewUserControl
foreach (var elem in Model)
{
.... render your HTML
}
Upvotes: 1
Reputation: 1570
MVC does have strongly typed views. From your markup, you can access your model to determine location which basicly replaces codebehind logic:
<%= Html.Encode(ViewData.Model.GetSiteMap()) %>
which will render the appropriate sitemap. Your model could be a 'Master Presentation' class that exposes different methods that are commonly used by pages.
I guess this is similar to Marc's proposed solution.
Upvotes: 0
Reputation: 1062780
It depends what it does; if it is just inspecting the request, then you could write (for example) an extension method on HtmlHelper
and write it from the view;
<%=Html.GetSiteMap()%>
Another alternatives would be to push this into a master page. If you need to do a database query etc, you might consider an "action filter" to do half the work (preparing the data), and then (as above) a call on HtmlHelper
in the view to display it. Any use?
Upvotes: 1