5

Tôi đang cố gắng xây dựng các cm nhỏ của riêng mình. Tôi đã tạo một lớp pageBase trừu tượng được kế thừa bởi Static, Reviews, Articles, News. Mỗi có phương pháp điều khiển riêng.Nhiều cấp độ trong định tuyến tùy chỉnh MVC

Vấn đề của tôi là tôi cần cho phép quản trị viên xác định cấp đường dẫn tùy chỉnh của riêng mình. Ví dụ. news\local\mynewdog hoặc Articles\events\conventions\mycon. Vì vậy, tôi muốn một cách để vượt qua một mảng các chuỗi và cũng có thể thiết lập định tuyến tùy chỉnh.

+0

nghĩ có thể được gần gũi với những gì bạn đang tìm kiếm http://stackoverflow.com/questions/16026441/dynamic-routes-from-database-for-asp-net-mvc-cms – timothyclifford

+0

http://stackoverflow.com/questions/42250306/asp-net-mvc-custom-route-url-at-variable-controller-or-action-name – Abhay

Trả lời

8

Bạn có thể làm điều này liền mạch với lớp con tùy chỉnh RouteBase.

public class PageInfo 
{ 
    // VirtualPath should not have a leading slash 
    // example: events/conventions/mycon 
    public string VirtualPath { get; set; } 
    public Guid Id { get; set; } 
} 

public class CustomPageRoute 
    : RouteBase 
{ 
    private object synclock = new object(); 

    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
     RouteData result = null; 

     // Trim the leading slash 
     var path = httpContext.Request.Path.Substring(1); 

     // Get the page that matches. 
     var page = GetPageList(httpContext) 
      .Where(x => x.VirtualPath.Equals(path)) 
      .FirstOrDefault(); 

     if (page != null) 
     { 
      result = new RouteData(this, new MvcRouteHandler()); 

      // Optional - make query string values into route values. 
      this.AddQueryStringParametersToRouteData(result, httpContext); 

      // TODO: You might want to use the page object (from the database) to 
      // get both the controller and action, and possibly even an area. 
      // Alternatively, you could create a route for each table and hard-code 
      // this information. 
      result.Values["controller"] = "CustomPage"; 
      result.Values["action"] = "Details"; 

      // This will be the primary key of the database row. 
      // It might be an integer or a GUID. 
      result.Values["id"] = page.Id; 
     } 

     // IMPORTANT: Always return null if there is no match. 
     // This tells .NET routing to check the next route that is registered. 
     return result; 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
     VirtualPathData result = null; 

     PageInfo page = null; 

     // Get all of the pages from the cache. 
     var pages = GetPageList(requestContext.HttpContext); 

     if (TryFindMatch(pages, values, out page)) 
     { 
      if (!string.IsNullOrEmpty(page.VirtualPath)) 
      { 
       result = new VirtualPathData(this, page.VirtualPath); 
      } 
     } 

     // IMPORTANT: Always return null if there is no match. 
     // This tells .NET routing to check the next route that is registered. 
     return result; 
    } 

    private bool TryFindMatch(IEnumerable<PageInfo> pages, RouteValueDictionary values, out PageInfo page) 
    { 
     page = null; 
     Guid id = Guid.Empty; 

     // This example uses a GUID for an id. If it cannot be parsed, 
     // we just skip it. 
     if (!Guid.TryParse(Convert.ToString(values["id"]), out id)) 
     { 
      return false; 
     } 

     var controller = Convert.ToString(values["controller"]); 
     var action = Convert.ToString(values["action"]); 

     // The logic here should be the inverse of the logic in 
     // GetRouteData(). So, we match the same controller, action, and id. 
     // If we had additional route values there, we would take them all 
     // into consideration during this step. 
     if (action == "Details" && controller == "CustomPage") 
     { 
      page = pages 
       .Where(x => x.Id.Equals(id)) 
       .FirstOrDefault(); 
      if (page != null) 
      { 
       return true; 
      } 
     } 
     return false; 
    } 

    private void AddQueryStringParametersToRouteData(RouteData routeData, HttpContextBase httpContext) 
    { 
     var queryString = httpContext.Request.QueryString; 
     if (queryString.Keys.Count > 0) 
     { 
      foreach (var key in queryString.AllKeys) 
      { 
       routeData.Values[key] = queryString[key]; 
      } 
     } 
    } 

    private IEnumerable<PageInfo> GetPageList(HttpContextBase httpContext) 
    { 
     string key = "__CustomPageList"; 
     var pages = httpContext.Cache[key]; 
     if (pages == null) 
     { 
      lock(synclock) 
      { 
       pages = httpContext.Cache[key]; 
       if (pages == null) 
       { 
        // TODO: Retrieve the list of PageInfo objects from the database here. 
        pages = new List<PageInfo>() 
        { 
         new PageInfo() 
         { 
          Id = new Guid("cfea37e8-657a-43ff-b73c-5df191bad7c9"), 
          VirtualPath = "somecategory/somesubcategory/content1" 
         }, 
         new PageInfo() 
         { 
          Id = new Guid("9a19078b-2d7e-4fc6-ae1d-3e76f8be46e5"), 
          VirtualPath = "somecategory/somesubcategory/content2" 
         }, 
         new PageInfo() 
         { 
          Id = new Guid("31d4ea88-aff3-452d-b1c0-fa5e139dcce5"), 
          VirtualPath = "somecategory/somesubcategory/content3" 
         } 
        }; 

        httpContext.Cache.Insert(
         key: key, 
         value: pages, 
         dependencies: null, 
         absoluteExpiration: System.Web.Caching.Cache.NoAbsoluteExpiration, 
         slidingExpiration: TimeSpan.FromMinutes(15), 
         priority: System.Web.Caching.CacheItemPriority.NotRemovable, 
         onRemoveCallback: null); 
       } 
      } 
     } 

     return (IEnumerable<PageInfo>)pages; 
    } 
} 

Bạn có thể đăng ký tuyến đường với MVC như thế này.

routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

// Case sensitive lowercase URLs are faster. 
// If you want to use case insensitive URLs, you need to 
// adjust the matching code in the `Equals` method of the CustomPageRoute. 
routes.LowercaseUrls = true; 

routes.Add(
    name: "CustomPage", 
    item: new CustomPageRoute()); 

routes.MapRoute(
    name: "Default", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
); 
Các vấn đề liên quan