2009-04-21 8 views
1

Wenn ich möchte, dass die Standard-URL meiner Webanwendung je nach Benutzer völlig unterschiedliche Benutzeroberflächen anzeigt, was ist der beste Weg, dies zu erreichen? Ich möchte nicht wirklich den gleichen Controller für jede Art von Benutzer verwenden. Um es anders auszudrücken, wenn ein Benutzer eingeloggt ist und zu http://mysweetapp.com geht und ein Admin-Benutzer ist, sollten sie bekommen, was sie das gleiche sehen würden, als ob sie zu http://mysweetapp.com/admin gegangen wären. Wenn der Benutzer als normaler Benutzer angemeldet ist, sollte er dasselbe sehen, als ob er zu http://mysweetapp.com/normaluserasp.net mvc - dynamischer Controller basierend auf authentifiziertem Benutzer

gegangen wäre. Sollte ich nur einen "Redirect" -Controller als meinen Standard definieren und den Client an den entsprechenden Controller senden lassen ?

routes.MapRoute(
       "Default", 
       "{controller}/{action}/{id}", 
       new { controller = "Redirect", action = "Index", id = "0" }); 

ich auch habe versucht, meine eigenen Controller zu schaffen, aber ich glaube nicht, ich war auf dem Konzept klar und konnte es nicht zur Arbeit kommen.

Dank

Antwort

1

Der sauberste Weg wäre meiner Meinung nach, einen benutzerdefinierten Routen-Handler zu erstellen, der von Ihrer Standardroute verwendet werden kann. Anschließend können Sie den zu verwendenden Controller auswählen, wenn der Name des Controllers Ihr Standard-Controller-Name ist. Im folgenden Beispiel lautet er: Home. Überprüfen Sie dann, ob der Benutzer ein Administrator ist oder nicht und verarbeiten Sie die Anfrage mit dem Controller, den Sie verwenden möchten. Hier

ist der Code:

public class CustomHttpHandler : IHttpHandler 
{ 
    public RequestContext RequestContext { get; private set; } 

    public CustomHttpHandler(RequestContext requestContext) 
    { 
     try 
     { 
      string controllerName = RequestContext.RouteData.GetRequiredString("controller"); 
      if (controllerName.Equals("home", StringComparison.CurrentCultureIgnoreCase)) 
      { 
       bool isAdmin = RequestContext.HttpContext.User.IsInRole("Admin"); 
       controllerName = isAdmin ? "admin" : "normaluser"; 
      } 

      IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory(); 
      IController controller = factory.CreateController(RequestContext, controllerName); 
      if (controller != null) 
      { 
       controller.Execute(RequestContext); 
      } 
     } 
     finally 
     { 
      factory.ReleaseController(controller); 
     } 
    } 
} 

public class CustomRouteHandler : IRouteHandler 
{ 
    public IHttpHandler GetHttpHandler(RequestContext requestContext) 
    { 
     return new CustomHttpHandler(requestContext); 
    } 
} 

// Now use the CustomRouteHandler when you map your default route. 
routes.MapRoute(
    "Default", 
    "{controller}/{action}/{id}", 
    new { controller = "Home", action = "Index", id = "" } 
).RouteHandler = new CustomRouteHandler(); 

Hoffnung, das hilft.

+0

Das sieht nach einer netten Lösung aus, ich werde es versuchen, danke. – JeremyWeir

1

Der Einfachheit halber in Ihrem Homecontroller Index-Methode (oder was auch immer Standard-Controller Sie verwenden) können Sie einen Code wie diese setzen und dann können die Links aus dem AdminIndex Ansicht oder der Indexansicht, die die Benutzer senden entsprechende Bereiche, wenn sie beginnen, auf Ihrer Website zu navigieren - auf diese Weise haben Sie einen gemeinsamen Controller und die anderen Controller können für den Benutzertyp spezifisch sein.

return user.IsAdministrator ? View("AdminIndex") : View("Index"); 

der user.IsAdministrator Aufruf ist Pseudo-Code natürlich - ersetzen diese mit dem, was Methode Sie verwenden, um herauszufinden, ob der Benutzer ein Benutzer admin ist

+0

die ein wenig zu einfach ist, glaube ich, müssen die Ansichten Modelle bereit, die völlig unterschiedlich sind, weshalb ich denke, verschiedene Controller geeignet ist. Aber was Sie vorschlagen, könnte sein, was ich gerade mache, indem ich Ihre View() s mit RedirectToRoute() s ausschalte. – JeremyWeir

