[ASP.NET MVC] Dynamisch menu 1x inladen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Beste ontwikkelaars,

In ASP.NET MVC ben ik een applicatie aan het ontwikkelen waar een dynamisch menu op de master page moet komen. Het menu moet geinitalizeerd worden vanuit een XML bestand. Welke items er zichtbaar zijn hangt af van de gebruikersrol.
Na het inloggen moet het menu zichtbaar zijn. Het is niet de bedoeling dat bij iedere muisklik het menu opnieuw ingeladen wordt.
Ik heb al naar verschillende oplossingen gekeken om er voor te zorgen dat het menu niet iedere keer ingeladen hoeft te worden, maar ik ben er niet uit gekomen. Heeft een van jullie een idee?

Bekeken oplossingen:
-http://code-inside.de/blog-in/2008/04/15/aspnet-mvc-display-dynamic-data-on-master-pages/ , werkt niet meer.
-Met sessie. Dit is niet handig omdat dan aan iedere controller actie code toegevoegd moet worden.

Groet

Acties:
  • 0 Henk 'm!

  • creator1988
  • Registratie: Januari 2007
  • Laatst online: 23:06
In je model een property maken met daarin 'MenuItems', die afhankelijk van je locatie, en ingelogd status een lijst met menuitems geeft. Kan je in een usercontrol hier doorheen itereren en iets doen als

code:
1
2
3
<% foreach(MenuItem item in Model.MenuItems) { %>
   <li><a href="<%=item.Url%>"><%=item.Naam%></a></li>
<%}%>

o.i.d.

Acties:
  • 0 Henk 'm!

Verwijderd

creator1988 schreef op maandag 07 september 2009 @ 12:33:
In je model een property maken met daarin 'MenuItems', die afhankelijk van je locatie, en ingelogd status een lijst met menuitems geeft. Kan je in een usercontrol hier doorheen itereren en iets doen als

code:
1
2
3
<% foreach(MenuItem item in Model.MenuItems) { %>
   <li><a href="<%=item.Url%>"><%=item.Naam%></a></li>
<%}%>

o.i.d.
Maar is het dan niet zo dat 'ie nog steeds die MenuItems bij elke muisklik uit een XML gaat laden? Volgens mij moet je dan ook nog Lazy-loading toepassen in je model:

code:
1
2
  if (Model.MenuItems == null) then
    Model.MenuItems = XMLMenuItems.GetFromXML();


offtopic:
Uit nieuwsgierigheid: ik ben ook bezig met het opzetten van een ASP.NET MVC applicatie en ik vroeg me af hoe je die menu items naar de juiste controllers laat wijzen? Geef je dan ook menu items specifieke actions en parameters mee?

[ Voor 15% gewijzigd door Verwijderd op 07-09-2009 13:34 . Reden: Offtopic toegevoegd ]


Acties:
  • 0 Henk 'm!

  • creator1988
  • Registratie: Januari 2007
  • Laatst online: 23:06
Verwijderd schreef op maandag 07 september 2009 @ 13:27:
[...]


Maar is het dan niet zo dat 'ie nog steeds die MenuItems bij elke muisklik uit een XML gaat laden? Volgens mij moet je dan ook nog Lazy-loading toepassen in je model:

code:
1
2
  if (Model.MenuItems == null) then
    Model.MenuItems = XMLMenuItems.GetFromXML();


offtopic:
Uit nieuwsgierigheid: ik ben ook bezig met het opzetten van een ASP.NET MVC applicatie en ik vroeg me af hoe je die menu items naar de juiste controllers laat wijzen? Geef je dan ook menu items specifieke actions en parameters mee?
Je pseudocode klopt van geen kant, aangezien MVC stateless is, elke request gaat deze dus de items opnieuw laden uit de xml, verder wordt er maar één keer geladen per request, want dat is de eigenschap van een foreach(). Je kunt uiteraard wel de items cachen in memory (in een Session oid).

Je menuitems mappen naar controllers via je mappings in global.asax, dus je doet gewoon <a href="/controllernaam/actie/">. Zoals je ook je normale pagina's zou opbouwen.

Acties:
  • 0 Henk 'm!

  • TheNameless
  • Registratie: September 2001
  • Laatst online: 07-02 21:38

TheNameless

Jazzballet is vet!

Ik heb hier zelf ook behoefte aangehad en heb zelf ook geprobeerd een menu in elkaar te knutselen.
Totdat ik het volgende project vond op codeplex:
http://mvcsitemap.codeplex.com/

Het project implementeerd een sitemap provider voor MVC. Dat beteken dus dat je je menu kan definieren in een web.sitemap file (of dynamisch vanuit een database of een XML file in jou geval). Hier word ook meteen rekening gehouden met nodige roles (kan je aangeven door middel van een System.Web.Mvc.AuthorizeAttribute op je controller of actions).
Ook zit er al zaken in zoals caching van je sitemap.

Om het op het scherm te tonen kan je via een HtmlHelper extension de SitemapProvider aanroepen, zodat je de boel niet in je ViewData hoeft te stoppen.

[ Voor 11% gewijzigd door TheNameless op 07-09-2009 15:03 ]

Ducati: making mechanics out of riders since 1946


Acties:
  • 0 Henk 'm!

Verwijderd

creator1988 schreef op maandag 07 september 2009 @ 14:10:
[...]


