【问题标题】:Attempting ValidationAttribute in MVC4 that is asynchronous using Async, Task and Await在 MVC4 中尝试使用 Async、Task 和 Await 异步的 ValidationAttribute
【发布时间】:2013-09-13 11:21:11
【问题描述】:

我正在尝试在 MVC4 中编写验证属性。 目的是检查是否存在应用程序引用(只是一个代表我希望防止重复的键的字符串)。 我的数据是通过 WebAPI 访问的,因为我使用的是 4.5,所以如果可能的话,我希望将其设为异步。

我可能没有充分或适当地使用 async 和 await,但我想知道如何从继承的 Validation 类的重写 IsValid 方法中调用我的 async 方法。

public class UniqueApplicationReferenceAttribute : ValidationAttribute
{
    public UniqueApplicationReferenceAttribute() : base(() => "The {0} already exists") { }

    public int? ApplicationCount { get; set; }

    public override bool IsValid(object value)
    {
        var myTask = GetApplicationRefCountAsync();

        myTask.Wait();

        this.ApplicationCount = this.ApplicationCount ?? 0;

        if (ApplicationCount > 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }


    public async Task GetApplicationRefCountAsync()
    {
        HttpClient client = new HttpClient();

        client.BaseAddress = new Uri("http://localhost:11111/");
        client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

        var apps = client.GetStringAsync("api/dataapplications");

        await Task.WhenAll(apps);

        var appList = apps.Result;

        this.ApplicationCount =  appList.Count();// apps.Count();
    }
}

非常感谢, 丹。

【问题讨论】:

  • C# 4 不常与 MVC 4 一起使用。你的意思是 C# 5 吗?您的 MVC 应用程序是否在 .NET 4.5 上运行?
  • .net 4.5 上的 MVC 4 - 我的大脑被标记阶段溶解了

标签: c#-4.0 asp.net-mvc-4 asynchronous asp.net-web-api async-await


【解决方案1】:

我无法对此进行全面测试,但您应该可以执行以下操作:

public bool IsValid(object value)
{
    var appCount = GetApplicationRefCountAsync().Result;
    return appCount > 0;
}

public async Task<int> GetApplicationRefCountAsync()
{
    var client = new HttpClient();

    client.BaseAddress = new Uri("http://localhost:11111/");
    client.DefaultRequestHeaders.Accept.Add(
        new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

    return await client.GetStringAsync("api/dataapplications")
        .ContinueWith(r => Convert.ToInt32(r))
        .ConfigureAwait(false);
}

在 ASP.NET 线程中使用 async/await 方法时要小心。很容易造成死锁。

【讨论】:

  • 死锁是服务调用/异步中的常见问题吗?我应该使用某种技术来降低这种风险吗?
  • 在 ASP.NET 中特别麻烦,因为一切都在 UI 线程中运行。如果您在产生该任务的同一线程上等待任务的结果,则该任务将永远不会返回。
【解决方案2】:

我建议您同步调用 WebAPI 方法。 ValidationAttribute 本身不支持异步实现,因此您将编写的任何同步异步代码都只是一个 hack,与同步版本相比实际上并没有提供任何好处。

【讨论】:

  • 感谢斯蒂芬的回复!我认为你是对的,我会看看如何实现这个 - 你有没有看到一个如何做到这一点的例子?我看到很多例子,但经常是 WPF。我正在 Angular 中创建一个 SPA,并希望确保我正确调用 webapi,因为此代码将用于无数的验证和基本数据查找 - 想要做到这一点。
  • 恐怕这超出了我的经验范围,但我强烈推荐 John Papa 的 Pluralsight 课程和博客。他目前使用 Durundal 而不是 Angular,但概念应该非常相似。
  • 我已经听了那个系列 3 遍了——还有很长的视频!我的第一个 SPA 测试是使用 Durandal 创建的。精彩的视频,喜欢数据访问中泛型的工厂模式。感谢您的指点。
  • 这有点过时了,但我有一个下个月开始的 SPA 项目,想听听你为什么选择 Angular 而不是 Durandal。如果你写博客,请分享链接。 :)
  • 嗨,斯蒂芬,简而言之,这更像是一项战略举措,而不是经过深思熟虑的举措。当时,Durandal 似乎没有尽其所能地宣传自己,缺乏文档,而且听起来该项目与基于团队的 Google 项目绑定到一个人——我觉得与 Google 合作更安全。我仍然处于探索领域,但我喜欢 Angular 结构——我还设法使用 require js 异步加载所有文件——加载屏幕是我的第一个要求。使用引导程序看起来也很漂亮。 ASP.NET MVC + Angular MVC + WebAPI = 许多文件:D
猜你喜欢
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-11
  • 2019-10-08
相关资源
最近更新 更多