+0

Ja, dann könnte eine Weiterleitung eine bessere Option sein, wenn die Modelle sehr unterschiedlich sind. –

0

Was Sie vielleicht, um Bereiche zu betrachten. Dies würde Ihnen ermöglichen, separate Controller für jeden Bereich zu haben. Dann erlauben Sie Zugang zu diesen Bereichen basierend auf Rollen oder was auch immer Sie wünschen. Dies gibt Ihnen Routen wie '/ admin/controller/action', '/ users/controller/action' usw. Das 'Muster' trennt alle Ihre Controller nach Namespace und behandelt das Routing sehr gut. Separate Masterseiten leicht, etc.

Es gibt Ihnen nicht die (möglicherweise verwirrend, IMO) "/" und "/ admin /", die für einen Admin-Benutzer gleich aussehen, aber es wird Ihnen den Inhalt trennen und Controller.

Was Sie beschreiben, würde zu potenziell Tonnen von Methoden für jeden Controller führen, was im Allgemeinen von der MVC/REST-Crowd verpönt ist. Es ist nicht schrecklich, aber es gilt auch nicht als Best Practice.

Sie können über Bereiche in diesem Blog here lesen. Google "asp.net mvc Bereiche" für mehr.

-------- ----------- bearbeiten

ein wenig zu erweitern:

Ohne eigene Routen oder einige andere Spielereien sind Aktionen Controller zugeordnet durch die URL. Wenn Sie also alle Admin-Aktionen und -Ansichten anders als in der Root-URL beibehalten möchten, würde dies zusammen mit normalen Benutzeraktionen zu einem großen Controller führen, der alle diese Aktionen oder einige seltsame "wenn diese Rolle, diese Ansicht Wenn diese Rolle, diese Sichtweise "Art von Unsinn, der in jeder Aktion passieren müsste. Eine Art Chaos, um potentiell zu debuggen.

In ähnlicher Weise findet die Standardansichts-Engine die Ansichten basierend auf der URL.

Dies würde bedeuten, dass alle Ihre Ansichten in einem großen hässlichen Verzeichnis voller allerlei seltsamen, ähnlich benannten, aber sich anders verhaltenden Ansichten sitzen.

Kurz gesagt, dies würde je nach Komplexität der Anwendung zu einem potenziell schrecklichen Wartungsalarm werden.

+0

Könnten Sie erklären, warum Sie sagen: "Was Sie beschreiben, würde zu potenziell vielen Methoden für jeden Controller führen" und was wäre eine Alternative? – JeremyWeir

+0

Ist die Bearbeitung ein bisschen hilfreicher? –

+0

Verstanden, im Grunde, was Sie sagen, ist die Verwendung der Standard-Controller/Viewname Verhalten, gibt es keine gute Möglichkeit, um die URL sauber zu halten. – JeremyWeir

0

Wenn Sie nicht den gleichen Controller verwenden möchten, richten Sie zuerst für jedes Element eigene Controller und Ansichten ein - mysweetapp.com/admin und mysweetapp.com/normaluser.

Sie können dann bestimmte Benutzer basierend auf ihrer angemeldeten Rolle über einen Standardcontroller auf diese Seite umleiten.

if (User.IsInRole("Admin") 
      { 
       return RedirectToAction("Index", "admin"); 
      } 
      else if (User.IsInRole("Standard") 
      { 
       return RedirectToAction("Index", "normaluser"); 
      } 
+0

Das war auch mein erster Gedanke, ich dachte nur, dass es eine Standardmethode geben könnte, dies mit Routen oder so zu tun. – JeremyWeir

0

Konnten Sie eine Klasse erstellen, die sich von DefaultControllerFactory erweitert und CreateController überschreibt?

public class RedirectControllerFactory : DefaultControllerFactory 
{ 
    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) 
    { 
     if (controllerName.Equals("Redirect")) 
     { 
      controllerName = requestContext.HttpContext.User.IsInRole("Admin") ? "Admin" : "NormalUser"; 
     } 
     return base.CreateController(requestContext, controllerName); 
    } 
} 

Dann in Ihrem Application_Start():

protected void Application_Start() 
{ 
    // ... 
    ControllerBuilder.Current.SetControllerFactory(new RedirectControllerFactory()); 
} 
Verwandte Themen