[ASP MVC3] Terugkerende algemene informatie

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Ik ben bezig met een eerste project met MVC3 en Entity Framework.

Ik heb 1 controller met diverse acties. Ik heb een aantal view models welke door de controller per actie gecreëerd en gevuld worden. Verder een aantal views om de models te presenteren (of bewerken).

Nou wil ik op elke pagina een header met een aantal dynamische gegevens (ingelogde gebruiker, locatie en nog meer). Via de algemene _Layout.cshtml is dit prima te presenteren. Maar hoe kom ik aan de juiste gegevens?

Moet ik elk view model uitbreiden met een property (sub view model) en deze in elke controller actie vullen? Kan dit niet generieker of denk ik verkeerd?

"The shell stopped unexpectedly and Explorer.exe was restarted."


Acties:
  • 0 Henk 'm!

  • Arite
  • Registratie: April 2006
  • Laatst online: 12-06 13:53
Je zou kunnen kijken naar @Html.Action. Hiermee kan je een controller inclusief renderen welke deze informatie bevat.

MSDN: ChildActionExtensions.Action Method (System.Web.Mvc.Html)

Acties:
  • 0 Henk 'm!

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Arite schreef op donderdag 19 januari 2012 @ 10:07:
Je zou kunnen kijken naar @Html.Action. Hiermee kan je een controller inclusief renderen welke deze informatie bevat.

MSDN: ChildActionExtensions.Action Method (System.Web.Mvc.Html)
Ziet er goed uit, maak volgens mij zorgt dit voor extra (HTTP) requests. Dat is toch niet nodig aangezien ik prima alle gegevens in 1x kan ophalen.

Probleem is ook dat je view dan kennis krijgt van je controller.

[ Voor 5% gewijzigd door jelmervos op 19-01-2012 10:09 ]

"The shell stopped unexpectedly and Explorer.exe was restarted."


Acties:
  • 0 Henk 'm!

  • Arite
  • Registratie: April 2006
  • Laatst online: 12-06 13:53
jelmervos schreef op donderdag 19 januari 2012 @ 10:08:
[...]

Ziet er goed uit, maak volgens mij zorgt dit voor extra (HTTP) requests. Dat is toch niet nodig aangezien ik prima alle gegevens in 1x kan ophalen.

Probleem is ook dat je view dan kennis krijgt van je controller.
Dit is allemaal intern, er komen geen extra HTTP requests bij te kijken.

Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 28-02 01:01
Je kan beter een basecontroller /basemodel maken waar je normale controllers van zijn afgeleid. Deze kan je properties meegeven welke je bij de constructor inlaadt.

[ Voor 3% gewijzigd door Megamind op 19-01-2012 10:12 ]


Acties:
  • 0 Henk 'm!

  • cvs79
  • Registratie: April 2002
  • Laatst online: 12:14
Waarom geen partial view die de header teruggeeft steeds (inclusief header controller). Of levert dit zoveel overhead op?

Acties:
  • 0 Henk 'm!

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
cvs79 schreef op donderdag 19 januari 2012 @ 10:50:
Waarom geen partial view die de header teruggeeft steeds (inclusief header controller). Of levert dit zoveel overhead op?
Ik heb het geprobeerd met een partial view, maar hoe komt deze aan zijn gegevens? In principe uit het model welke door de aanroepende view wordt gebruikt. Ik wil liever niet dat elke controller actie alle te tonen data (dus ook algemene/generieke) moet ophalen en in het model zet. Immers moet ik dan ook elk view model uitbreiden met deze algemene gegevens. Dit geeft veel dubbele code.

Ik heb even gezocht en Martin Fowler lost dit op met een Front Controller.
Hier nog een interessant stuk.
Maar ik weet niet of dit ook in MVC3 te implementeren is.

Een base controller lijkt me nog de beste oplossing tot nu toe. Al is overerving duur omdat het maar 1 keer kan. Misschien kan ik hetzelfde bereiken met een custom attribute.

[ Voor 3% gewijzigd door jelmervos op 19-01-2012 11:42 ]

"The shell stopped unexpectedly and Explorer.exe was restarted."


Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 10-06 23:15
Waarom gebruik je geen global action filter die iets in de ViewBag gooit. In combinatie met een partialview.

[ Voor 19% gewijzigd door D-Raven op 19-01-2012 11:51 ]


Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-06 19:14
Verreweg de beste oplossing is al genoemd. Dat is het gebruik van child actions m.b.v. de Html.Action helper.

De gegevens zoals huidige login naam, etc. staan conceptueel los van de gegevens voor de normale pagina actie. Deze wil je dus ook in je code niet gekoppeld hebben. Een child action werkt op een tweede, compleet losstaand (view)model, wat hier perfect in past.