Je pseudocode klopt van geen kant, aangezien MVC stateless is, elke request gaat deze dus de items opnieuw laden uit de xml, verder wordt er maar één keer geladen per request, want dat is de eigenschap van een foreach(). Je kunt uiteraard wel de items cachen in memory (in een Session oid).
Ok, dat is dan wat ik bedoel. Ik 'cache' ze in de sessie (al heb ik gelezen dat je weer niet teveel op wilt slaan in de sessie wanneer je meerdere users hebt, dus dat is bekend ;) ), maar ik kijk dan wel of ze al eens in de sessie gezet zijn. Zoniet dan haal ik ze op (in mijn geval uit de db).
creator1988 schreef op maandag 07 september 2009 @ 14:10:
[...]

Je menuitems mappen naar controllers via je mappings in global.asax, dus je doet gewoon <a href="/controllernaam/actie/">. Zoals je ook je normale pagina's zou opbouwen.
Daar heb ik inderdaad ook al aan zitten denken, maar dat zou in mijn implementatie niet altijd goed gaan omdat ik via een regex url's van de vorm /paginanaam/ map naar /controller/actie?parameter=paginanaam. Misschien is dat dan wel weer niet de beste oplossing.

Wellicht is /controller/actie/paginanaam een betere url, die ik vervolgens via regex naar /controller/actie?parameter=paginanaam kan mappen. Dan zou ik kunnen bewerkstelligen wat je voorstelt.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor jullie reacties. Ik heb er naar gekeken en aan zitten denken. Maar zoals jullie het zouden doen, dan wordt het menu toch ge-init op het moment dat je de app opstart en niet wanneer een user inlogt? Ik zou het liefst het menu opslaan in een sessie, maar dan krijg je weer allemaal code in je views om je view object om te zetten in een List<MenuItems>. Of niet?

Acties:
  • 0 Henk 'm!

  • TheNameless
  • Registratie: September 2001
  • Laatst online: 07-02 21:38

TheNameless

Jazzballet is vet!

Verwijderd schreef op maandag 07 september 2009 @ 15:04:
[...]


Daar heb ik inderdaad ook al aan zitten denken, maar dat zou in mijn implementatie niet altijd goed gaan omdat ik via een regex url's van de vorm /paginanaam/ map naar /controller/actie?parameter=paginanaam. Misschien is dat dan wel weer niet de beste oplossing.

Wellicht is /controller/actie/paginanaam een betere url, die ik vervolgens via regex naar /controller/actie?parameter=paginanaam kan mappen. Dan zou ik kunnen bewerkstelligen wat je voorstelt.
Je wilt juist gebruik maken van je routing rules (IMHO) die je aangemaakt hebt tijdens het opstarten van je webapplicatie.
Een manier om van je routevalues een url te genereren is de volgende:
C#:
1
2
3
4
5
6
7
8
9
RequestContext context = new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData());
RouteValueDictionary values = new RouteValueDictionary(
    new { 
        controller = "Controller", action = "Actie", parameter = "paginanaam" 
    }
);
//RouteTable.Routes heb je geinitialiseerd tijdens Application_Start()
VirtualPathData vp = RouteTable.Routes.GetVirtualPath(context, values);
string url = vp.VirtualPath;


Je gebruikt dus op deze manier je zelf gedefinieerde routes en laat de ASP.NET Routing API je URL genereren

[ Voor 3% gewijzigd door TheNameless op 07-09-2009 15:24 ]

Ducati: making mechanics out of riders since 1946


Acties:
  • 0 Henk 'm!

Verwijderd

TheNameless schreef op maandag 07 september 2009 @ 15:21:
[...]

Je wilt juist gebruik maken van je routing rules (IMHO) die je aangemaakt hebt tijdens het opstarten van je webapplicatie.
Een manier om van je routevalues een url te genereren is de volgende:
C#:
1
2
3
4
5
6
7
8
9
RequestContext context = new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData());
RouteValueDictionary values = new RouteValueDictionary(
    new { 
        controller = "Controller", action = "Actie", parameter = "paginanaam" 
    }
);
//RouteTable.Routes heb je geinitialiseerd tijdens Application_Start()
VirtualPathData vp = RouteTable.Routes.GetVirtualPath(context, values);
string url = vp.VirtualPath;


Je gebruikt dus op deze manier je zelf gedefinieerde routes en laat de ASP.NET Routing API je URL genereren
Het lukt me wel om de routing te laten gebeuren (overigens werk ik nog met Monorail en eigenlijk stiekem niet met ASP.NET MVC, detail :) ) door mijn regexs te definieren. Maar ik ik gebruik nu voor 'mooie' urls de paginanaam op de plaats van de controller naam, dus dan raakt de routingmodule in de war.

Stel je hebt: /welkom/1/ is pagina 1 van welkom, maar je hebt ook /controllerx/actie1, dan gaat de routingmodule in mijn geval controllerx interpreteren als paginanaam en naar de pagina controller routen terwijl ik in dit geval naar een controller wil routen. Mijn opzet is dus niet handig :)

Overigens wil ik hiermee nu niet het probleem van de TS onder laten sneeuwen en kan ik hiervoor beter een apart topic openen als ik er niet uitkom. Mijn excuses :o

@TS: Ik haal het menu op mbv lazy loading, maar dat gebeurt idd als de app start. Ik zou zeggen dat dat ook in jou geval niet zo'n probleem is? Je kunt toch ook na het inloggen van de gebruiker menu items laten zien die alleen user specifiek zijn? Overigens denk ik dat ik in mijn geval me niet echt strak aan de MVC structuur houdt, ik ga idd in eigen ViewControls mijn collectie menu items uitlezen en hier li's en lu's van maken.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik zit net nog een beetje te lezen in ASP.NET MVC framework unleashed. Daarin wordt goed uitgelegd hoe je met View User Controls en Master pages moet werken. Het zou ideaal zijn als ik op een manier kon zeggen dat een child page of user control net zo lang blijft bestaan tot een user uitlogt.
Pagina: 1