2016-07-11 8 views
2

Ich muss eine Routing-Mechanik bieten, wo die Routen zur Laufzeit aus Benutzerkonten erstellt werden. Wie http://mysite/username/home.Dynamisches Routing in ASP.Net Core

Ich nehme an, dass dies über Routing getan werden kann, aber ich bin nicht sicher, wo ich mit ASP.Net Core beginnen soll. Ich habe einige Beispiele online für MVC 5 gesehen, aber ASP.Net Core scheint das Routing ein wenig anders zu handhaben. Wie kann ich sicherstellen, dass die Website nicht zwischen http://mysite/username/news als benutzerdefinierte Zielseite des Nutzers und http://mysite/news als Website-News-Seite verwechselt wird?

+0

Sie cab diese lösen durch Routing nach rechts. Zum Beispiel hätten Sie eine Route in Ihrem Controller von [Route ("{username}/news")], die sich von der anderen Route ["news"] unterscheidet. Macht das Sinn oder habe ich es falsch verstanden? –

+0

Ich wusste nicht, dass du '{username}' benutzen kannst. Behandelt asp.net core das, indem es die Identität betrachtet? Was passiert, wenn "http: // mysite/johndoe/news" eine öffentlich zugängliche URL ist, sodass jeder, der nicht authentifiziert ist, es betreten darf? –

+0

Entschuldigung, ich meine, du hast das als Parameter auf deiner Route und redirect entsprechend. Das macht Sinn? –

Antwort

2

Ich bin mir nicht sicher, ob der folgende Weg richtig ist. Es funktioniert für mich, aber Sie sollten es für Ihre Szenarien testen.

zuerst einen Benutzerdienst erstellen überprüfen Benutzername:

public interface IUserService 
{ 
    bool IsExists(string value); 
} 

public class UserService : IUserService 
{ 
    public bool IsExists(string value) 
    { 
     // your implementation 
    } 
} 
// register it 
services.AddScoped<IUserService, UserService>(); 

Dann Route Beschränkung für Benutzernamen erstellen:

public class UserNameRouteConstraint : IRouteConstraint 
{ 
    public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     // check nulls 
     object value; 
     if (values.TryGetValue(routeKey, out value) && value != null) 
     { 
      var userService = httpContext.RequestServices.GetService<IUserService>(); 
      return userService.IsExists(Convert.ToString(value)); 
     } 

     return false; 
    } 
} 

// service configuration 
services.Configure<RouteOptions>(options => 
      options.ConstraintMap.Add("username", typeof(UserNameRouteConstraint))); 

Schließlich Route und Controller schreiben:

app.UseMvc(routes => 
{ 
    routes.MapRoute("default", 
     "{controller}/{action}/{id?}", 
     new { controller = "Home", action = "Index" }, 
     new { controller = @"^(?!User).*$" }// exclude user controller 
    ); 

    routes.MapRoute("user", 
     "{username:username}/{action=Index}", 
     new { controller = "User" }, 
     new { controller = @"User" }// only work user controller 
    ); 
}); 

public class UserController : Controller 
{ 
    public IActionResult Index() 
    { 
     // 
    } 
    public IActionResult News() 
    { 
     // 
    } 
} 

public class NewsController : Controller 
{ 
    public IActionResult Index() 
    { 
     // 
    } 
} 
+1

Ich weiß, dass die Reihenfolge wichtig ist, in der ich die Routen platziere, also frage ich mich, was passiert, wenn es einen Benutzernamen namens "Nachrichten" gibt, der mit meiner "Nachrichten" Controller-Aktionsroute kollidieren würde. Wenn der Standard-Routing-Inhalt zuerst platziert wird, wird der Benutzer "News" ignoriert, da eine "News" -Controller-Aktion existiert. Sollte ich versuchen, zuerst zu einem Benutzer "Domain" zu routen, bevor Sie meine Standardeinstellungen treffen? –

+0

Wenn Sie die Reihenfolge der Routen ändern, würde in diesem Fall die '' Nachrichten''-Controller-Route ignoriert und die 'UserService.Exists'-Methode würde für alle Anfragen aufgerufen (auch wenn dies nicht erforderlich ist). Ich denke, du solltest mit Konflikten sowieso umgehen. Die Verwendung von "reservierten Benutzernamen" erscheint sinnvoll. –