Eerder is genoemd dat je view hierdoor van je controllers af gaat weten. Ja, dat klopt. Ooit Html.ActionLink gebruikt of Url.Action ? Die weten even veel van controllers af. Namelijk: controller naam, action naam en een optionele set argumenten of parameters. Dat is dus een behoorlijk non-argument. Je moet alleen opletten dat je het niet te bont maakt en complete object-graphs gaat mee sturen in de parameters.
(Maar dan zijn je header gegevens ook niet meer een conceptueel losstaande set data...)

Het resultaat van een child action is trouwens los te output-cachen. Als je een high-performance site of applicatie maakt kan dat ook nog wel eens van belang zijn. Verder kan een child action gerust in een compleet andere area staan. Dat kan handig zijn als je site of applicatie zo groot is (of gaat worden) dat de extra opdeling van MVC areas nuttig kan zijn om het overzicht te behouden.


De alternatieven:

Het slechtste alternatief is om alles dynamically typed in de viewbag te gooien. Dat is niet alleen langzaam, maar ook foutgevoeligig. (Geen compile time checks. Geen code completion. Etc.) Verder is het ook compleet niet transparant welke data er dan voor de view beschikbaar is om mee te werken. Niet doen dus.

Een ander alternatief is om al je top level models een interface IHeaderModel o.i.d. te laten implementeren. Dit is weliswaar strongly typed, maar eerder schreef ik al; je wilt deze concepten in code niet gekoppeld hebben zitten. Zeker niet in al je inviduele model classes, zoals met een shared interface het geval zou zijn. Deze oplossing zou dus ook meteen moeten vervallen.
(Even ook een praktisch argument: Dat gaat leuk worden als de set gegevens die in de header staan verandert. Dan kun je door al je models en factories heen gaan om alles bij te werken. Nee dank je....)

Het andere alternatief is een shared base controller. Dat is een variant op het vorige waar de base controller onder de kap een nieuw model opbouwt uit het eigen model en het header model en dit gecombineerde model naar de view door stuurt. Dit breekt de verwachtingen van de programmeur: het type van het model wat hij/zij naar de view stuurt komt niet meer overeen met wat de view aangeleverd krijgt. Slecht idee dus.

Verder kleeft er ook nog het extra risico aan dat je gaandeweg gemakshalve een god class base controller gaat brouwen met nog allerlei andere handigheidjes. Zo hoor je niet met ASP.NET MVC te werken. De insteek van ASP.NET MVC is om te werken met composition en niet complexe inheritance graphs. Via IoC en DI injecteer je providers om je eigen logica te faciliteren en via filters (decorators...) wrap je de lifecycle events van een controller zodat je daar gedrag kunt toevoegen of wijzigen.

Acties:
  • 0 Henk 'm!

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
R4gnax schreef op donderdag 19 januari 2012 @ 13:02:
Verreweg de beste oplossing is al genoemd. Dat is het gebruik van child actions m.b.v. de Html.Action helper.

...
Geïmplementeerd en werkt goed. Over het gebruik van Html.ActionLink heb je gelijk, had ik zo snel niet door. Ondanks dat het niet "netjes" is om vanuit de View terug te verwijzen naar een Controller, is deze oplossing prima.

Helemaal met gebruik van het ChildActionOnlyAttribute, waar bij de Remarks precies staat wat ik bedoel:
A child action method renders inline HTML markup for part of a view instead of rendering a whole view.
Bedankt.

"The shell stopped unexpectedly and Explorer.exe was restarted."


Acties:
  • 0 Henk 'm!

  • Rickets
  • Registratie: Augustus 2001
  • Niet online

Rickets

Finger and a shift

Als je de resulterende HTML-string niet hoeft te bewerken, kan je Html.RenderAction gebruiken in plaats van Html.Action.
The difference between the two is that Html.RenderAction will render the result directly to the Response (which is more efficient if the action returns a large amount of HTML) whereas Html.Action returns a string with the result.

If some cunt can fuck something up, that cunt will pick the worst possible time to fucking fuck it up, because that cunt’s a cunt.


Acties:
  • 0 Henk 'm!

  • YakuzA
  • Registratie: Maart 2001
  • Niet online

YakuzA

Wat denk je nou zelluf hey :X

vaak haal je in je _Layout of _LogOnPartial een gebruikersvariabele uit je sessie waar je naam etc uit kan afleiden.
(HttpContext.Current.Session)

[ Voor 13% gewijzigd door YakuzA op 19-01-2012 15:03 ]

Death smiles at us all, all a man can do is smile back.
PSN


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
D-Raven schreef op donderdag 19 januari 2012 @ 11:50:
Waarom gebruik je geen global action filter die iets in de ViewBag gooit. In combinatie met een partialview.
ViewBag is typisch zo'n feature die slecht gestructureerd programmeren in de hand werkt. R4gnax geeft al het goede antwoord: child actions.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info

Pagina: 1