none
关于异步 asp.net page/handler 产生结果后 调用原线程方法的问题 RRS feed

  • 问题

  • 遇到了一个问题。

    最近在做一个不需要维护用户 用windows live id 登陆的站点

    用Live Id 登陆的时候 使用了一个微软提供的异步HttpHandler.

      这时候想在Handler内部实现如果登陆成功 就发起对FormsAuthentication的调用,setcookie 直接登陆用户,

    但是由于FormsAuthentication需要原线程内使用,否则其方法内部无法找到context.

     

    如何在异步page调用FormsAuthentication呢? 虽然做的事情很简单  就是通过context找到cookie加密后写入

    但是细节很多。我可不想把相关的所有代码反编出来啊。。。

     

    目前我使用一个同步的handler 做代理 在其中原线程的process request 方法内调用异步handler的begin和end.

    这样不但要用原线程 还要调度另外一个异步线程 自觉十分浪费。

     

    有没有别的办法呢?

     


    入了ipad,最近用ipad上论坛
    2011年5月10日 1:52

答案

  • 关于ASP.NET异步编程一般有两点可能需要注意的:
    1. 不要用HttpContext.Current,把HttpContext对象保留起来传来传去使用。
    2. 如果外部类库使用HttpContext.Current,那么自己保留起来,然后在回调之后重新为HttpContext.Current赋值。

    Happy programming, happy life.
    http://www.cnblogs.com/JeffreyZhao/
    2011年5月10日 2:30

全部回复

  • 关于ASP.NET异步编程一般有两点可能需要注意的:
    1. 不要用HttpContext.Current,把HttpContext对象保留起来传来传去使用。
    2. 如果外部类库使用HttpContext.Current,那么自己保留起来,然后在回调之后重新为HttpContext.Current赋值。

    Happy programming, happy life.
    http://www.cnblogs.com/JeffreyZhao/
    2011年5月10日 2:30
  • 
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.SessionState;
    
    namespace Spits.WebSite.Content.Login.LivePassport
    {
      /// <summary>
      /// Summary description for OAuthWrapCallback
      /// </summary>
      public class OAuthWrapCallback : IHttpHandler, IRequiresSessionState,IHttpAsyncHandler
      {
        IHttpAsyncHandler hdl = new Microsoft.Live.OAuthWrapHandler();
    
    
    
        public void ProcessRequest(HttpContext context)
        {
          //var ar = hdl.BeginProcessRequest(context, o => { }, null);
          //hdl.EndProcessRequest(ar);
          //var dic = AuthIntegration.GetSessionAuthInfo(context);
          //FormsAuthentication.SetAuthCookie(dic["UID"], true);
    
           hdl.ProcessRequest(context);
        }
    
        public bool IsReusable
        {
          get
          {
            return hdl.IsReusable;
          }
        }
    
    
    
        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
          AsyncCallback ncb =
            o =>
            {
              cb(o);
              CheckLogin();
            };
    
          return hdl.BeginProcessRequest(context, ncb, extraData);
        }
    
        public void EndProcessRequest(IAsyncResult result)
        {
          hdl.EndProcessRequest(result);
        }
    
        /// <summary>
        /// Must invoke in response thread
        /// </summary>
        void CheckLogin()
        {
    
          var dic = AuthIntegration.GetSessionAuthInfo(HttpContext.Current );
    
          if (dic != null)
          {
            FormsAuthentication.SetAuthCookie(dic["UID"], true);
          }
          else
          {
            FormsAuthentication.SignOut();
          }
    
        }
    
    
      }
    }
    
    
    
    

    入了ipad,最近用ipad上论坛
    2011年5月10日 2:48
  • 以上是接收 live.com 返回用户登陆数据的handler.

     

    CheckLogin() 是根据这一信息设置 FormsAuthentication的方法

    我曾以为  begin方法中的callback函数会在原thread 进行,所以写出了newcallback的代码,经测试无效

     


    入了ipad,最近用ipad上论坛
    2011年5月10日 2:50
  • 我目前使用的折衷办法:

     

     

      public class OAuthWrapCallback : IHttpHandler, IRequiresSessionState
      {
        IHttpAsyncHandler hdl = new Microsoft.Live.OAuthWrapHandler();
    
    
    
        public void ProcessRequest(HttpContext context)
        {
          var ar = hdl.BeginProcessRequest(context, o => { }, null);
          hdl.EndProcessRequest(ar);
          var dic = AuthIntegration.GetSessionAuthInfo(context);
    
          if (dic != null)
          {
            FormsAuthentication.SetAuthCookie(dic["UID"], true);
          }
          else
          {
            FormsAuthentication.SignOut();
          }
        }
    
        public bool IsReusable
        {
          get
          {
            return hdl.IsReusable;
          }
        }
    
      }
    
     


    入了ipad,最近用ipad上论坛
    2011年5月10日 2:55
  • 这就是倒霉孩子 FormsAuthentication 内部的实现

    上手直接取current  (*&@#(*@!

    可恶啊  里面调用的CookielessHelperClass 还是个internal的class

     

     

     

    public static void SetAuthCookie(string userName, bool createPersistentCookie, string strCookiePath)
    {
     Initialize();
     HttpContext current = HttpContext.Current;
     if (!current.Request.IsSecureConnection && RequireSSL)
     {
      throw new HttpException(SR.GetString("Connection_not_secure_creating_secure_cookie"));
     }
     bool flag = CookielessHelperClass.UseCookieless(current, false, CookieMode);
     HttpCookie cookie = GetAuthCookie(userName, createPersistentCookie, flag ? "/" : strCookiePath, !flag);
     if (!flag)
     {
      HttpContext.Current.Response.Cookies.Add(cookie);
      current.CookielessHelper.SetCookieValue('F', null);
     }
     else
     {
      current.CookielessHelper.SetCookieValue('F', cookie.Value);
     }
    }
    
     
    
     
    
    

     


    入了ipad,最近用ipad上论坛
    2011年5月10日 2:58
  • 在Callback里设回HttpContext.Current不行吗?
    Happy programming, happy life.
    http://www.cnblogs.com/JeffreyZhao/
    2011年5月10日 2:59
  • 请看 void CheckLogin()
    中的代码

    其中对cookie的修改不是我们能控制的

     

      是    FormsAuthentication 静态类中的实现  无法把context 传入FormsAuthentication。SetAuthCookie  函数

     

    :(   桑心总是难免的


    入了ipad,最近用ipad上论坛
    2011年5月10日 3:03
  • >_<  突然发现 HttpContext.Current 是可以set的????   只要及时清除 应该可以在异步线程中使用????

     

    有希望了!


    入了ipad,最近用ipad上论坛
    2011年5月10日 3:05
  • 我一条回复不就说了“为HttpContent.Current赋值”么……
    Happy programming, happy life.
    http://www.cnblogs.com/JeffreyZhao/
    2011年5月10日 3:09
  • 嗯 当时没看懂

     

    目前的做法是这样呵呵

     

     public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
          
          AsyncCallback ncb =
            o =>
            {
              cb(o);
              HttpContext.Current = context;
              CheckLogin();
              HttpContext.Current = null;
            };
    
          return hdl.BeginProcessRequest(context, ncb, extraData);
        }
    


    入了ipad,最近用ipad上论坛
    2011年5月10日 3:16
  • 赞,我终于也有正确答案了……
    Happy programming, happy life.
    http://www.cnblogs.com/JeffreyZhao/
    2011年5月10日 3:34
  • GOOD。。。又学到东西鸟。。。
    To love is not to hold!
    2011年5月10日 4:53