从ASP.Net调用异步函数

时间:2016-03-22 14:02:17

标签: c# asp.net async-await impersonation

在ASP.Net项目中,我最近将一些冗长的函数更改为异步。事实证明这会导致一些未解决的问题。

基本上这些函数在使用await时正在工作,但是必须从另一个异步函数调用它最终成为表单中的问题。 到目前为止,我将页面指令Async设置为true,并使用RegisterAsyncTask启动对异步函数的调用。通话有效。但事实证明,当我启用了Async页面指令时,用户上下文有时会发生变化。

为了调用某些页面中所有代码的调用用户,我继承了System.Web.UI.Page类到ImpersonatedPage。在我的班级中,我使用OnLoad来强制调用用户。这样我肯定用户永远不会看到或做任何他/她已经访问过的,并且审计日志显示正确的用户。

启用异步页面指令时,它仍会模拟用户。但是,例如在按钮单击的代码中,用户上下文突然回到应用程序池上下文。在Page_Load中,用户上下文是预期的调用用户。 造成这种情况的原因是什么,是否可以避免切换回应用程序池用户?

或者,我尝试删除Async页面指令,并使用Task.Run调用异步函数。然后用户上下文不会切换回来,而是HttpContext.Current为null,async函数无法完成它的工作。

从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(为什么?)
  • [网页内容]
  • 模仿撤消

1 个答案:

答案 0 :(得分:2)

好像您错过了表单页面指令中的Async="true",详细here。试试这个:

<%@ Page Async="true" Language="C#" Async="true"
    AutoEventWireup="true" Inherits="ProxyAddresses" 
    Codebehind="ProxyAddresses.aspx.cs" %>