Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #Code and problem explanation on:
- http://stackoverflow.com/questions/32896475/c-sharp-mvc-routing-with-routebase
- http://stackoverflow.com/questions/33924366/c-sharp-mvc-routebase-routing-too-many-redirects
- #ATTENTION: slidingExpiration is 0 for testing purposes, for production use another value, i would suggest 30 minutes
- /// <summary>
- /// Example of the implementation of the Clone method, it has to be used with the cache to prevent changes on the value
- /// with reference on the cache
- /// </summary>
- public partial class Page : ICloneable
- {
- public object Clone()
- {
- var clonePage = (Page)MemberwiseClone();
- return clonePage;
- }
- }
- public class PageInfo
- {
- public int Id { get; set; }
- public Redirect Redirect { get; set; }
- public Page Page { get; set; }
- public string VirtualPath { get; set; }
- public string Action { get; set; }
- }
- public sealed class CacheList<T> where T : ICloneable
- {
- private static List<T> _dataList = new List<T>();
- /// <summary>
- /// Add a list of items to the internal list
- /// </summary>
- /// <param name="item">List of items do be cached</param>
- public static void Add( List<T> item )
- {
- _dataList.AddRange( item );
- }
- /// <summary>
- /// Cache the items on the internal list
- /// </summary>
- /// <param name="cacheKey">Key of the cache</param>
- public static void CacheIt( string cacheKey )
- {
- IList<T> clone = HelperMethods.CloneList<T>( _dataList );
- HttpRuntime.Cache.Insert(
- key : cacheKey,
- value : clone,
- dependencies : null,
- absoluteExpiration: DateTime.UtcNow.AddMinutes( 10 ),
- slidingExpiration : Cache.NoSlidingExpiration,
- priority : CacheItemPriority.NotRemovable,
- onRemoveCallback : null
- );
- }
- /// <summary>
- /// Load the items from the cache to the internal list
- /// </summary>
- /// <param name="cacheKey">Key of the cache</param>
- /// <returns></returns>
- public static bool LoadCached( string cacheKey )
- {
- var obj = HttpRuntime.Cache[cacheKey];
- if( obj == null || !( obj is List<T> ) ) return false;
- _dataList = HelperMethods.CloneList<T>( (List<T>)obj );
- return true;
- }
- /// <summary>
- /// Return the internal list of items
- /// </summary>
- public static List<T> DataList
- {
- get { return _dataList; }
- }
- }
- public class CustomPageRoute : RouteBase
- {
- private readonly object wslock = new object();
- private readonly object hslock = new object();
- public override RouteData GetRouteData( HttpContextBase httpContext )
- {
- var path = httpContext.Request.Path.TrimStart( '/' ).TrimEnd( '/' ).Split( '/' ).ToList();
- if( httpContext.Request.HttpMethod == "POST" ) return null;
- var pages = DataRepository.GetPageList( httpContext, wslock ).ToList();
- var page = RouteGetter.GetRouteInfo( pages, path, httpContext );
- if( page == null ) return null;
- var result = new RouteData( this, new MvcRouteHandler() );
- result.DataTokens["namespaces"] = new [] { "Site.Controllers" };
- result.Values["controller"] = page.Redirect.controller;
- result.Values["action"] = page.Action;
- 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 = DataRepository.GetPageList( requestContext.HttpContext, wslock ).ToList();
- 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 )
- {
- 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.
- page = pages.FirstOrDefault( x => x.Redirect.controller.Equals( controller ) && x.Action.Equals( action ) );
- if( page != null )
- {
- return true;
- }
- return false;
- }
- }
- public static PageInfo GetRouteInfo( List<PageInfo> pageList, List<string> path, HttpContextBase httpContext )
- {
- var page = BuscaURLWS( pageList, path );
- if( page != null )
- {
- if( page.Pagina != null )
- {
- if( page.Pagina.redirect == 1 )
- {
- httpContext.Response.Redirect( page.Pagina.redirectURL );
- httpContext.Response.End();
- }
- }
- }
- if( page == null || "NaoEncontrado".Equals( page.Redirect.controller ))
- {
- page = pageList.First( x => x.Redirect.controller == "NaoEncontrado" );
- page.Action = "Index";
- return page;
- }
- return page;
- }
- /// <summary>
- /// Get route information by URL (WebSite)
- /// </summary>
- /// <param name="pageList">List of pages</param>
- /// <param name="pUrl">Actual URL</param>
- /// <returns>Route information</returns>
- public static PageInfo BuscaURLWS( List<PageInfo> pageList, List<string> pUrl )
- {
- PageInfo freakingPage = null;
- var splitUrl = pUrl;
- if( splitUrl.Count > 1 )
- {
- if( splitUrl.Count == 2 && "appointment".Equals( splitUrl[1] ) || "conclusion".Equals( splitUrl[1] ) )
- {
- var tPage = pageList.FirstOrDefault( x => x.Redirect.url.Equals( splitUrl[0] ) );
- if( tPage == null ) return null;
- if( tPage.Redirect.landPageId > 0 )
- {
- freakingPage = pageList.FirstOrDefault( x => x.Redirect.url == splitUrl[0] && "LandingPage".Equals( x.Redirect.controller ) );
- }
- else
- {
- freakingPage = pageList.FirstOrDefault( x => x.Redirect.url == splitUrl[1] && "QueroDesconto".Equals( x.Redirect.controller ) );
- }
- if( freakingPage != null )
- {
- freakingPage.Action = splitUrl[1];
- }
- }
- else if( splitUrl.Count == 2 && "voucher".Equals( splitUrl[1] ) )
- {
- freakingPage = pageList.FirstOrDefault( x => x.Redirect.url == splitUrl[0] );
- if( freakingPage != null )
- {
- freakingPage.Redirect.controller = "Voucher";
- freakingPage.Action = "Index";
- }
- }
- }
- else
- {
- freakingPage = pageList.FirstOrDefault( x => x.VirtualPath == splitUrl[0] );
- }
- return freakingPage;
- }
- /// <summary>
- /// Get DB routes for the website and create cache
- /// </summary>
- /// <param name="httpContext">Executing HTTP Context</param>
- /// <param name="wslock">Lock object</param>
- /// <returns>List of routes</returns>
- public static List<PageInfo> GetPageList( HttpContextBase httpContext, object wslock )
- {
- List<PageInfo> pages;
- const string key = "WSRouteCache";
- CacheList<PageInfo>.LoadCached( key );
- if( CacheList<PageInfo>.LoadCached( key ) )
- {
- return CacheList<PageInfo>.DataList;
- }
- lock( wslock )
- {
- using( var db = new Site() )
- {
- var dbPages = db.Pagina;
- var lPages = dbPages.ToArray();
- var wsPages = ( from redirect in db.Redirect
- join page in dbPages on redirect.paginaId equals page.ID into data
- from subData in data.DefaultIfEmpty()
- select new PageInfo { VirtualPath = redirect.url, Redirect = redirect, Pagina = subData, Action = subData.action ?? "Index" } ).ToList();
- var hsPages = ( from redirect in dbHS.HS_Redirect
- select new { VirtualPath = redirect.url, Redirect = redirect } ).ToArray();
- var hsFPages = ( from x in hsPages
- join page in lPages on x.Redirect.paginaId equals page.ID into data
- from subData in data.DefaultIfEmpty()
- select new
- {
- VP = x.Redirect.url,
- Redir = x.Redirect,
- Action = subData == null ? "Index" : subData.action
- } ).AsEnumerable().Select( x =>
- new PageInfo
- {
- VirtualPath = x.VP,
- Redirect = x.Redir,
- Action = x.Action
- } ).ToList();
- wsPages.AddRange( hsFPages );
- pages = wsPages;
- }
- CacheList<PageInfo>.Add( pages );
- CacheList<PageInfo>.CacheIt( key );
- }
- return pages;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement