C# MVC Routing With RouteBase

本文关键字:RouteBase With Routing MVC | 更新日期: 2023-09-27 18:15:48

我有一个自定义路由系统在我的web应用程序,我有一个数据库与我的路由(url, Controller, Action和一些更多的信息)。向服务器发出的每个请求都进入数据库,通过url查询该路由并返回一组我需要为未来渲染Filter, ControllerView保持可访问性的内容,我将此数据保存在全局变量中。asax文件:

public static class GlobalVars
{
    public static Redirect reqContext { get; set; }
    public static UnidadeHotSite HotSite { get; set; }
}

我的问题是,现在这个信息是通过用户混合,有时当我在我的浏览器,我有3个打开的选项卡,我刷新他们在"几乎"同一时间,最后一个将获得前一个加载的路由数据。

例如,我的HotSite var保留了一些子网站信息,如name, url, ID等,子网站的url将是:abc.com/subsite。当我加载第一个选项卡时,我得到正确的数据,这是子网站数据,第二个选项卡是离开子网站区域,abc.com,我得到与最后加载的选项卡相同的数据。

现在,问题是什么呢?我已经在OutputCache上使用了NoStore,并试图禁用会话,但似乎没有任何工作。

这是我的路由处理器:

[OutputCache( NoStore = true, Duration = 0 )]
public class RouteHandler : MvcRouteHandler
{
    private static string RedirectAction { get; set; }
    private static string UnidadeURL { get; set; }
    protected override IHttpHandler GetHttpHandler( RequestContext requestContext )
    {
        var friendlyUrl = (string)requestContext.RouteData.Values["RedirectUrl"];
        var objRet      = BuscaURL( friendlyUrl, requestContext );
        GlobalVars.reqContext = objRet[0] as Redirect;
        return base.GetHttpHandler(objRet[1] as RequestContext);
    }
    private static object[] BuscaURL( string pURL, RequestContext reqContext )
    {
        RedirectAction = "Index";
        var isHotSite  = BuscaHotSiteInfo( pURL );
        var tRedirect = !isHotSite ? BuscaURLWS( pURL ) : BuscaURLHS( pURL );
        if( tRedirect == null || "NotFound".Equals( tRedirect.controller ) )
        {
            Configuracoes.GeraLog( "pURL", pURL );
            if(tRedirect == null)
                Configuracoes.GeraLog( "tRedirect", "NULL" );
            else
                HelperController.GeraLog( tRedirect );
            tRedirect      = RedirectController.BuscaPaginaPorUrlWS( 5 );
            RedirectAction = "Index";
            reqContext.RouteData.DataTokens["Namespaces"] = "Site.Controllers";
        }
        if( tRedirect != null && tRedirect.paginaId > 0 && RedirectAction == "Index" )
        {
            using( var db = new SkillSite() )
            {
                var pagina = db.Pagina.First( x => x.ID == tRedirect.paginaId && x.ativo == 1 );
                RedirectAction = pagina.action;
            }
        }
        reqContext.RouteData.Values["controller"] = tRedirect.controller;
        reqContext.RouteData.Values["action"]     = RedirectAction;
        reqContext.RouteData.Values["id"]         = tRedirect.ID;
        return new object[] { tRedirect, reqContext };
    }
    private static Redirect BuscaURLHS( string pUrl )
    {
        Redirect redirect = null;
        pUrl = pUrl.Replace( UnidadeURL, "" ).Replace( "teste", "" ).TrimStart( '/' ).TrimEnd( '/' );
        if( !string.IsNullOrEmpty( pUrl ) && !string.IsNullOrWhiteSpace( pUrl ) )
        {
            var splitUrl = pUrl.Split( '/' ).ToList();
            if( splitUrl.Count > 1 )
            {
                if( "cursos".Equals( splitUrl[0] ) )
                {
                    if( splitUrl.Count == 2 )
                    {
                        redirect = RedirectController.SearchPageByUrlWS( 1, splitUrl[1] );
                    }
                    else if( splitUrl.Count == 3 )
                    {
                        redirect = RedirectController.SearchPageByUrlWS( 2, splitUrl[1], splitUrl[2] );
                    }
                }
            }
            else
            {
                redirect = RedirectController.SearchPageByUrlWS( 0, "", "", splitUrl[0] );
            }
        }
        else
        {
            redirect = RedirectController.SearchPageByUrlWS( 0, "", "", "home" );
        }
        return redirect;
    }
    private static Redirect BuscaURLWS( string pUrl )
    {
        Redirect redirect = null;
        if( !string.IsNullOrEmpty( pUrl ) && !string.IsNullOrWhiteSpace( pUrl ) )
        {
            var splitUrl = pUrl.TrimEnd( '/' ).Split( '/' ).ToList();
            if( splitUrl.Count > 1 )
            {
                if( "cursos".Equals( splitUrl[0] ) )
                {
                    if( splitUrl.Count == 2 )
                    {
                        redirect = RedirectController.SearchPageByUrlHS( 1, splitUrl[1] );
                    }
                    else if( splitUrl.Count == 3 )
                    {
                        redirect = RedirectController.SearchPageByUrlHS( 2, splitUrl[1], splitUrl[2] );
                    }
                }
            }
            else
            {
                redirect = RedirectController.SearchPageByUrlHS( 0, "", "", splitUrl[0] );
            }
        }
        else
        {
            redirect = RedirectController.SearchPageByUrlHS( 0, "", "", "home" );
        }
        return redirect;
    }
}

