GET 上的 .net 核心电子邮件验证 link 无法将类型 'System.GUID' 的对象转换为类型 'Sytem.String' 的对象

.net core email verification link on GET fails to cast object of type 'System.GUID' to object of type 'Sytem.String'

我一直在使用 .net core 通过电子邮件发送用户验证 link。 link 构建得很好并且看起来没问题,但是当我单击 link 时,我得到一个 System.InvalidCastException 来破坏页面。 link 带你到剃须刀页面并且是这样构建的:

var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var codeBytes = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(      // the UrlHelperExtensions.Page method
    "/Account/ConfirmEmail",
    pageHandler: null,
    values: new { area = "Identity", userId = user.Id, code = codeBytes, returnUrl = svm.Input.ReturnUrl },
    protocol: Request.Scheme);                        

string htmlLink = HtmlEncoder.Default.Encode(callbackUrl);

其中 htmlLink 是 link,我应该可以点击它来验证电子邮件地址。然后我使用这样的 SmtpClient 发送电子邮件:

public bool SendEmailMessage(string subjectHeader, string emailBody, string userEmail)
{

    MailMessage msg = CreateMailMessage(subjectHeader, emailBody, userEmail);

    // call this function to create the client and send the email
    return SendEmail(msg);
}

private MailMessage CreateMailMessage(string subject, string body, string email)
{
    MailMessage msg = new MailMessage
    {
        IsBodyHtml = true,
        From = new MailAddress(_ADMIN_ADDRESS, _FROM_NAME),
        Subject = subject,
        Body = body
    };

    msg.To.Add(new MailAddress(email));

    return msg;
}

private bool SendEmail(MailMessage message)
{
    using (var client = new SmtpClient(_SMTP_HOST, _PORT))
    {
        client.Credentials = new System.Net.NetworkCredential(_SMTP_USER, _SMTP_PASSWORD);
        client.EnableSsl = true;

        try
        {
            client.Send(message);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Email not sent");
            Console.WriteLine($"Error message: {ex.Message}");
            return false;
        }
    }
}

这会无误地发送电子邮件,Razor 页面会像这样处理 OnGet 方法:

public async Task<IActionResult> OnGetAsync(string userId, string code)
{
    if (userId == null || code == null)
    {
        return RedirectToPage("/Index");
    }

    UserId = userId;
    var user = await _userManager.FindByIdAsync(userId);
    if (user == null)
    {
        return NotFound($"Unable to load user with ID '{userId}'.");
    }

    code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code));
    var result = await _userManager.ConfirmEmailAsync(user, code);

    StatusMessage = result.Succeeded ? "Thank you for confirming your email." : "Error confirming your email.";
    IsSuccess = result.Succeeded;
    return Page();
}

我一直在查看堆栈跟踪(见下文),但看起来所有使用的模块都是我间接使用的东西。我还没有找到为什么我得到 InvalidCastException,但是我缺少一些代码吗?我的 Startup.cs 文件包含 app.UseHttpsRedirection();,但我认为这与转换错误无关。

有什么想法吗?

Aug 10 21:42:13 ip-172-31-36-195 web: #033[41m#033[30mfail#033[39m#033[22m#033[49m: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
Aug 10 21:42:13 ip-172-31-36-195 web: An unhandled exception has occurred while executing the request.
Aug 10 21:42:13 ip-172-31-36-195 web: System.InvalidCastException: Unable to cast object of type 'System.Guid' to type 'System.String'.
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.Extensions.Internal.PropertyHelper.CallPropertySetter[TDeclaringType,TValue](Action`2 setter, Object target, Object value)
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.Extensions.Internal.PropertyHelper.SetValue(Object instance, Object value)
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.SaveTempDataPropertyFilterBase.SetPropertyValues(ITempDataDictionary tempData)
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.Filters.PageSaveTempDataPropertyFilter.OnPageHandlerExecuting(PageHandlerExecutingContext context)
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync()
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
Aug 10 21:42:13 ip-172-31-36-195 web: at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()

我对比了一个一直在用的之前的版本,我做了如下改动:

在我的 Startup.cs 文件中,我删除了这些行:

var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json",
        optional: false,
        reloadOnChange: true)
    .AddEnvironmentVariables();

builder.AddUserSecrets<Startup>();

在我的 ConfirmEmail.cshtml.cs 中,我删除了这些行:

[TempData]
public string UserId { get; set; }

// in OnGetAsync:
UserId = userId; // "userId" was passed in a URL parameter

因此,n ConfirmEmail.cshtml 我删除了这一行:

<a asp-controller="Transactions" asp-action="ResendVerificationlink" asp-route-userId="@Model.UserId">Resend Verification Link</a>

因为模型不再具有属性 UserId

我不确定这些更改中的哪一个导致错误得到解决,但我想它是 ConfirmEmail class 和 razor 页面中的 UserId。如果其他人遇到同样的错误,希望这会有所帮助,我仍然很困惑究竟出了什么问题以及为什么服务器试图将 System.GUID 转换为 System.String.