应用程序启动时出错:操作不能同时使用表单和 JSON 正文参数

问题描述 投票:0回答:1

在一个新的 Blazor WebApp 项目中,我将尽可能多地转换 C#,以便我可以用我喜欢的语言构建尽可能多的应用程序。这几乎包括

program.cs
中的所有内容。

问题点:在

program.cs
的末尾(带有脚手架的身份和示例页面)我们发现了这个调用:

app.MapAdditionalIdentityEndpoints();

我已成功将该扩展方法中的所有内容转换为 VB.NET,并且它可以构建,但我在运行时遇到了障碍。问题集中在这个 lambda 上:

accountGroup.MapPost("/Logout", async (
    ClaimsPrincipal user,
    SignInManager<User> signInManager,
    [FromForm] string returnUrl) =>
{
    await signInManager.SignOutAsync();
    return TypedResults.LocalRedirect($"~/{returnUrl}");
});

因为 VB.NET 不支持 lambda 参数上的属性(例如

<FromForm>
),所以我必须对其进行扩展:

Public Module Extensions
  Private Delegate Function LogoutDelegate(
    User As ClaimsPrincipal,
    SignInManager As SignInManager(Of ApplicationUser),
    <FromForm> ReturnUrl As String) As Task(Of RedirectHttpResult)

  <Extension>
  Public Function MapSomeAdditionalIdentityEndpoints(Endpoints As IEndpointRouteBuilder) As IEndpointConventionBuilder
    Dim oLogoutHandler As LogoutDelegate
    Dim oAccountGroup As RouteGroupBuilder

    oLogoutHandler = AddressOf LogoutAsync

    oAccountGroup = Endpoints.MapGroup("/Account")
    oAccountGroup.MapPost("/Logout", oLogoutHandler)
    
    Return oAccountGroup
  End Function

  Private Async Function LogoutAsync(
    User As ClaimsPrincipal,
    SignInManager As SignInManager(Of ApplicationUser),
    <FromForm> ReturnUrl As String) As Task(Of RedirectHttpResult)

    Await SignInManager.SignOutAsync()

    Return TypedResults.LocalRedirect($"~/{ReturnUrl}")
  End Function
End Module

是的,这是一个冗长的混乱,但是哦,好吧。一旦完成并开始工作,我就会想出一种方法来稍微缩减它。

当我使用此签名时,应用程序在启动时崩溃(

app.Run
)。这是完整的错误消息:

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Private.CoreLib.dll
An action cannot use both form and JSON body parameters.
Below is the list of parameters that we found:

Parameter           | Source
---------------------------------------------------------------------------------`
SignInManager       | Body (Inferred)
ReturnUrl           | Form (Attribute)

这似乎是有道理的,因为

SignInManager
参数没有经过专门修饰。但是,当我稍微改变签名并添加
<FromForm>
属性时,如下所示:

<FromForm> SignInManager As SignInManager(Of ApplicationUser)

...应用程序确实运行。

问题在于,当调用委托函数时,

SignInManager
为空。当我使用
<FromServices>
时,它也是空的,即使
SignInManager
很早就被注册了:

builder.Services.AddIdentityCore<User>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<Context>()
    .AddSignInManager()
    .AddDefaultTokenProviders();

当我运行 C# 版本的 lambda 时,这些行为都不会出现。

我不知道从哪里开始寻找解决方案。我向墙上扔一些奇怪的东西只是为了看看它是否粘住。我已经尝试了所有

From*
属性,我尝试分别从委托和函数的
<FromForm>
参数中删除
ReturnUrl

它会因委托上的装饰而崩溃,但不会因函数而崩溃,并且会因函数上的装饰而运行,但不会因委托而崩溃。但对于后者,当我单击“注销”按钮时,我收到 415 错误。当我移除两个装饰时,会得到 415。

ReturnUrl
更改为
<FromBody>
,以与
SignInManager
的推论保持一致,也会导致崩溃,尽管有一些不同的错误:

Failure to infer one or more parameters.
Below is the list of parameters that we found: 

Parameter           | Source                        
---------------------------------------------------------------------------------
SignInManager       | Body (Inferred)
ReturnUrl           | UNKNOWN        


Did you mean to register the "UNKNOWN" parameters as a Service?

C# 版本中不会出现这种行为。

考虑到所涉及的因素,寻找这个问题的答案已被证明是毫无意义的。我认为我的情况非常罕见。

我是 Blazor 新手;我不确定这里内部发生了什么。为什么推理在我的 VB.NET 版本中导致问题,但在 C# 版本中却没有?我怎样才能运行这段代码?

c# vb.net blazor blazor-server-side
1个回答
0
投票

我是 Blazor 新手;我不确定内部发生了什么。

事实证明,该问题与 Blazor 的内部结构关系不大,而与我的代码中的问题关系更大。我从两个不同的位置获取

IdentityUser
实例:C# 项目和 VB.NET 项目。

这当然把一切都抛之脑后了。参数

SignInManager As SignInManager(Of ApplicationUser)
返回
Nothing
是很自然的,因为该特定类型从未被注册过。一旦我将所有内容切换到一侧(在本例中为
ApplicationUser
),一切就开始正常工作。

向 Aluan Haddad 指出这一点致敬。

© www.soinside.com 2019 - 2024. All rights reserved.