C# ASP.NET MVC中回调后的重定向操作

C# ASP.NET MVC中回调后的重定向操作,c#,asp.net,asp.net-mvc,redirecttoaction,C#,Asp.net,Asp.net Mvc,Redirecttoaction,我想在完成一些任务(发送电子邮件)后重定向到操作,但我不知道如何正确执行 这是我的代码,但是重定向到操作在这里没有任何作用 [HttpPost] public ActionResult SendEmail(EmailContentViewModel emailDetails) { using (MailMessage email = new MailMessage(emailDetails.from, emailDetails.to)) { email.Subje

我想在完成一些任务(发送电子邮件)后重定向到操作,但我不知道如何正确执行

这是我的代码,但是
重定向到操作
在这里没有任何作用

[HttpPost]
public ActionResult SendEmail(EmailContentViewModel emailDetails)
{
    using (MailMessage email = new MailMessage(emailDetails.from, emailDetails.to))
    {
        email.Subject = emailDetails.subject;
        email.Body = emailDetails.body;
        email.Priority = emailDetails.MailPriority;

        processSendingEmail(email, (result) =>
        {
            RedirectToAction("ContactResult", "Contact", new { success = result }); //It's not redirecting to the ContactResult page!
        });
    }

    return null;
}

private void processSendingEmail(MailMessage email,Action callback=null)
{
使用(SmtpClient SmtpClient=new SmtpClient(\u smtpHostName,\u smtpPort))
{
bool=false;
尝试
{
//.............//
}
捕获(例外e)
{
//.............//
}
回调?.Invoke(成功调用);
}
}

基于,以下是一个工作代码:

    [HttpPost]
    public async Task<ActionResult> SendEmail(EmailContentViewModel emailDetails)
    {
        using (MailMessage email = new MailMessage(emailDetails.from, emailDetails.to))
        {
            email.Subject = emailDetails.subject;
            email.Body = emailDetails.body;
            email.Priority = emailDetails.MailPriority;

            var sentSuccessfully= await processSendingEmail(email);

            return RedirectToAction("ContactResult", "Contact", new { success = sentSuccessfully});
        }
    }


    private async Task<bool> processSendingEmail(MailMessage email)
    {
        var client = new MailKit.Net.Smtp.SmtpClient();
        //Configure the client here ...
        try
        {
            var msg = (MimeKit.MimeMessage)email;
            await client.SendAsync(msg);
            return true;
        }
        catch (Exception ex)
        {
            Debug.Fail(ex.Message);
            string errorMessage = "";
            switch (ex)
            {
                case SmtpFailedRecipientException f:
                    errorMessage = $"Failed to send to {f.FailedRecipient}";
                    break;
                case SmtpException s:
                    errorMessage = "Protocol error";
                    break;
                default:
                    errorMessage = "Unexpected error";
                    break;
            }

            //Do anything you want with the error message

            return false;
        }
    }
[HttpPost]
公共异步任务SendEmail(EmailContentViewModel emailDetails)
{
使用(MailMessage email=新的MailMessage(emailDetails.from、emailDetails.to))
{
email.Subject=emailDetails.Subject;
email.Body=emailDetails.Body;
email.Priority=emailDetails.MailPriority;
var sent successfully=等待处理发送电子邮件(电子邮件);
返回RedirectToAction(“ContactResult”,“Contact”,new{success=sentSuccessfully});
}
}
专用异步任务处理发送电子邮件(MailMessage电子邮件)
{
var client=new MailKit.Net.Smtp.SmtpClient();
//在此处配置客户端。。。
尝试
{
var msg=(MimeKit.MimeMessage)电子邮件;
等待client.sendaync(msg);
返回true;
}
捕获(例外情况除外)
{
调试失败(例如消息);
字符串errorMessage=“”;
开关(ex)
{
案例SmtpFailedRecipientException f:
errorMessage=$“未能发送到{f.FailedRecipient}”;
打破
案例SMTPS:
errorMessage=“协议错误”;
打破
违约:
errorMessage=“意外错误”;
打破
}
//对错误消息执行任何操作
返回false;
}
}

