c# - WebForms 事件中的异步

标签 c# asp.net webforms async-await

我正在尝试在 WebForms 应用程序中使用新的 ASP.NET Identity 2.0 身份验证系统,但在允许用户保存数据源之前验证用户时遇到了问题。

问题源于从数据源的 OnUpdating 事件调用 IIdentityValidator.ValidateAsync。该标记在功能上与默认的动态数据模板相同(除了添加了 Async="true"),在后面的代码中进行了一些自定义。基本上,我为请求手动设置了 MetaTable(因为此页面是我的动态数据路由之一的替代品,但我想保留脚手架属性的好处)并且我添加了DetailsDataSource_Updating 事件。虽然下面的代码示例成功地将用户保存到我们的数据库中,但在返回到客户端之前通常会抛出以下错误:

"An asynchronous module or handler completed while an asynchronous operation was still pending."

我花了相当多的时间试图让它工作,但还没有找到不会锁定页面或抛出上述错误的解决方案。我担心我完全误解了 WebForms 中的 async/await,或者更糟的是,async/await 仅真正可用于 MVC 之外的数据库查询/绑定(bind)。

public partial class Edit : System.Web.UI.Page
{
    protected UserManager manager;
    protected CustomMetaTable table;

    protected void Page_Init(object sender, EventArgs e)
    {
        manager = UserManager.GetManager(Context.GetOwinContext());
        table = Global.DefaultModel.GetTable(typeof(User)) as CustomMetaTable;
        DynamicDataRouteHandler.SetRequestMetaTable(Context, table);
        FormView1.SetMetaTable(table);
        DetailsDataSource.EntityTypeFilter = table.EntityType.Name;
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        Title = table.EntityName;
        DetailsDataSource.Include = table.ForeignKeyColumnsNames;
    }

    protected void FormView1_ItemCommand(object sender, FormViewCommandEventArgs e)
    {
        if (e.CommandName == DataControlCommands.CancelCommandName)
        {
            Response.Redirect(table.ListActionPath);
        }
    }

    protected void FormView1_ItemUpdated(object sender, FormViewUpdatedEventArgs e)
    {
        if (e.Exception == null || e.ExceptionHandled)
        {
            Response.Redirect(table.ListActionPath);
        }
    }

    protected async void DetailsDataSource_Updating(object sender, Microsoft.AspNet.EntityDataSource.EntityDataSourceChangingEventArgs e)
    {
        IdentityResult result = await manager.UserValidator.ValidateAsync(e.Entity as User);
        if (!result.Succeeded)
        {
            e.Cancel = true;
        }
    }

最佳答案

在用同步Validate方法写一个新的UserValidator的过程中,I found a class in the Identity assembly它用于 UserManagerRoleManager 的所有同步包装器。我将此类复制到我的项目中,它允许我同步使用异步方法,只有少数异常(exception)(似乎通过在别处引用结果之前将结果分配给变量来避免主要异常)。

internal static class AsyncHelper
{
    private static readonly TaskFactory _myTaskFactory = new TaskFactory(
        CancellationToken.None,
        TaskCreationOptions.None, 
        TaskContinuationOptions.None, 
        TaskScheduler.Default);

    public static TResult RunSync<TResult>(Func<Task<TResult>> func)
    {
        return _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
    }

    public static void RunSync(Func<Task> func)
    {
        _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
    }
}

用法:

AsyncHelper.RunSync(() => manager.UserValidator.ValidateAsync(e.Entity as User));

关于c# - WebForms 事件中的异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23893984/

相关文章:

c# - 如何将 dataGrid 中的日期值与当前日期进行比较?

c# - 如何在 ASP.NET MVC 5 Controller 中返回 http 中的字符串?

C# ICodeCompiler - 运行类

asp.net 文本框添加BehaviorID

jquery - 使用 NSError 处理 WCF REST 服务和 iOS 错误

asp.net - 从代码隐藏中调用ASP.NET Web API

asp.net - 有条件地排除 ASP.NET WebForms 中的 html block

c# - DataGridView CellSelect 和 FullRowSelect

c# - 如何在标题标签后动态添加脚本

asp.net - Crystal Reports 将无法正确呈现