我在我的网络应用程序上有一个自定义路由系统,我有一个包含我的路由的数据库(url
,Controller
,Action
以及更多信息)。对服务器发出的每个请求都会转到数据库,查询按网址路由并返回一组我需要保持可访问的内容,以便将来呈现Filter
,Controller
和{{1}我将此数据保存在Global.asax文件的全局变量中:
View
我的问题是,现在这个信息正在通过用户混合,有时当我在我的浏览器并且我有3个打开的标签并且我在“几乎”同时刷新它们同时最后一个将获得路由数据之前加载过的。
例如,我的public static class GlobalVars
{
public static Redirect reqContext { get; set; }
public static UnidadeHotSite HotSite { get; set; }
}
var会保留一些子网站信息,例如HotSite
,name
,url
等,子网址网址为:abc.com/subsite。当我加载第一个选项卡时,我获得了正确的数据,即子网站数据,第二个选项卡不在子网站区域abc.com,我得到的数据与上次加载的选项卡相同。
现在,可能是什么问题?我已经使用ID
上的NoStore
并尝试停用会话,但似乎没有任何效果。
这是我的路线处理程序:
OutputCache
这是在数据库上进行搜索的控制器
[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;
}
}
修改
我设法让@ NightOwl888回答我需要的区域和其他一切,我不会在这里发布,因为它有点大,所以这里是代码:http://pastebin.com/yTdWKMp4
编辑2
我已经在pastebin上更新了文件并进行了一些更改以提高速度和可用性:http://pastebin.com/yTdWKMp4
答案 0 :(得分:2)
您正在使用static
属性...除非您能做出某些保证,否则通常不是一个好主意 - 在这种情况下,可以保证这些数据将在您的应用程序域的所有用户之间共享。
基本上,使用Session
存储来跟踪个人用户的设置(有关详情,请参阅this article)。
另外,我还是注意到BuscaURLWS
和BuscaURLHS
中的代码重复了 - 请不要这样做!有关原因,请参阅DRY。此外,您手动进行URL标记化;有很多工具可以轻松完成这项工作(有关详细信息,请参阅Uri)。
答案 1 :(得分:2)
您的方法存在一些问题:
MvcRouteHandler
以制作自定义网址方案。 URL路由是一个双向进程,路由处理程序只能处理传入的路由,但不构建传出的URL。如果要使用数据库驱动的路由,则应该将RouteBase
子类化。这使您有机会将URL映射到一组路由值(表示控制器操作和参数),并将路由值映射回URL(因此ActionLink
和RouteLink
将正常工作你的意见)。
了解this answer的可靠方法。它还包括URL数据和线程锁定的缓存,以确保缓存仅在缓存过期时由单个线程(以及仅调用一次的数据库)更新。
如果您需要使其更具可重用性(即使用更多控制器和操作方法),您可以通过传递控制器和操作信息以及数据提供程序实例,使其更加通用,类似于此MVC 6 sample通过自定义RouteBase
的构造函数,并在配置中多次注册路由(当然,使用不同的参数)。