我有一个非常微妙的错误,我无法识别。
背景 我们有2个站点在同一个Web服务器上运行相同的应用程序。
当请求首次出现时,将根据主机识别siteId并将其存储在Session中,如下所示:
protected void Application_BeginRequest(object sender, EventArgs e)
{
string host = Request.Url.Host;
int siteId = new SiteManager().GetSiteByUrl(host).SiteId;
if (SessionUser.Instance().SiteId != siteId)
{
SessionUser.Instance().SiteId = siteId;
}
}
此ID稍后用于确定要检索的数据以及确定要呈现的样式:
// this happens during an initialization phase
_siteConfiguration = _siteManager.GetSiteById(SessionUser.Instance().SiteId);
// then later:
private void SetPageTheme()
{
string theme = null;
switch (_siteConfiguration.SiteId)
{
case ConfigurationHelper.SITE.A:
theme = "SiteATheme";
break;
case ConfigurationHelper.SITE.B:
theme = "SiteBTheme";
break;
}
Page.Theme = theme;
}
问题:
我面临的问题是,如果您在几乎完全同时加载两个站点,即在几毫秒内,有时SiteA将加载SiteB的主题,反之亦然。这种情况不会经常发生,但它已经引起了客户的注意,所以它现在是一个问题。在SiteA加载和SiteB加载之间的差异在几毫秒内发生了某些事情,我不知道如何确定那是什么。
问题:
有没有人有任何想法可能会出错?有些东西在某处变得混乱。是IIS混淆了请求吗?是会话混合了它应该返回SiteId的网站吗?
如果需要更多信息,我会提供。
更新
作为参考,这是SessionUser
的定义(基本上,创建一个对象的静态实例以从Session获取SiteId值):
public class SessionUser
{
private static SessionUser _instance;
public int SiteId { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public static SessionUser Instance()
{
if (null == _instance)
{
_instance = new SessionUser();
if (null != HttpContext.Current.Session)
{
if (null == HttpContext.Current.Session["User"])
{
if (HttpContext.Current.Request.QueryString["sid"] != null)
{
int nSiteId = int.Parse(HttpContext.Current.Request.QueryString["sid"]);
_instance.SiteId = nSiteId;
HttpContext.Current.Session["User"] = _instance;
}
}
else
{
_instance = (SessionUser) HttpContext.Current.Session["User"];
}
}
}
return _instance;
}
}
答案 0 :(得分:4)
不知道'SessionUser'类是什么样的,我只能推测。
我将假设SessionUser.Instance()返回一个'静态'实例(或者成员)。
现在,这些将在整个应用程序中共享。所以有意义的是,这不能在两个站点之间共享。
我建议您使用HttpContext
将设置存储在BeginRequest
。
代码将如下所示:
class SessionUser
{
public static SessionUser Instance()
{
var ctx = HttpContext.Current;
var su = ctx["SessionUser"] as SessionUser;
if (su == null)
{
ctx["SessionUser"] = su = new SessionUser();
}
return su;
}
}
答案 1 :(得分:0)
我想您可以将存储当前站点ID的代码放在lock
块中,但这可能会妨碍性能。使用两个网站不共享的内容更有意义,如leppie says。
对于锁定示例:
if (SessionUser.Instance().SiteId != siteId)
{
lock(somePrivateStaticObject)
{
if (SessionUser.Instance().SiteId != siteId)
{
SessionUser.Instance().SiteId = siteId;
}
}
}