2012-04-13 1 views
0

Wir verwenden ein benutzerfreundliches URL-Routenschema. Grundsätzlich kann eine Kombination aus Principal Identity und einem freundlichen Namen verwendet werden, die intern auf eine Identität abgebildet werden kann (Person ID). So eine Route wie folgt aus:Bereitstellung einer ID für viele Teilansichten aus einer übergeordneten Ansicht, ohne dass die sensiblen IDs offengelegt werden

routes.MapRoute(string.Empty, "{friendlyname}/Products/{action}", new {controller = "Products", action = "List"}); 

wie diese zu einer URL Karte Würde:

Adam/Products/List 

Das alles funktioniert gut und abstrahiert die interne ID der benannten Person entfernt, die auch benötigt wird.

Das Problem ist, unsere Ansichten bestehen aus vielen Teilansichten. Wenn sie mit der Methode @ Html.Action gerendert werden, benötigen sie letztendlich die PersonID, aber von der URL haben wir nur den 'Anzeigenamen'.

Ich habe für eine Weile darüber nachgedacht und es gibt zwei Lösungen meiner Meinung nach:

  1. Übergeben Sie den ‚freundlichen Namen‘ in jedem der Controller-Aktion Methoden, die die Teilansichten und intern die Methode zurückgeben muss einen Blick auf die aktuell angemeldete Identität und den angezeigten Namen werfen. Dies wird mir die PersonID geben und ich kann dann effizient abfragen. Das einzige Problem bei dieser Vorgehensweise besteht darin, dass ich aufgrund der verschiedenen Teilansichten den aktuell angemeldeten Identitäts- und Anzeigenamen für jeden Teilansichtsaufruf abfragen werde, der innefficeint ist, und ich denke, ich sollte diesen Code nur einmal schreiben müssen.

  2. Irgendwie Abfrage in der Ansicht und erhalten die PersonID, so dass es auf jeden @ Html.Action Aufruf übergeben werden kann, so dass die partiellen View-Controller-Methoden müssen nicht selbst suchen Runden Rundreisen in die Datenbank für die gemeinsame zu speichern information. Das Problem dabei ist, dass ich mir nicht sicher bin, wie ich das sauber machen kann, wenn ich die DI verwende, die wir für den Rest der Anwendung verwenden.

Alle Gedanken zur Annäherung an würde sehr geschätzt werden.

Danke,

Adam

Antwort

1

Sie die Id es mit in den Ansichten von den Session-Variablen und Zugriff hinzufügen könnte:

@{var personId = int.Parse(Session["PersonId"])} 

Dann können Sie es direkt passieren zu Teilansichten vom Elternteil, ohne dass es den Client trifft oder Parameter an irgendwelche Controller übergeben muss.

aktualisieren

Sie auch die Session-Variablen aus der Steuerung zugreifen können, wenn Sie die Arbeit dort statt, ohne Roundtripping in der Datenbank tun wollte.

EDIT

Wenn Sie die Eigenschaft in einem Modell setzen und übergeben es an einer Seite, die Rückseite der Post dann wird nicht das Modell zwischen den Pfosten bestehen bleiben.

Wenn zum Beispiel der Controller funktioniert:

[HttpPost] 
public ActionResult DoSomething(ViewModel model) 
{ 
    if(ModelState.IsValid) 
    { 
     // Logic Here 
    } 
    return View(model) 
} 

, wenn die Seite neu geladen wird, wird das Modell über die ID vergessen haben.

Es gibt eine Reihe von Möglichkeiten. Entweder verwenden Sie @ Html.HiddenFor (m => m.ID) , was die Eigenschaft in den gerenderten HTML-Code einfügt, der, wenn es wirklich eine sensible Information ist, schlecht ist.

Oder Sie können das Ansichtsmodell bei jedem nachfolgenden Postback neu erstellen.

this helps

+0

Hallo Marc. Danke für Ihre Antwort. Ich habe es gerade mit dem Modell herausgefunden. Ich werde die Antwort jetzt posten. – Adam

+0

Ok, anscheinend kann ich nicht für weitere 8 Stunden antworten. Ich werde aktualisieren, wenn ich darf. – Adam

+0

Ich werde meine Antwort mit dem aktualisieren, von dem ich annehme, dass Sie es tun werden, aber mit ein paar Fallen bemerkt. –

0

Als Marc Staaten könnte ich Ihnen die Session damit umgehen, aber ich habe mit der Verwendung des Modells gegangen, wie er in seinem Update ausgeführt hat. Wenn die übergeordnete View-Controller-Aktion den angezeigten Namen annimmt, kann sie die Suche durchführen, die PersonID in das Modell einfügen und dann können alle partiellen Renderer den Modellwert in der Ansicht der übergeordneten View-Controller-Aktion an sie übergeben. Ein Beispiel ist unten dargestellt (dies ist Code Demo, aber es wird hoffentlich den Punkt herüber, ich würde nie einen statischen Datenkontext in echtem Code)

Heimsteuerung

public class HomeController : Controller 
{ 
    public ActionResult Index(string friendlyName) 
    { 
     int pupilId = Data.People.Single(x => x.Name == friendlyName).PersonId; 
     HomeIndexViewModel homeIndexViewModel = new HomeIndexViewModel {PupilId = pupilId}; 

     return View(homeIndexViewModel); 
    } 
} 

Startseite Übersicht

@model SharingInformationBetweenPartials.Web.Models.HomeIndexViewModel 
@{ 
    ViewBag.Title = "Index"; 
} 
<h2>Index</h2>  
@Html.Action("DisplayPersonDetail", "Person", new {Model.PersonId}) 

DisplayPersonDetail die Methode des PersonController können die entsprechenden Daten dann präsentieren sie das in PersonId geben wünscht ein:

public class PupilController : Controller 
{ 
    [ChildActionOnly] 
    public ActionResult DisplayPupilDetail(int pupilId) 
    { 
     Person person = Data.People.Single(x => x.PersonId == pupilId); 
     return View(person); 
    } 
} 

Ich habe versucht, was ich dachte, war dies vorher, aber ich muss etwas falsch gemacht haben, wie die ViewModels Eigenschaften wurden in der URL angezeigt, was ist, was ich versuchte wegzukommen. Wie auch immer, ich hoffe, das hilft jedem anderen, der etwas Ähnliches machen möchte. Wenn Sie Fragen haben, lassen Sie es mich wissen.

Danke,

Adam

0

Sie können [Bind] die genauen Eigenschaften ein Modell Bindemittel in der Bindung oder verwenden Exclude Parameter auf das Attribut enthalten sollte auszuschließen PersonId

[HttpPost] 
public ActionResult EditPerson([Bind(Exclude = "PersonId")] Person person) 
{ 
    //do domething 
} 
angeben Attribut verwenden, um

Sie können auch das Attribut [ReadOnly] verwenden, das der Modellbinder verstehen und nicht dieser Eigenschaft zuweisen wird.

Der beste Ansatz besteht jedoch darin, separate ViewModels zu verwenden: eines zum Anzeigen und eines zum Bearbeiten.

public abstract class Person 
{ 
    public string Name { get; set; } 
    public string Surname { get; set; } 

} 

public class PersonCreateVM : Person 
{ 
    //no PersonId here 
} 

public class PersonEditVM : Person 
{ 
    public int PersonId{ get; set; } 
} 

Dieser Ansatz ist vielleicht ein „Overkill“, aber wenn sie richtig und mit AutoMapper verwendet http://automapper.codeplex.com/ ist es eine Leichtigkeit, mit zu arbeiten.

Verwandte Themen