我在这里完全迷失了。我有一个运行.net5的Blazor WASM Hosted,它已部署到Azure应用服务。当没有数据库时,部署到Azure没有问题。它按预期加载并运行。我已经安装了Identity和DBContext。一切都在本地构建,并使用本地SQL示例正常运行。
在Azure上,我创建了一个新的SQLServer和一个SQL数据库。在SQL数据库防火墙设置中,我有“允许Azure服务和资源访问此服务器”以及我的客户端IP(而不是Azure应用程序的IP)的规则。
对于Configuration中的App Service,我有一个名为DefaultConnection的ConnectionString(与appsettings.json中的相同),其连接字符串与SQLDatabase提供的连接字符串相同,源AppConfig,类型为SqlAzure
我正在使用VS 2019 Publish on the Server项目(启动项目)发布到Azure。我选择目标为Azure -> Azure应用服务(Windows)和我的示例名称。配置为Release,Target Framework net5.0,DeploymentMode Framework依赖,Target runtime Portable。
服务配置设置为AzureSqlDatabase,它使用ConnectionName DefaultConnection,配置和密码是在Azure上创建的SQL Server的管理员用户密码设置,SaveConnectionStringValue是Azure应用程序设置。(此自动填充上述应用程序服务配置连接字符串。
当我点击publish时,我在输出中看到所有发布都正确:
Publish Succeeded.
Web App was published successfully http://bbqfriend.azurewebsites.net/
========== Build: 1 succeeded, 0 failed, 6 up-to-date, 0 skipped ==========
========== Publish: 1 succeeded, 0 failed, 0 skipped ==========
Installation of Web App Site extension Microsoft.AspNetCore.AzureAppServices.SiteExtension is in progress...
Restarting the Web App...
Successfully installed Web App extension Microsoft.AspNetCore.AzureAppServices.SiteExtension
Successfully restarted Web App.
但是当页面启动时,它会显示500错误。
如果我返回到Publish and Edit the settings - Database - DefaultConnection并选中Use this Connection string at runtime,选择在ServiceMigrencies中配置的connectionstring,以及在发布时应用此迁移。当我发布这个概要文件时,它将执行迁移以及我在DataContextOnModelCreating覆盖中定义的Seeds
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
#region Identity Seed
modelBuilder.ApplyConfiguration(new ApplicationUserConfiguration());
modelBuilder.ApplyConfiguration(new IdentityRoleConfiguration());
modelBuilder.ApplyConfiguration(new IdentityUserRoleConfiguration());
#endregion
//modelBuilder.ApplyConfiguration(new CountryConfiguration());
}
所以我知道连接字符串是正确的,并且有一个具有正确模型和种子数据的数据库。为什么我得了500分?!?
这是我在Server项目中的appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database={DatabaseName};Trusted_Connection=True;MultipleActiveResultSets=true"
},
"IdentityServer": {
"Clients": {
"XXXX.Client": {
"Profile": "IdentityServerSPA"
}
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.MSSqlServer" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.Authorization.DefaultAuthorizationService": "Warning",
"Microsoft.EntityFrameworkCore": "Warning",
"System": "Warning",
"System.Net.Http.HttpClient*": "Warning",
"IdentityServer4": "Warning",
"Serilog.AspNetCore": "Warning"
}
},
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "DefaultConnection",
"sinkOptionsSection": {
"tableName": "Logs"
},
"columnOptionsSection": {
"additionalColumns": [
{
"ColumnName": "InstanceId"
},
{
"ColumnName": "Origin"
},
{
"ColumnName": "SourceContext"
},
{
"ColumnName": "UserId"
},
{
"ColumnName": "Username"
}
],
"excludeAdditionalProperties": true
}
}
}
]
},
"AllowedHosts": "*"
}
下面是Server项目的Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
//Register the Datacontext and Connection String
services.AddDbContext<DataContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
//Sets up the default Asp.net core Identity Screens - Use Identity Scaffolding to override defaults
services.AddDefaultIdentity<ApplicationUser>( options =>
{
options.SignIn.RequireConfirmedAccount = true;
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireUppercase = true;
options.Password.RequiredUniqueChars = 0;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequiredLength = 8;
options.User.RequireUniqueEmail = true;
})
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<DataContext>();
//Associates the User to Context with Identity
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, DataContext>( options =>
{
options.IdentityResources["openid"].UserClaims.Add(JwtClaimTypes.Role);
options.ApiResources.Single().UserClaims.Add(JwtClaimTypes.Role);
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove(JwtClaimTypes.Role);
//Adds authentication handler
services.AddAuthentication().AddIdentityServerJwt();
//Register Repositories for Dependency Injection
services.AddScoped<ICountryRepository, CountryRepository>();
services.AddControllersWithViews();
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext dataContext)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseMigrationsEndPoint();
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//AutoMigrates data
//dataContext.Database.Migrate();
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseSerilogIngestion();
app.UseSerilogRequestLogging();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
}
下面是服务器项目的Program.cs
public class Program
{
public static void Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.WithProperty("InstanceId", Guid.NewGuid())
.Enrich.WithProperty("Origin", "Server")
.CreateLogger();
try
{
Log.Information("Starting up");
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
下面是客户端项目的Program.cs
public static async Task Main(string[] args)
{
//Serilog
var levelSwitch = new LoggingLevelSwitch();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(levelSwitch)
.Enrich.WithProperty("InstanceId", Guid.NewGuid())
.Enrich.FromLogContext()
.WriteTo.BrowserHttp(controlLevelSwitch: levelSwitch)
.CreateLogger();
Log.ForContext<Program>().Information("Client has started");
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddLogging(logging =>
{
logging.ClearProviders();
logging.AddSerilog(dispose: true);
});
builder.Services.AddHttpClient("XXX.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
// Supply HttpClient instances that include access tokens when making requests to the server project
builder.Services.AddTransient(sp =>
sp.GetRequiredService<IHttpClientFactory>()
.CreateClient("XXXX.ServerAPI"));
builder.Services.AddApiAuthorization()
.AddAccountClaimsPrincipalFactory<RolesClaimsPrincipalFactory>();
//Register Services
var baseAddress = new Uri($"{builder.HostEnvironment.BaseAddress}api/");
void RegisterTypedClient<TClient, TImplementation>(Uri apiBaseUrl)
where TClient : class where TImplementation : class, TClient
{
builder.Services.AddHttpClient<TClient, TImplementation>(client => client.BaseAddress = apiBaseUrl)
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
}
RegisterTypedClient<ICountryService, CountryService>(baseAddress);
await builder.Build().RunAsync();
}
我确实配置了Serilog,它看起来也在工作。以下是我在服务器启动期间看到的错误消息
System.InvalidOperationException: Startup assembly Microsoft.ApplicationInsights.StartupBootstrapper failed to execute. See the inner exception for more details.
---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.ApplicationInsights.StartupBootstrapper, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
File name: 'Microsoft.ApplicationInsights.StartupBootstrapper, Culture=neutral, PublicKeyToken=null'
at System.Reflection.RuntimeAssembly.InternalLoad(ObjectHandleOnStack assemblyName, ObjectHandleOnStack requestingAssembly, StackCrawlMarkHandle stackMark, Boolean throwOnFileNotFound, ObjectHandleOnStack assemblyLoadContext, ObjectHandleOnStack retAssembly)
at System.Reflection.RuntimeAssembly.InternalLoad(AssemblyName assemblyName, RuntimeAssembly requestingAssembly, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, AssemblyLoadContext assemblyLoadContext)
at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.ExecuteHostingStartups()
--- End of inner exception stack trace ---
和
System.InvalidOperationException: Startup assembly DiagnosticServices.HostingStartup failed to execute. See the inner exception for more details.
---> System.IO.FileNotFoundException: Could not load file or assembly 'DiagnosticServices.HostingStartup, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
File name: 'DiagnosticServices.HostingStartup, Culture=neutral, PublicKeyToken=null'
at System.Reflection.RuntimeAssembly.InternalLoad(ObjectHandleOnStack assemblyName, ObjectHandleOnStack requestingAssembly, StackCrawlMarkHandle stackMark, Boolean throwOnFileNotFound, ObjectHandleOnStack assemblyLoadContext, ObjectHandleOnStack retAssembly)
at System.Reflection.RuntimeAssembly.InternalLoad(AssemblyName assemblyName, RuntimeAssembly requestingAssembly, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, AssemblyLoadContext assemblyLoadContext)
at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.ExecuteHostingStartups()
--- End of inner exception stack trace ---
更新我能够复制上述错误消息,并通过Serilog记录到数据库中。
因此,我们可以看到来自Server Program.cs Main方法的“Starting up”(启动)(上面),下一个条目是来自BulletyFramework Model Validation。然后是错误。我可以看到作为异常源的Microsoft.AspNetCore.Hosting.Diagnostics的空间。
1.我试图添加一个Nuget参考,但没有做什么
1.我试图添加对已添加服务的引用。AddApplicationInsightsTelemetry();将ApplicationInsights InstrumentationKey添加到appsettings.json(它已经作为变量存在于Azure中),但这没有任何作用
1.我添加了一个引用,并添加了
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>().UseAzureAppServices();
});
根据这里找到的解决方法,https://github.com/dotnet/extensions/issues/2566没有帮助
更新第2天
添加更多信息,因为我仍然得到相同的例外。我很好奇这是否是版本之间的兼容性问题。我的应用程序是.net5,并使用.net5抢先体验在Azure上运行。
以下是我为服务器项目准备的Nuget软件包
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="5.0.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="5.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="5.0.1" />
<PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="5.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Serilog.AspNetCore.Ingestion" Version="1.0.0-dev-00012" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.MSSqlServer" Version="5.6.0" />
</ItemGroup>
以下是客户端项目的Nuget包
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="5.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
<PackageReference Include="Serilog.Sinks.BrowserHttp" Version="1.0.0-dev-00012" />
<PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
</ItemGroup>
我试着从客户端和服务器项目中删除Serilog。我仍然得到了500。
在删除Serilog后,我尝试从https://github.com/dotnet/extensions/issues/2566使用. xmlAzureAppServices(),但也没有成功。
我注意到一个额外的错误消息
2021-01-06 19:00:38.322 +00:00 [Error] Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware: An unhandled exception has occurred while executing the request.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Extensions.DependencyInjection.IdentityServerBuilderConfigurationExtensions.<>c.<AddSigningCredentials>b__10_2(IServiceProvider sp)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at ... (removed for post size)
- 当我将我的网站部署为Blazor WebAssembly托管解决方案时,我已经能够将此隔离为一个问题。我能够得到一个版本的我的网站,这是升级到.net5 PRE切换从Blazor WebAssembly到Blazor WebAssembly托管。.net5版本能够毫无问题地部署到Azure。当部署WebAssembly托管版本时,我得到了500个错误。因此,这与将Blazor WebAssembly托管解决方案部署到Azure有关。
我还尝试创建了一个开箱即用的Blazor WebAssembly托管解决方案,没有身份验证,并将其部署到Azure。这工作没有问题。然而,当我创建一个开箱即用的Blazor WebAssembly托管身份验证(个人用户帐户存储在应用程序中)并将其部署到Azure时,它失败了500!
1条答案
按热度按时间qyuhtwio1#
最简单的方法让它工作:
将环境变量
ASPNETCORE_ENVIRONMENT
添加/设置为Development
.你的托管Blazor WASMwith Identity将最终在Azure应用服务中运行
如果你不想要上面的简单方法,那么可以这样做:
1.按照本文生成自签名证书:
(in生成自签名证书部分)https://gavilan.blog/2020/08/18/blazor-using-a-self-signed-certificate-for-identityserver4-in-azure-app-service/
1.记住您用于生成的证书的密码。
1.将证书放在您的项目中(例如在服务器项目中)
1.将这些添加到
appsettings.json
文件中:1.再次发布应用程序。