UrlRewriter + HttpModule + Session问题

时间:2009-02-03 09:04:23

标签: c# asp.net

我需要使用HttpModule编写自定义“UrlRewriter”,在“重写”的那一刻我需要访问Session并遵循另一个SO线程的建议:

Can I access session state from an HTTPModule?

除RewritePath / Redirect部分外,一切正常。我没有任何例外,但浏览器需要永远加载。这真的是建立像这样的urlrewriter的最好方法吗?

using System;
using System.Web;
using System.Web.SessionState;
using System.Diagnostics;

namespace MyCompany.Campaigns
{

    public class CampaignRewriteModule : IHttpModule
    {
        public void Init(HttpApplication application)
        {
            application.PostAcquireRequestState += new EventHandler(Application_PostAcquireRequestState);
            application.PostMapRequestHandler += new EventHandler(Application_PostMapRequestHandler);
        }

        void Application_PostMapRequestHandler(object source, EventArgs e)
        {
            HttpApplication app = (HttpApplication)source;

            if (app.Context.Handler is IReadOnlySessionState || app.Context.Handler is IRequiresSessionState)
            {
                return;
            }

            app.Context.Handler = new MyHttpHandler(app.Context.Handler);
        }

        void Application_PostAcquireRequestState(object source, EventArgs e)
        {
            HttpApplication app = (HttpApplication)source;

            MyHttpHandler resourceHttpHandler = HttpContext.Current.Handler as MyHttpHandler;

            if (resourceHttpHandler != null)
            {
                HttpContext.Current.Handler = resourceHttpHandler.OriginalHandler;
            }

            Debug.Assert(app.Session != null);


            string path = HttpUtils.Path();

            if (!CampaignCodeMethods.IsValidCampaignCode(path)) return;

            string domain = HttpUtils.Domain();

            CampaignCode code = CampaignManager.RegisterCode(path, domain.Equals(Config.Instance.Domain.ToLower()) ? null : domain);

            if (code != null)
            {
               //app.Context.RewritePath(code.CampaignCodePath.Path, false);
               app.Context.Response.Redirect(code.CampaignCodePath.Path, true);
            }


        }

        public void Dispose() { }

        public class MyHttpHandler : IHttpHandler, IRequiresSessionState
        {
            internal readonly IHttpHandler OriginalHandler;

            public MyHttpHandler(IHttpHandler originalHandler)
            {
                OriginalHandler = originalHandler;
            }

            public void ProcessRequest(HttpContext context)
            {
                throw new InvalidOperationException("MyHttpHandler cannot process requests.");
            }

            public bool IsReusable
            {
                get { return false; }
            }
        }

    }

}

5 个答案:

答案 0 :(得分:4)

我想我知道它是什么。您的模块在所有请求上执行,并分配一个抛出错误的处理程序,除非有一个有效的活动代码(发生重写/重定向)。

但是因为这不仅仅是因为你的“处理程序广告系列代码”网址,它会导致错误被抛出,这会导致您被重定向到错误页面,该错误页面被模块捕获,该模块正在分配处理程序,它正在抛出一个错误,它正在重定向......我想你会到达我要去的地方;)

否则我会尝试一些事情:

  • 设置Fiddler并检查无限重定向循环
  • 在app.Context.Response.Redirect上放置一个断点 - 确保你没有进入无限循环
  • 在MyHttpHandler.ProcessRequest上放置一个断点 - 确保它没有被调用并且吞下了异常

答案 1 :(得分:2)

我写了一个简单的URL重写器模块,它做了类似的事情。通过将请求的URL与已知URL列表进行比较,在BeginRequest中完成URL重写。如果我们找到一个mach,我们使用HttpContext.RewritePath来改变请求的URL。

这似乎没有严重的副作用。

我注意到您使用Response.Redirect而不是Context.RewritePath。使用重定向将导致用户浏览器请求具有新URL的新页面。这真的是你想要的吗?然后,用户将在他的浏览器中看到新的URL。如果这真的是你想要的,你可以使用另一种方法,你使用自定义404页面未找到错误处理程序将用户重定向到适当的页面。

如果您设置IIS以将所有404错误重定向到您已设置的新页面,例如Custom404.aspx。在此页面中,您可以检查请求的URL以查看是否应该重写URL。如果它应该可以简单地将Response.Status设置为“301 Moved Permanently”并写一个名为“Location”的标题和新的url作为值。如果不应该重写url,则只能输出标准404页面未找到错误。

最后一种方法效果很好,但与Response.Redirect方法一样,用户将在浏览器中看到新的URL。使用Context.RewritePath可以提供与请求页面不同的页面。

答案 2 :(得分:1)

您的网址重写器是否处理不适用于实际网页的请求?如果他们是,那么我认为你不能访问Session ...我写的最后一个URL重写器是在那里处理404错误,我记得挖掘并找到(在某处,不记得在哪里)你如果该请求不是针对实际的.aspx页面,则不能访问Session。

答案 3 :(得分:0)

我认为问题可能在这个区块内:

if (code != null)
{
    //app.Context.RewritePath(code.CampaignCodePath.Path, false);
    app.Context.Response.Redirect(code.CampaignCodePath.Path, true);
}

尝试在if语句中添加断点,看看是否会不断受到攻击。

答案 4 :(得分:0)

我认为在将其重置为原始处理程序后应该调用'return',否则您将不断重写路径。

考虑一下,这可能是页面永远加载的原因! :)