这是在DB

上进行搜索的控制器
[OutputCache( NoStore = true, Duration = 0 )]
public class RedirectController
{
    public static Redirect SearchPageByUrlWS( int tipo, string cursoCURL = "", string cursoURL = "", string redirectURL = "", string redirectURLTwo = "" )
    {
        using( var db = new Site() )
        {
            IQueryable<Redirect> redirects;
            if( tipo == 1 )
            {
                redirects = from redirect in db.Redirect
                            where redirect.url == cursoCURL && redirect.cursoCatId > 0
                            select redirect;
            }
            else
            {
                redirects = from redirect in db.Redirect
                            where redirect.url == redirectURL &&
                            redirect.cursoCatId == 0 &&
                            redirect.regulamentoId == 0 &&
                            redirect.noticiaId == 0 &&
                            redirect.ebookId == 0 &&
                            redirect.conhecaId == 0
                            select redirect;
            }
            return (redirects.ToList().Count > 0) ? redirects.ToList()[0] : null;
        }
    }
    public static HS_Redirect SearchPageByUrlHS( int tipo, string cursoCURL = "", string cursoURL = "", string redirectURL = "", string redirectURLTwo = "" )
    {
        using( var dbHS = new HS() )
        {
            IQueryable<HS_Redirect> redirects;
            if( tipo == 4 )
            {
                redirects = from redirect in dbHS.HS_Redirect
                            where redirect.url == redirectURL && redirect.noticiaId > 0 && redirect.unidadeCE == GlobalVars.HotSite.unidadeHS.unidadeCE
                            select redirect;
            }
            else
            {
                redirects = from redirect in dbHS.HS_Redirect
                            where
                                redirect.url           == redirectURL &&
                                redirect.cursoCatId    == 0 &&
                                redirect.regulamentoId == 0 &&
                                redirect.noticiaId     == 0 &&
                                redirect.ebookId       == 0 &&
                                redirect.conhecaId     == 0
                            select redirect;
            }
            return ( redirects.ToList().Count > 0 ) ? redirects.ToList()[0] : null;
        }
    }
}
编辑:

我设法使@NightOwl888回答工作与区域和其他一切我需要的,我不打算在这里张贴,因为它有点大,所以这里是代码:http://pastebin.com/yTdWKMp4

编辑2

我已经更新了pastebin上的文件与一些变化,以提高速度和可用性:http://pastebin.com/yTdWKMp4

C# MVC Routing With RouteBase

你的方法有几个问题:

  1. 永远不要扩展MvcRouteHandler来创建自定义URL方案。URL路由是一个双向过程,路由处理程序只能处理传入路由,但不能构建传出的URL。
  2. 你实际上不是"路由"在这里。路由意味着您正在将传入的请求映射到资源。您所做的是允许请求进入,决定如何处理它,然后浏览器重定向到另一个URL。这会导致不必要的服务器往返,这对性能和搜索引擎优化不利。
  3. OutputCache属性只作用于控制器动作方法,并且它只适用于缓存视图的内容。它不适用于缓存数据。

如果你想有数据库驱动的路由,你应该子类化RouteBase。这让你有机会将URL映射到一组路由值(代表控制器动作和参数),也可以将路由值映射回URL(因此ActionLinkRouteLink将在你的视图中正确工作)。

看看这个答案,找到一个可靠的方法。它还包括URL数据的缓存和线程锁定,以确保缓存过期时仅由单个线程更新缓存(并且数据库仅被调用一次)。

如果你需要使它更可重用(也就是说,使用更多的控制器和动作方法),你可以使它更通用类似于这个MVC 6样例通过传递控制器和动作信息和一个数据提供程序实例,通过您的自定义RouteBase的构造函数,并在您的配置中注册路由多次(当然,使用不同的参数)。

您正在使用static属性…通常不是一个好主意,除非你能做出一定的保证——在这种情况下,有一个保证,这个数据将被您的应用程序域的所有用户共享。

基本上,使用Session存储来跟踪单个用户的设置(有关更多信息,请参阅本文)。另外,作为题外话,我注意到你在BuscaURLWSBuscaURLHS中重复了代码——不要这样做!请参阅DRY了解为什么不可以。此外,你正在做你的URL标记化手动;有很多工具可以轻松地做到这一点(有关更多信息,请参阅Uri)。