You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core中IsCompletedSuccessfully返回false问题求助

问题分析与解决:订单结账邮件发送后无法进入Completed视图

看起来你踩了异步编程里的一个常见坑——用同步方式调用异步方法,导致任务状态判断完全失效,这就是为什么IsCompletedSuccessfully一直返回false,始终跳不到Completed视图的原因。咱们一步步拆解问题,再给出具体的修复方案:

一、核心问题根源

你的GetIsCompleted()方法直接调用了Email.SendMessageAsync().IsCompletedSuccessfully,但SendMessageAsync是一个返回Task的异步方法:

public async Task SendMessageAsync() { ... }

当你不使用await直接调用异步方法时,会立即得到一个未完成的Task对象——此时邮件发送逻辑可能刚启动甚至还没开始执行,IsCompletedSuccessfully自然是false。

另外还有个隐藏问题:SendMessageAsync内部捕获了异常但没有向外抛出,就算邮件发送真的失败了,上层代码也只能通过IsCompletedSuccessfully判断状态,无法知道具体失败原因,排查起来非常困难。

二、具体修复步骤

1. 重构CheckOut方法,改用异步等待

首先要把CheckOut改成异步方法,直接等待邮件发送完成,去掉多余的GetIsCompleted()判断:

[HttpPost]
public async Task<ViewResult> CheckOut(Order order) // 标记为async,返回Task<ViewResult>
{
    if (Cart.Lines.Count() == 0)
    {
        ModelState.AddModelError("", "Your Cart is empty!");
    }
    if (ModelState.IsValid)
    {
        order.CartLines = Cart.Lines;
        order.DateTime = DateTime.Now;
        order.TotalPrice = Cart.ComputeTotalValue();
        
        if (Repository.SaveOrder(order))
        {
            if (User.Identity.IsAuthenticated) // 用IsAuthenticated判断用户是否登录更准确
            {
                Email.SetMessageBody(order.OrderID);
                try
                {
                    await Email.SendMessageAsync(); // 等待邮件发送完成
                    Cart.Clear();
                    return View("Completed");
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex, "Failed to send order confirmation email for OrderID: {OrderID}", order.OrderID);
                    ViewBag.Error = "An error occurred while sending you an email with the order details.";
                }
            }
        }
        else
        {
            ViewBag.Error = "An error occurred while trying to save your order. Please try again!";
        }
    }
    else
    {
        ViewBag.Error = "An error occurred while trying to save your order. Please try again!";
    }
    return View(new Order());
}

2. 修改SendMessageAsync,让错误可被上层感知

现在你的SendMessageAsync捕获异常后只打了日志,上层无法知道发送失败。可以选择抛出异常让上层处理,或者返回布尔值表示成功状态:

选项1:抛出异常(推荐,便于排查问题)

public async Task SendMessageAsync()
{
    // 用using自动释放MailMessage,避免资源泄漏
    using var message = new MailMessage(MailFrom.ToString(), MailTo.ToString(), GetSubject(), GetMessageBody());
    try
    {
        await Client.SendMailAsync(message);
    }
    catch (Exception ex)
    {
        Logger.LogError(ex, "Failed to send email to {Recipient}", MailTo);
        throw; // 抛出异常,让上层知道发送失败
    }
}

选项2:返回布尔值

如果你不想抛出异常,也可以让方法返回是否发送成功:

public async Task<bool> SendMessageAsync()
{
    using var message = new MailMessage(MailFrom.ToString(), MailTo.ToString(), GetSubject(), GetMessageBody());
    try
    {
        await Client.SendMailAsync(message);
        return true;
    }
    catch (Exception ex)
    {
        Logger.LogError(ex, "Failed to send email to {Recipient}", MailTo);
        return false;
    }
}

对应的上层调用可以改成:

if (await Email.SendMessageAsync())
{
    Cart.Clear();
    return View("Completed");
}
else
{
    ViewBag.Error = "An error occurred while sending you an email with the order details.";
}

3. 额外优化建议

  • 用using语句管理MailMessage的生命周期,自动释放资源,不需要手动调用Dispose()。
  • 日志里加入订单ID、收件人等关键信息,方便后续排查问题(比如SMTP配置错误、收件地址无效、网络波动等)。
  • 替换User.Identity.Name != null为User.Identity.IsAuthenticated,更准确判断用户是否登录。

三、补充解释:为什么IsCompletedSuccessfully一直为false?

IsCompletedSuccessfully是Task的属性,只有当任务已经执行完成且没有抛出任何异常时才会返回true。你直接调用SendMessageAsync()而不等待,Task处于WaitingForActivation(等待启动)或Running(正在执行)状态,此时这个属性必然是false。只有用await等待任务完成后,它才会根据执行结果变成true或false。

内容的提问来源于stack exchange,提问作者konstantinos Dms

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:41:46