【发布时间】:2016-03-22 14:02:17
【问题描述】:
在一个 ASP.Net 项目中,我最近将一些冗长的函数更改为异步。事实证明,这会导致一些意想不到的问题。
基本上这些函数在使用 await 时可以工作,但不得不从另一个异步函数调用它最终会成为表单中的一个问题。 到目前为止,我将页面指令 Async 设置为 true 并使用 RegisterAsyncTask 来启动对异步函数的调用。通话有效。但事实证明,当我启用异步页面指令时,用户上下文有时会发生变化。
为了模拟某些页面中所有代码的调用用户,我将 System.Web.UI.Page 类继承到 ImpersonatedPage。在我的课堂上,我使用 OnLoad 来冒充调用用户。这样,我可以确定用户再也无法看到或执行任何操作,而他/她已经可以访问,并且审核日志会显示正确的用户。
启用异步页面指令后,它仍会模拟用户。但是例如在按钮单击的代码中,用户上下文突然回到应用程序池上下文。在 Page_Load 中,用户上下文是预期的调用用户。 是什么原因造成的,是否可以避免切换回应用程序池用户?
另外,我尝试删除异步页面指令,并使用 Task.Run 调用异步函数。然后用户上下文不会切换回来,而是 HttpContext.Current 为 null 并且异步函数无法完成它的工作。
还有什么其他方法可以从 ASP.Net 调用异步函数而无需启用异步页面指令?
目标框架:4.6.1 AFAIK 没有启用怪癖
ImpersonatedPage 类:
public class ImpersonatedPage : System.Web.UI.Page
{
WindowsImpersonationContext m_wic = null;
protected override void OnLoad(EventArgs e)
{
WindowsIdentity wi = (WindowsIdentity)System.Web.HttpContext.Current.User.Identity;
m_wic = wi.Impersonate();
HttpContext.Current.Response.Write("Impersonate<br />");
base.OnLoad(e);
}
protected override void OnUnload(EventArgs e)
{
base.OnUnload(e);
_ImpersonationUndo();
}
protected void _ImpersonationUndo()
{
if (m_wic != null)
{
m_wic.Undo();
HttpContext.Current.Response.Write("Impersonate undo<br />");
}
m_wic = null;
}
}
表单页面指令:
<%@ Page Async="true" Language="C#" AutoEventWireup="true" Inherits="ProxyAddresses" Codebehind="ProxyAddresses.aspx.cs" %>
类声明:
public partial class ProxyAddresses : ImpersonatedPage
Page_Load:
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("Page_Load: " + WindowsIdentity.GetCurrent().Name + "<br />");
if (!IsPostBack)
{
RegisterAsyncTask(new PageAsyncTask(InitialPageLoadAsync));
}
...
异步函数:
private async Task InitialPageLoadAsync()
{
Response.Write("InitialPageLoadAsync: " + WindowsIdentity.GetCurrent().Name + "<br />");
await fnDoSomeAsyncWork();
...
按钮点击:
protected void idBtnSaveSrv_Click(object sender, EventArgs e)
{
Response.Write("idBtnSaveSrv_Click: " + WindowsIdentity.GetCurrent().Name + "<br />");
...
调试输出 - 初始请求:
- 冒充
- Page_Load:DOMAIN\myuser
- InitialPageLoadAsync:IIS APPPOOL\appuser(为什么?)
- [页面内容]
- 模拟撤消
调试输出 - 按钮点击:
- 冒充
- Page_Load:DOMAIN\myuser
- idBtnSaveSrv_Click:IIS APPPOOL\appuser(为什么?)
- [页面内容]
- 模拟撤消
【问题讨论】:
-
请贴一些代码。
-
如果你想在 Page_Load 中进行异步调用,你应该声明它
async void,不使用 RegisterAsyncTask。 RegisterAsyncTask 旨在通知 IIS 正在运行的任务在当前请求结束时不应中止 -
几乎太容易和明显了......虽然我试过了但它没有用,然后按照这里的例子:link 无论如何,使 Page_Load async 似乎工作完美。
标签: c# asp.net async-await impersonation