c# - Mvc .Net 从异步方法中捕获异常

标签 c# asp.net-mvc exception mailchimp

我正在使用 this作为 Mailchimp API v3.0 包装器的库

现在我无法从该库的方法中捕获异常。

这些方法抛出 MailChimpException,它是从 Exception 扩展而来的。

问题是,如果我从控制台应用程序运行它,那么我能够捕捉到异常,但是当我从我的 Web 项目中运行它时,我无法捕捉到异常,当异常发生时代码就卡住了。

这是我的调用示例:

public bool ListSubscribe(string emailAddress, string apiKey, string listId)
{
    try
    {
       var api = new MailChimpManager(apiKey);
       var profile = new Member();
       profile.EmailAddress = emailAddress;
       var output = api.Members.AddOrUpdateAsync(listId, profile).Result;
       return true;
    }
    catch (Exception ex)
    {
       logger.Error("An error ocurred in trying to Subscribe to Mailchimp list. {0}", ex.Message);
       return false;
    }
}

这是我调用的库中的方法:

namespace MailChimp.Net.Logic
{
    /// <summary>
    /// The member logic.
    /// </summary>
    internal class MemberLogic : BaseLogic, IMemberLogic
    {
        private const string BaseUrl = "lists";

        /// <summary>
        /// Initializes a new instance of the <see cref="MemberLogic"/> class.
        /// </summary>
        /// <param name="apiKey">
        /// The api key.
        /// </param>
        public MemberLogic(string apiKey)
            : base(apiKey)
        {
        }

        /// <summary>
        /// The add or update async.
        /// </summary>
        /// <param name="listId">
        /// The list id.
        /// </param>
        /// <param name="member">
        /// The member.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref>
        ///         <name>uriString</name>
        ///     </paramref>
        ///     is null. </exception>
        /// <exception cref="UriFormatException">In the .NET for Windows Store apps or the Portable Class Library, catch the base class exception, <see cref="T:System.FormatException" />, instead.<paramref name="uriString" /> is empty.-or- The scheme specified in <paramref name="uriString" /> is not correctly formed. See <see cref="M:System.Uri.CheckSchemeName(System.String)" />.-or- <paramref name="uriString" /> contains too many slashes.-or- The password specified in <paramref name="uriString" /> is not valid.-or- The host name specified in <paramref name="uriString" /> is not valid.-or- The file name specified in <paramref name="uriString" /> is not valid. -or- The user name specified in <paramref name="uriString" /> is not valid.-or- The host or authority name specified in <paramref name="uriString" /> cannot be terminated by backslashes.-or- The port number specified in <paramref name="uriString" /> is not valid or cannot be parsed.-or- The length of <paramref name="uriString" /> exceeds 65519 characters.-or- The length of the scheme specified in <paramref name="uriString" /> exceeds 1023 characters.-or- There is an invalid character sequence in <paramref name="uriString" />.-or- The MS-DOS path specified in <paramref name="uriString" /> must start with c:\\.</exception>
        /// <exception cref="MailChimpException">
        /// Custom Mail Chimp Exception
        /// </exception>
        /// <exception cref="TargetInvocationException">The algorithm was used with Federal Information Processing Standards (FIPS) mode enabled, but is not FIPS compatible.</exception>
        /// <exception cref="ObjectDisposedException">
        /// The object has already been disposed.
        /// </exception>
        /// <exception cref="EncoderFallbackException">
        /// A fallback occurred (see Character Encoding in the .NET Framework for complete explanation)-and-<see cref="P:System.Text.Encoding.EncoderFallback"/> is set to <see cref="T:System.Text.EncoderExceptionFallback"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Enlarging the value of this instance would exceed <see cref="P:System.Text.StringBuilder.MaxCapacity"/>. 
        /// </exception>
        /// <exception cref="FormatException">
        /// <paramref>
        ///         <name>format</name>
        ///     </paramref>
        /// includes an unsupported specifier. Supported format specifiers are listed in the Remarks section.
        /// </exception>
        public async Task<Member> AddOrUpdateAsync(string listId, Member member)
        {
            using (var client = this.CreateMailClient($"{BaseUrl}/"))
            {
                var response =
                await
                client.PutAsJsonAsync($"{listId}/members/{this.Hash(member.EmailAddress.ToLower())}", member, null).ConfigureAwait(false);

                await response.EnsureSuccessMailChimpAsync().ConfigureAwait(false);

                return await response.Content.ReadAsAsync<Member>().ConfigureAwait(false);
            }
        }
    }
}

有没有人知道为什么我能够在控制台应用程序中触发异常,但不能在 Web 项目中触发。有什么建议要检查什么吗?

更新: 如果我更改代码以使用 Task.Run,例如:

var task = Task.Run(async () => { await api.Members.AddOrUpdateAsync(listId, profile); });
                    task.Wait();

所以:

public bool ListSubscribe(string emailAddress, string apiKey, string listId)
{
    try
    {
       var api = new MailChimpManager(apiKey);
       var profile = new Member();
       profile.EmailAddress = emailAddress;
       var task = Task.Run(async () => { await api.Members.AddOrUpdateAsync(listId, profile); });
                    task.Wait();
       return true;
    }
    catch (Exception ex)
    {
       logger.Error("An error ocurred in trying to Subscribe to Mailchimp list. {0}", ex.Message);
       return false;
    }
}

然后我在 catch block 中捕获异常,但是当一切正常时我如何从任务中获取结果???

最佳答案

正确的解决方案是使这个“一直异步”,正如我在 MSDN 文章中描述的那样 async best practices .直接调用 Result 的问题在于它会导致死锁(正如我在博客文章 Don't block on async code 中所描述的)。 (在您的情况下,Result 的第二个问题是它将 MailChimpException 包装在 AggregateException 中,使错误处理更加尴尬)。

包装对 Task.Run 的调用,然后调用 Result 是一种 hack,它会降低您的网络服务的可扩展性(并且不会处理次要问题异常包装,要么)。如果不想使用异步代码,则使用同步 API。由于这是一个 I/O 操作,最自然的方法是异步代码,如下所示:

public async Task<bool> ListSubscribeAsync(string emailAddress, string apiKey, string listId)
{
  try
  {
    var api = new MailChimpManager(apiKey);
    var profile = new Member();
    profile.EmailAddress = emailAddress;
    var output = await api.Members.AddOrUpdateAsync(listId, profile);
    return true;
  }
  catch (Exception ex)
  {
    logger.Error("An error ocurred in trying to Subscribe to Mailchimp list. {0}", ex.Message);
    return false;
  }
}

关于c# - Mvc .Net 从异步方法中捕获异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38892832/

相关文章:

c# - 计算圆内坐标

c# - 有没有比Environment.StackTrace更简洁的方法来获取调用堆栈信息?

c# - ASP.NET MVC 3 工具包

c# - C#中如何获取调用方法的属性

c# - 用于复杂方法调用的 PInvoke C#

c# - 有没有办法假装来自切换按钮的 handleCheck 从未发生过?

asp.net-mvc - 使用 LINQ to SQL 在 ASP.NET MVC 中建模多对多关系

asp.net-mvc - JsonSerializer - 使用 'N2' 格式序列化小数位

events - Ollydbg “Single step event at ntdll - Press shift+f8 to pass execution…”吗?

java - Java中处理渲染异常?