Advertisement
Terkhos

C# Routing System

Nov 25th, 2015
743
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.73 KB | None | 0 0
  1. #Code and problem explanation on:
  2. http://stackoverflow.com/questions/32896475/c-sharp-mvc-routing-with-routebase
  3. http://stackoverflow.com/questions/33924366/c-sharp-mvc-routebase-routing-too-many-redirects
  4. #ATTENTION: slidingExpiration is 0 for testing purposes, for production use another value, i would suggest 30 minutes
  5.  
  6. /// <summary>
  7. /// Example of the implementation of the Clone method, it has to be used with the cache to prevent changes on the value
  8. /// with reference on the cache
  9. /// </summary>
  10. public partial class Page : ICloneable
  11. {
  12.     public object Clone()
  13.     {
  14.         var clonePage = (Page)MemberwiseClone();
  15.  
  16.         return clonePage;
  17.     }
  18. }
  19.  
  20. public class PageInfo
  21. {
  22.     public int Id { get; set; }
  23.     public Redirect Redirect { get; set; }
  24.     public Page Page { get; set; }
  25.     public string VirtualPath { get; set; }
  26.     public string Action { get; set; }
  27. }
  28.  
  29. public sealed class CacheList<T> where T : ICloneable
  30. {
  31.     private static List<T> _dataList = new List<T>();
  32.  
  33.     /// <summary>
  34.     /// Add a list of items to the internal list
  35.     /// </summary>
  36.     /// <param name="item">List of items do be cached</param>
  37.     public static void Add( List<T> item )
  38.     {
  39.         _dataList.AddRange( item );
  40.     }
  41.  
  42.     /// <summary>
  43.     /// Cache the items on the internal list
  44.     /// </summary>
  45.     /// <param name="cacheKey">Key of the cache</param>
  46.     public static void CacheIt( string cacheKey )
  47.     {
  48.         IList<T> clone = HelperMethods.CloneList<T>( _dataList );
  49.  
  50.         HttpRuntime.Cache.Insert(
  51.             key               : cacheKey,
  52.             value             : clone,
  53.             dependencies      : null,
  54.             absoluteExpiration: DateTime.UtcNow.AddMinutes( 10 ),
  55.             slidingExpiration : Cache.NoSlidingExpiration,
  56.             priority          : CacheItemPriority.NotRemovable,
  57.             onRemoveCallback  : null
  58.         );
  59.     }
  60.  
  61.     /// <summary>
  62.     /// Load the items from the cache to the internal list
  63.     /// </summary>
  64.     /// <param name="cacheKey">Key of the cache</param>
  65.     /// <returns></returns>
  66.     public static bool LoadCached( string cacheKey )
  67.     {
  68.         var obj = HttpRuntime.Cache[cacheKey];
  69.  
  70.         if( obj == null || !( obj is List<T> ) ) return false;
  71.  
  72.         _dataList = HelperMethods.CloneList<T>( (List<T>)obj );
  73.  
  74.         return true;
  75.     }
  76.  
  77.     /// <summary>
  78.     /// Return the internal list of items
  79.     /// </summary>
  80.     public static List<T> DataList
  81.     {
  82.         get { return _dataList; }
  83.     }
  84. }
  85.  
  86. public class CustomPageRoute : RouteBase
  87. {
  88.     private readonly object wslock = new object();
  89.     private readonly object hslock = new object();
  90.  
  91.     public override RouteData GetRouteData( HttpContextBase httpContext )
  92.     {
  93.         var path = httpContext.Request.Path.TrimStart( '/' ).TrimEnd( '/' ).Split( '/' ).ToList();
  94.  
  95.         if( httpContext.Request.HttpMethod == "POST" ) return null;
  96.  
  97.         var pages = DataRepository.GetPageList( httpContext, wslock ).ToList();
  98.         var page  = RouteGetter.GetRouteInfo( pages, path, httpContext );
  99.  
  100.         if( page == null ) return null;
  101.  
  102.         var result = new RouteData( this, new MvcRouteHandler() );
  103.  
  104.         result.DataTokens["namespaces"] = new [] { "Site.Controllers" };
  105.         result.Values["controller"] = page.Redirect.controller;
  106.         result.Values["action"]     = page.Action;
  107.         result.Values["id"]         = page.Id;
  108.  
  109.         // IMPORTANT: Always return null if there is no match.
  110.         // This tells .NET routing to check the next route that is registered.
  111.         return result;
  112.     }
  113.  
  114.     public override VirtualPathData GetVirtualPath( RequestContext requestContext, RouteValueDictionary values )
  115.     {
  116.         VirtualPathData result = null;
  117.         PageInfo page = null;
  118.  
  119.         // Get all of the pages from the cache.
  120.         var pages = DataRepository.GetPageList( requestContext.HttpContext, wslock ).ToList();
  121.  
  122.         if( TryFindMatch( pages, values, out page ) )
  123.         {
  124.             if( !string.IsNullOrEmpty( page.VirtualPath ) )
  125.             {
  126.                 result = new VirtualPathData( this, page.VirtualPath );
  127.             }
  128.         }
  129.  
  130.         // IMPORTANT: Always return null if there is no match.
  131.         // This tells .NET routing to check the next route that is registered.
  132.         return result;
  133.     }
  134.  
  135.     private bool TryFindMatch( IEnumerable<PageInfo> pages, RouteValueDictionary values, out PageInfo page )
  136.     {
  137.         var controller = Convert.ToString( values["controller"] );
  138.         var action     = Convert.ToString( values["action"] );
  139.  
  140.         // The logic here should be the inverse of the logic in
  141.         // GetRouteData(). So, we match the same controller, action, and id.
  142.         // If we had additional route values there, we would take them all
  143.         // into consideration during this step.
  144.         page = pages.FirstOrDefault( x => x.Redirect.controller.Equals( controller ) && x.Action.Equals( action ) );
  145.  
  146.         if( page != null )
  147.         {
  148.             return true;
  149.         }
  150.  
  151.         return false;
  152.     }
  153. }
  154.  
  155. public static PageInfo GetRouteInfo( List<PageInfo> pageList, List<string> path, HttpContextBase httpContext )
  156. {
  157.     var page = BuscaURLWS( pageList, path );
  158.  
  159.     if( page != null )
  160.     {
  161.         if( page.Pagina != null )
  162.         {
  163.             if( page.Pagina.redirect == 1 )
  164.             {
  165.                 httpContext.Response.Redirect( page.Pagina.redirectURL );
  166.                 httpContext.Response.End();
  167.             }
  168.         }
  169.     }
  170.  
  171.     if( page == null || "NaoEncontrado".Equals( page.Redirect.controller ))
  172.     {
  173.         page = pageList.First( x => x.Redirect.controller == "NaoEncontrado" );
  174.         page.Action = "Index";
  175.  
  176.         return page;
  177.     }
  178.  
  179.     return page;
  180. }
  181.  
  182. /// <summary>
  183. /// Get route information by URL (WebSite)
  184. /// </summary>
  185. /// <param name="pageList">List of pages</param>
  186. /// <param name="pUrl">Actual URL</param>
  187. /// <returns>Route information</returns>
  188. public static PageInfo BuscaURLWS( List<PageInfo> pageList, List<string> pUrl )
  189. {
  190.     PageInfo freakingPage = null;
  191.  
  192.     var splitUrl = pUrl;
  193.  
  194.     if( splitUrl.Count > 1 )
  195.     {
  196.         if( splitUrl.Count == 2 && "appointment".Equals( splitUrl[1] ) || "conclusion".Equals( splitUrl[1] ) )
  197.         {
  198.             var tPage = pageList.FirstOrDefault( x => x.Redirect.url.Equals( splitUrl[0] ) );
  199.  
  200.             if( tPage == null ) return null;
  201.  
  202.             if( tPage.Redirect.landPageId > 0 )
  203.             {
  204.                 freakingPage = pageList.FirstOrDefault( x => x.Redirect.url == splitUrl[0] && "LandingPage".Equals( x.Redirect.controller ) );
  205.             }
  206.             else
  207.             {
  208.                 freakingPage = pageList.FirstOrDefault( x => x.Redirect.url == splitUrl[1] && "QueroDesconto".Equals( x.Redirect.controller ) );
  209.             }
  210.  
  211.             if( freakingPage != null )
  212.             {
  213.                 freakingPage.Action = splitUrl[1];
  214.             }
  215.         }
  216.         else if( splitUrl.Count == 2 && "voucher".Equals( splitUrl[1] ) )
  217.         {
  218.             freakingPage = pageList.FirstOrDefault( x => x.Redirect.url == splitUrl[0] );
  219.  
  220.             if( freakingPage != null )
  221.             {
  222.                 freakingPage.Redirect.controller = "Voucher";
  223.                 freakingPage.Action = "Index";
  224.             }
  225.         }
  226.     }
  227.     else
  228.     {
  229.         freakingPage = pageList.FirstOrDefault( x => x.VirtualPath == splitUrl[0] );
  230.     }
  231.  
  232.     return freakingPage;
  233. }
  234.  
  235. /// <summary>
  236. /// Get DB routes for the website and create cache
  237. /// </summary>
  238. /// <param name="httpContext">Executing HTTP Context</param>
  239. /// <param name="wslock">Lock object</param>
  240. /// <returns>List of routes</returns>
  241. public static List<PageInfo> GetPageList( HttpContextBase httpContext, object wslock )
  242. {
  243.     List<PageInfo> pages;
  244.     const string key = "WSRouteCache";
  245.  
  246.     CacheList<PageInfo>.LoadCached( key );
  247.  
  248.     if( CacheList<PageInfo>.LoadCached( key ) )
  249.     {
  250.         return CacheList<PageInfo>.DataList;
  251.     }
  252.  
  253.     lock( wslock )
  254.     {
  255.         using( var db = new Site() )
  256.         {
  257.             var dbPages = db.Pagina;
  258.             var lPages  = dbPages.ToArray();
  259.  
  260.             var wsPages = ( from redirect in db.Redirect
  261.                             join page in dbPages on redirect.paginaId equals page.ID into data
  262.                             from subData in data.DefaultIfEmpty()
  263.                             select new PageInfo { VirtualPath = redirect.url, Redirect = redirect, Pagina = subData, Action = subData.action ?? "Index" } ).ToList();
  264.  
  265.             var hsPages = ( from redirect in dbHS.HS_Redirect
  266.                             select new { VirtualPath = redirect.url, Redirect = redirect } ).ToArray();
  267.  
  268.             var hsFPages = ( from x in hsPages
  269.                              join page in lPages on x.Redirect.paginaId equals page.ID into data
  270.                              from subData in data.DefaultIfEmpty()
  271.                              select new
  272.                              {
  273.                                 VP     = x.Redirect.url,
  274.                                 Redir  = x.Redirect,
  275.                                 Action = subData == null ? "Index" : subData.action
  276.                              } ).AsEnumerable().Select( x =>
  277.                                 new PageInfo
  278.                                 {
  279.                                     VirtualPath = x.VP,
  280.                                     Redirect    = x.Redir,
  281.                                     Action      = x.Action
  282.                                 } ).ToList();
  283.  
  284.             wsPages.AddRange( hsFPages );
  285.  
  286.             pages = wsPages;
  287.         }
  288.  
  289.         CacheList<PageInfo>.Add( pages );
  290.         CacheList<PageInfo>.CacheIt( key );
  291.     }
  292.  
  293.     return pages;
  294. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement