当 运行 IIS 上的发布版本时,Blazor WebAssembly InvalidCastException
Blazor WebAssembly InvalidCastException when running Published version on IIS
我有一个 Blazor WebAssembly 应用程序,它在调试时运行良好,但在 IIS 上 运行 时抛出异常(已发布):
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Specified cast is not valid.
System.InvalidCastException: Specified cast is not valid.
at Microsoft.AspNetCore.Components.Reflection.MemberAssignment.GetPropertiesIncludingInherited(Type , BindingFlags )+MoveNext()
at Microsoft.AspNetCore.Components.ComponentFactory.CreateInitializer(Type )
at Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider , IComponent )
at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider , Type )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateComponent(Type )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer , RenderBatchBuilder , Int32 , ArrayRange`1 , ArrayRange`1 )
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder , RenderFragment , Exception& )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
这个错误非常无用 i.m.o,因为我找不到确切的原因,而不是 invalid cast exception
。
因为无法在已发布的 IIS 站点上进行调试,所以我将 Console.WriteLine
添加到 Program.cs
和第一个 Index.razor
。但是,错误发生在 Index.razor
被渲染之前。在 await builder.Build().RunAsync();
调用之前我的 Program.main 中的所有代码也能正常工作。
所以我想这与我的App.razor
或MainLayout.razor
有关。现在 MainLayout.razor
位于具有命名空间 Libs.Blazor.Components.Shared
.
的 Razor Class 库中
Program.cs
/// <summary>
/// Program entry
/// </summary>
public class Program {
/// <summary>
/// Entry point of application
/// </summary>
/// <param name="args">Arguments to pass</param>
/// <returns>Task with a result</returns>
public static async Task Main (String[] args) {
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
HttpClient http = new HttpClient() {
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
};
IHostEnvironment hostEnvironment = new HostEnvironment() {
ApplicationName = builder.HostEnvironment.Environment,
EnvironmentName = builder.HostEnvironment.Environment,
ContentRootPath = builder.HostEnvironment.Environment
};
builder.Services.AddScoped(sp => http);
builder.Services.AddScoped(sp => hostEnvironment);
using HttpResponseMessage response = await http.GetAsync("appsettings.json"); //Load the appsettings
using Stream stream = await response.Content.ReadAsStreamAsync();
builder.Configuration.AddJsonStream(stream);
await builder.Build().RunAsync();
} // Main
/// <summary>
/// HotEnvironment filled by WebAssembly
/// </summary>
internal class HostEnvironment :IHostEnvironment {
private String m_EnvironmentName;
private String m_ApplicationName;
private String m_ContentRootPath;
private IFileProvider m_ContentRootFileProvider;
/// <summary>
/// EnvironmentName
/// </summary>
public String EnvironmentName { [DebuggerStepThrough()] get { return m_EnvironmentName; } set { m_EnvironmentName = value; } }
/// <summary>
/// ApplicationName
/// </summary>
public String ApplicationName { [DebuggerStepThrough()] get { return m_ApplicationName; } set { m_ApplicationName = value; } }
/// <summary>
/// ContentRootPath
/// </summary>
public String ContentRootPath { [DebuggerStepThrough()] get { return m_ContentRootPath; } set { m_ContentRootPath = value; } }
/// <summary>
/// FileProvider
/// </summary>
public IFileProvider ContentRootFileProvider { [DebuggerStepThrough()] get { return m_ContentRootFileProvider; } set { m_ContentRootFileProvider = value; } }
} // Class HostEnvironment
} // Class Program
App.razor
<Router AppAssembly="@typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Libs.Blazor.Components.Shared.MainLayout).Assembly }">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Libs.Blazor.Components.Shared.MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(Libs.Blazor.Components.Shared.MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Libs.Blazor.Components.Shared.MainLayout
@namespace Libs.Blazor.Components.Shared
@inherits LayoutComponentBase
<body id="LibsBody" class="LibsBody" style="cursor:default;">
@Body
<div id="LibsHidden"></div>
</body>
所以我很困惑为什么我在 IIS 上得到这个 Invalid Cast Exception
运行 应用程序,但在 VS 中调试它时却没有。
我遇到了同样的问题。对我有用的解决步骤是在托管 IIS 的 Windows 服务器上安装 .net 6 托管包。然后我重新启动了 IIS 服务器并从 VS2022 重新发布了我的应用程序。现在一切正常。希望这有帮助。
我偶然通过查看发布配置文件解决了这个问题。目标运行时以某种方式设置为 Portable,而不是所需的 browser-wasm.
我有一个 Blazor WebAssembly 应用程序,它在调试时运行良好,但在 IIS 上 运行 时抛出异常(已发布):
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Specified cast is not valid.
System.InvalidCastException: Specified cast is not valid.
at Microsoft.AspNetCore.Components.Reflection.MemberAssignment.GetPropertiesIncludingInherited(Type , BindingFlags )+MoveNext()
at Microsoft.AspNetCore.Components.ComponentFactory.CreateInitializer(Type )
at Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider , IComponent )
at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider , Type )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateComponent(Type )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 )
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer , RenderBatchBuilder , Int32 , ArrayRange`1 , ArrayRange`1 )
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder , RenderFragment , Exception& )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry )
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
这个错误非常无用 i.m.o,因为我找不到确切的原因,而不是 invalid cast exception
。
因为无法在已发布的 IIS 站点上进行调试,所以我将 Console.WriteLine
添加到 Program.cs
和第一个 Index.razor
。但是,错误发生在 Index.razor
被渲染之前。在 await builder.Build().RunAsync();
调用之前我的 Program.main 中的所有代码也能正常工作。
所以我想这与我的App.razor
或MainLayout.razor
有关。现在 MainLayout.razor
位于具有命名空间 Libs.Blazor.Components.Shared
.
Program.cs
/// <summary>
/// Program entry
/// </summary>
public class Program {
/// <summary>
/// Entry point of application
/// </summary>
/// <param name="args">Arguments to pass</param>
/// <returns>Task with a result</returns>
public static async Task Main (String[] args) {
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
HttpClient http = new HttpClient() {
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
};
IHostEnvironment hostEnvironment = new HostEnvironment() {
ApplicationName = builder.HostEnvironment.Environment,
EnvironmentName = builder.HostEnvironment.Environment,
ContentRootPath = builder.HostEnvironment.Environment
};
builder.Services.AddScoped(sp => http);
builder.Services.AddScoped(sp => hostEnvironment);
using HttpResponseMessage response = await http.GetAsync("appsettings.json"); //Load the appsettings
using Stream stream = await response.Content.ReadAsStreamAsync();
builder.Configuration.AddJsonStream(stream);
await builder.Build().RunAsync();
} // Main
/// <summary>
/// HotEnvironment filled by WebAssembly
/// </summary>
internal class HostEnvironment :IHostEnvironment {
private String m_EnvironmentName;
private String m_ApplicationName;
private String m_ContentRootPath;
private IFileProvider m_ContentRootFileProvider;
/// <summary>
/// EnvironmentName
/// </summary>
public String EnvironmentName { [DebuggerStepThrough()] get { return m_EnvironmentName; } set { m_EnvironmentName = value; } }
/// <summary>
/// ApplicationName
/// </summary>
public String ApplicationName { [DebuggerStepThrough()] get { return m_ApplicationName; } set { m_ApplicationName = value; } }
/// <summary>
/// ContentRootPath
/// </summary>
public String ContentRootPath { [DebuggerStepThrough()] get { return m_ContentRootPath; } set { m_ContentRootPath = value; } }
/// <summary>
/// FileProvider
/// </summary>
public IFileProvider ContentRootFileProvider { [DebuggerStepThrough()] get { return m_ContentRootFileProvider; } set { m_ContentRootFileProvider = value; } }
} // Class HostEnvironment
} // Class Program
App.razor
<Router AppAssembly="@typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Libs.Blazor.Components.Shared.MainLayout).Assembly }">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Libs.Blazor.Components.Shared.MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(Libs.Blazor.Components.Shared.MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Libs.Blazor.Components.Shared.MainLayout
@namespace Libs.Blazor.Components.Shared
@inherits LayoutComponentBase
<body id="LibsBody" class="LibsBody" style="cursor:default;">
@Body
<div id="LibsHidden"></div>
</body>
所以我很困惑为什么我在 IIS 上得到这个 Invalid Cast Exception
运行 应用程序,但在 VS 中调试它时却没有。
我遇到了同样的问题。对我有用的解决步骤是在托管 IIS 的 Windows 服务器上安装 .net 6 托管包。然后我重新启动了 IIS 服务器并从 VS2022 重新发布了我的应用程序。现在一切正常。希望这有帮助。
我偶然通过查看发布配置文件解决了这个问题。目标运行时以某种方式设置为 Portable,而不是所需的 browser-wasm.