使用任务库ActionResult调用

[HttpPost]
public async Task<ActionResult> SendEmail(EmailContentViewModel emailDetails)
{
   using (MailMessage email = new MailMessage(emailDetails.from, emailDetails.to))
   {
       email.Subject = emailDetails.subject;
       email.Body = emailDetails.body;
       email.Priority = emailDetails.MailPriority;

       var result = await processSendingEmail(email);
       return RedirectToAction("ContactResult", "Contact", new { success = result }); 
   }
}

async Task<bool> processSendingEmail(System.Net.Mail.MailMessage email) {            
    await Task.Delay(1000); //email code here...
    return true;
}
[HttpPost]
公共异步任务SendEmail(EmailContentViewModel emailDetails)
{
使用(MailMessage email=新的MailMessage(emailDetails.from、emailDetails.to))
{
email.Subject=emailDetails.Subject;
email.Body=emailDetails.Body;
email.Priority=emailDetails.MailPriority;
var结果=等待处理发送电子邮件(电子邮件);
返回RedirectToAction(“ContactResult”,“Contact”,new{success=result});
}
}
异步任务处理发送电子邮件(System.Net.Mail.MailMessage电子邮件){
等待任务。延迟(1000);//此处的电子邮件代码。。。
返回true;
}

不要使用回调。RedirectToAction创建一个ActionResult,该action应返回该ActionResult,但它不强制重定向

异步执行某些操作的正确方法是使用async/await。即使您的电子邮件库没有基于任务的异步方法,您也可以使用TaskCompletionSource使其适应基于任务的模型。这是相当不寻常的,尽管大多数库已经从较旧的异步模型(如回调、事件和APM)转移到任务

MailMessage
表明您正在使用。该方法是基于任务的,这意味着您可以编写

await client.SendMailAsync(email);
例如:

[HttpPost]
public async Task<ActionResult> SendEmail(EmailContentViewModel emailDetails)
{
    SmptClient client = ... //Configure the client here
    using (MailMessage email = new MailMessage(emailDetails.from, emailDetails.to))
    {
        email.Subject = emailDetails.subject;
        email.Body = emailDetails.body;
        email.Priority = emailDetails.MailPriority;

        await client.SendMailAsync(email);
        return RedirectToAction("ContactResult", "Contact", new { success = true }); 
    };
}
错误处理

MailKit和旧SmptClient的Send方法要么成功,要么抛出。一种选择是只隐藏异常并返回真/假成功标志:

try
{
    await client.SendAsync(msg);
    return RedirectToAction("ContactResult", "Contact", new { success = true});
}
catch
{
    return RedirectToAction("ContactResult", "Contact", new { success = false});
}
不过,这对试图诊断可能出现的问题的用户或管理员来说都不是很有帮助。这些方法的文档解释了可能发生的异常类型,例如:空消息的
ArgumentNullException
、InvalidOperationException、SmtpFailedRecipientException等

至少,代码可以在返回失败之前记录异常:

catch(Exception ex)
{
    _log.Error(ex);
    return RedirectToAction("ContactResult", "Contact", new { success = false});
}
更好的办法是处理特定的异常,并可能警告用户:

catch(SmtpFailedRecipientException ex)
{
    _log.Error(ex);
    return RedirectToAction("ContactResult", "Contact", new { success = false,message=$"Couldn't send the message to {ex.FailedRecipient}"});
}
catch(SmtpException ex)
{
    _log.Error(ex);
    return RedirectToAction("ContactResult", "Contact", new { success = false,message="Failed to send the message"});
}
catch(Exception ex)
{
    _log.Error(ex);
    return RedirectToAction("ContactResult", "Contact", new { success = false,message="An unexpected error occured"});
}
C#7中的模式匹配使这更容易:

