SharePoint开发中经常会用到HttpContext.Current和SPContext.Current来获取数据,如我们通过HttpContext.Current获取Request、Response等信息,通过SPContext.Current获取Web、CurrentUser、Site、SPListItem等等,在EventHandler(EventReceiver)中也不例外,但是如果我们在EventHandler(EventReceiver)使用了HttpContex.Current或SPContext.Current则会出现Null Reference Exception (空引用错误),下面介绍使用时的注意事项。
因为EventHandler 和HttpContext.Current在不同的线程(暂且这样理解,其实这种说法不明确),在ItemAdding、ItemAdded、ItemUpdating、ItemUpdated、ItemDeleting、ItemDeleted等方法中直接使用HttpContext时会出现Null引用错误,因为这个时候HttpContext.Current确实是不存在的,根据经验可以通过如下两种方式引用HttpContext.Current对象:
- 在EventReceiver的构造函数中用对象将HttpContext.Current引用到当前类对象
此方法仅适用于ItemAdding和ItemUpdating,Demo如下:
public
class
HttpContextTestReceiver: SPItemEventReceiver
{
HttpContext context = null;
public HttpContextTestReceiver()
: base()
{
context = HttpContext.Current;
}
void WriteInfo(SPItemEventProperties properties)
{
Debug.WriteLine("** begin " + properties.EventType + " **");
if (null == context)
{
Debug.WriteLine("context is null.");
}
else
{
Debug.WriteLine(context.Request.RawUrl);
}
Debug.WriteLine("** end " + properties.EventType + " **");
}
public
override
void ItemAdding(SPItemEventProperties properties)
{
WriteInfo(properties);
}
public
override
void ItemAdded(SPItemEventProperties properties)
{
WriteInfo(properties);
}
public
override
void ItemUpdating(SPItemEventProperties properties)
{
WriteInfo(properties);
}
public
override
void ItemUpdated(SPItemEventProperties properties)
{
WriteInfo(properties);
}
public
override
void ItemDeleting(SPItemEventProperties properties)
{
WriteInfo(properties);
}
public
override
void ItemDeleted(SPItemEventProperties properties)
{
WriteInfo(properties);
}
}
执行完输出结果如下:
** begin ItemAdding **
/moss/alcatel/pgb/Lists/Links/NewForm.aspx?RootFolder=%2fmoss%2falcatel%2fpgb%2fLists%2fLinks&Source=http%3a%2f%2fnanmutech%3a8680%2fmoss%2falcatel%2fpgb%2fLists%2fLinks%2fAllItems.aspx
** end ItemAdding **
** begin ItemAdded **
context is null.
** end ItemAdded **
** begin ItemUpdating **
/moss/alcatel/pgb/Lists/Links/EditForm.aspx?ID=3&Source=http%3a%2f%2fnanmutech%3a8680%2fmoss%2falcatel%2fpgb%2fLists%2fLinks%2fAllItems.aspx
** end ItemUpdating **
context is null.
** end ItemUpdated **
** begin ItemDeleting **
context is null.
** end ItemDeleting **
** begin ItemDeleted **
context is null.
** end ItemDeleted **
可见此方法只适用于ItemAdding 和 ItemUpdating。
- 通过HttpRunttime.Cache来传递HttpContex.Currentt对象
此方法适用于所有事件,但实现有点麻烦,需要在页面中添加一个控件,并在控件的OnLoad 事件中将HttpContext.Current缓存到HttpRuntime.Cache中,Demo如下:
- 创建一个WebPart
public
class
HttpContextTestPart: WebPart
{
protected
override
void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Page.IsPostBack)
{
// use the current user login name as key, add the httpcontext to HttpRuntime.Cache
HttpRuntime.Cache.Add(HttpContext.Current.User.Identity.Name.ToLower(), HttpContext.Current, null,
DateTime.Now.AddMinutes(2), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
}
}
}
- 创建一个EventReceiver
[CLSCompliant(false)]
public
class
HttpContextTestReceiver: SPItemEventReceiver
{
HttpContext context = null;
public HttpContextTestReceiver()
: base()
{
}
void WriteInfo(SPItemEventProperties properties)
{
context = HttpRuntime.Cache[properties.UserLoginName.ToLower()] as
HttpContext;
// remove form the cache
HttpRuntime.Cache.Remove(properties.UserLoginName.ToLower());
Debug.WriteLine("** begin " + properties.EventType + " **");
if (null == context)
{
Debug.WriteLine("context is null.");
}
else
{
Debug.WriteLine(context.Request.RawUrl);
}
Debug.WriteLine("** end " + properties.EventType + " **");
}
public
override
void ItemAdding(SPItemEventProperties properties)
{
WriteInfo(properties);
}
public
override
void ItemAdded(SPItemEventProperties properties)
{
WriteInfo(properties);
}
public
override
void ItemUpdating(SPItemEventProperties properties)
{
WriteInfo(properties);
}
public
override
void ItemUpdated(SPItemEventProperties properties)
{
WriteInfo(properties);
}
public
override
void ItemDeleting(SPItemEventProperties properties)
{
WriteInfo(properties);
}
public
override
void ItemDeleted(SPItemEventProperties properties)
{
WriteInfo(properties);
}
}
- 用Designer将WebPart添加到对应的页面,如NewForm.aspx, Editform.aspx,DisplayForm, AllItems.aspx等等
测试后输出的结果如下:
** begin ItemAdding **
/moss/alcatel/pgb/Lists/Links/NewForm.aspx?RootFolder=%2fmoss%2falcatel%2fpgb%2fLists%2fLinks&Source=http%3a%2f%2fnanmutech%3a8680%2fmoss%2falcatel%2fpgb%2fLists%2fLinks%2fAllItems.aspx
** end ItemAdding **
** begin ItemAdded **
/moss/alcatel/pgb/Lists/Links/EditForm.aspx?ID=3&Source=http%3a%2f%2fnanmutech%3a8680%2fmoss%2falcatel%2fpgb%2fLists%2fLinks%
** end ItemAdded **
** begin ItemUpdating **
/moss/alcatel/pgb/Lists/Links/EditForm.aspx?ID=3&Source=http%3a%2f%2fnanmutech%3a8680%2fmoss%2falcatel%2fpgb%2fLists%2fLinks%2fAllItems.aspx
** end ItemUpdating **
/moss/alcatel/pgb/Lists/Links/EditForm.aspx?ID=3&Source=http%3a%2f%2fnanmutech%3a8680%2fmoss%2falcatel%2fpgb%2fLists%2fLinks%
** end ItemUpdated **
** begin ItemDeleting **
/moss/alcatel/pgb/Lists/Links/AllItems.aspx
** end ItemDeleting **
** begin ItemDeleted **
/moss/alcatel/pgb/Lists/Links/AllItems.aspx
** end ItemDeleted **
可以看到每个事件中都可以取到HttpContext,但是用完之后要将HttpContext从缓存中删除。