catch(Exception ex)
{
    _log.Error(ex);
    string message="";
    switch (ex)
    {
        case SmtpFailedRecipientException f:
            message=$"Failed to send to {f.FailedRecipient}"; 
            break;
        case SmptException s :
            message="Protocol error";
            break;
        default:
            message="Unexpected error";
            break;
    }
    return RedirectToAction("ContactResult", "Contact", new { success = false,message=message});
}
分离方法

重构发送代码到单独的方法很容易。可以将try/catch块和客户端声明提取到单独的方法:

async Task<string> MySendMethod(MailMessage email)
{
    var client = new MailKit.Net.Smtp.SmptClient();
    //Configure the client here ...
    try
    {
        var msg=(MailKit)email;
        await client.SendAsync(msg);
        return "";
    }
    catch(Exception ex)
    {
        _log.Error(ex);
        switch (ex)
        {
            case SmtpFailedRecipientException f:
                return $"Failed to send to {f.FailedRecipient}"; 
            case SmptException s :
                return "Protocol error";
            default:
                return "Unexpected error";
        }
    }
}

不要使用回调
RedirectToAction
创建操作应返回的操作结果,它不强制重定向。异步执行某些操作的正确方法是使用
async/await
。即使您的电子邮件库没有基于任务的异步方法,您也可以使用TaskCompletionSource使其适应基于任务的模型。这将是相当不寻常的,尽管大多数库已经从较旧的异步模型(如回调、事件和APM)转移到任务库(如使用SmptClient)。该方法是基于任务的,您可以编写
wait-client.SendMailAsync(email)。但这是一个过时的类。假设它不应该被使用你假设该方法返回一个任务。代码不会在这里编译
new{success=result}
我已经更新了代码,你应该从processSendingEmail函数返回结果代码没有更改<无论该函数是否成功,都不会到达code>returnnull
。问题是functionan async方法返回任务的内部是什么,但是
success
是一个bool字段。谢谢,但是您的代码没有返回“结果”@是瓦杰伊。
return
是最后一条语句。
using
块定义了一个代码块,而不是另一个代码块function@Wadjey至于那个“结果”,它应该是什么?如果该方法成功,它将成功。如果没有,你会得到一个例外。如果发送邮件,您必须解释要返回的内容fails@Wadj
catch(Exception ex)
{
    _log.Error(ex);
    string message="";
    switch (ex)
    {
        case SmtpFailedRecipientException f:
            message=$"Failed to send to {f.FailedRecipient}"; 
            break;
        case SmptException s :
            message="Protocol error";
            break;
        default:
            message="Unexpected error";
            break;
    }
    return RedirectToAction("ContactResult", "Contact", new { success = false,message=message});
}
async Task<string> MySendMethod(MailMessage email)
{
    var client = new MailKit.Net.Smtp.SmptClient();
    //Configure the client here ...
    try
    {
        var msg=(MailKit)email;
        await client.SendAsync(msg);
        return "";
    }
    catch(Exception ex)
    {
        _log.Error(ex);
        switch (ex)
        {
            case SmtpFailedRecipientException f:
                return $"Failed to send to {f.FailedRecipient}"; 
            case SmptException s :
                return "Protocol error";
            default:
                return "Unexpected error";
        }
    }
}
[HttpPost]
public async Task<ActionResult> SendEmail(EmailContentViewModel emailDetails)
{
    using (MailMessage email = new MailMessage(emailDetails.from, emailDetails.to))
    {
        email.Subject = emailDetails.subject;
        email.Body = emailDetails.body;
        email.Priority = emailDetails.MailPriority;

        var message=await MySendMethod(email);
        return RedirectToAction("ContactResult", "Contact", 
                   new { success = String.IsNullOrWhitespace(result),
                         message=message 
                   }); 
    };
}