hi
There is no cache URL in the code, it must be a configuration problem. Please check again.
You can debug the application locally to check your configuration.
Thanks @maliming, you were correct.
The issue was related to the fact that there appears to be a bug in .NET were appsettings.{environment}.json deployments in Blazor fails when using anything other than ASPNETCORE_ENVIRONMENT equaling 'Development' or 'Production'.''
https://github.com/dotnet/aspnetcore/issues/25152
There will be no problem with the above functions, you can create a new version of the project to test it.
Great, thank you @mailiming. I also forgot to ask, is there any data that we need to migrate since the schema is changing? I'm also assuming that after the upgrade tests ok, we can just drop the IdentityServer* tables?
Hi malik.masis,
When we execute the following (as shown in Abp documentation)..
var l = validationContext.GetRequiredService<IStringLocalizer<AppNameResource>>();
We receive the following exception at runtime...
System.InvalidOperationException: No service for type 'Microsoft.Extensions.Localization.IStringLocalizer 1[FM.Timepiece.Localization.TimepieceResource] has been registered.
The call to GetRequiredService is initiated in the Validate method of our Dto located in the Application.Contracts project.
Any idea why this method call is not returning the service and erroring out for us?
Hi,
it's on our roadmap, but not a high priority. if you need this, you can implement it yourself
Thank you for the prompt feedback.
It appears that the error occurs when the setting "Authenticate with a Local Account" is turned off for a tenant. We are only using Identity Server for authentication (with separated tenant and host schemas configured) and are not using LDAP. Why does this setting need to be turned on in order to login?
Our Blazor Module's configuration (AppBlazorModule.cs) is:
using System;
using System.IO;
using System.Threading.Tasks;
using Blazorise.Bootstrap5;
using Blazorise.Icons.FontAwesome;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
using Microsoft.AspNetCore.Authentication.Twitter;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using FM.Timepiece.Blazor.Menus;
using FM.Timepiece.EntityFrameworkCore;
using FM.Timepiece.Localization;
using FM.Timepiece.MultiTenancy;
using Microsoft.OpenApi.Models;
using FM.Timepiece.Blazor.Components.Layout;
using Volo.Abp;
using Volo.Abp.Account.Pro.Admin.Blazor.Server;
using Volo.Abp.Account.Pro.Public.Blazor.Server;
using Volo.Abp.Account.Public.Web;
using Volo.Abp.Account.Public.Web.ExternalProviders;
using Volo.Abp.Account.Web;
using Volo.Abp.Account.Public.Web.Impersonation;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Components.Server.LeptonTheme;
using Volo.Abp.AspNetCore.Components.Server.LeptonTheme.Bundling;
using Volo.Abp.AspNetCore.Components.Web.Theming.Routing;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.AuditLogging.Blazor.Server;
using Volo.Abp.Autofac;
using Volo.Abp.AutoMapper;
using Volo.Abp.Identity;
using Volo.Abp.Identity.Pro.Blazor;
using Volo.Abp.Identity.Pro.Blazor.Server;
using Volo.Abp.IdentityServer.Blazor.Server;
using Volo.Abp.LanguageManagement.Blazor.Server;
using Volo.Abp.LeptonTheme.Management.Blazor.Server;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Volo.Abp.TextTemplateManagement.Blazor.Server;
using Volo.Abp.UI.Navigation;
using Volo.Abp.UI.Navigation.Urls;
using Volo.Abp.VirtualFileSystem;
using Volo.Saas.Host;
using Volo.Saas.Host.Blazor;
using Volo.Saas.Host.Blazor.Server;
using Volo.Abp.FluentValidation;
using MudBlazor.Services;
using Syncfusion.Blazor;
namespace FM.Timepiece.Blazor;
[DependsOn(
typeof(TimepieceApplicationModule),
typeof(TimepieceEntityFrameworkCoreModule),
typeof(TimepieceHttpApiModule),
typeof(AbpAspNetCoreMvcUiLeptonThemeModule),
typeof(AbpAutofacModule),
typeof(AbpSwashbuckleModule),
typeof(AbpAccountPublicWebImpersonationModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpAspNetCoreComponentsServerLeptonThemeModule),
typeof(AbpAccountPublicWebIdentityServerModule),
typeof(AbpAccountPublicBlazorServerModule),
typeof(AbpAccountAdminBlazorServerModule),
typeof(AbpAuditLoggingBlazorServerModule),
typeof(AbpIdentityProBlazorServerModule),
typeof(LeptonThemeManagementBlazorServerModule),
typeof(AbpIdentityServerBlazorServerModule),
typeof(LanguageManagementBlazorServerModule),
typeof(SaasHostBlazorServerModule),
typeof(TextTemplateManagementBlazorServerModule)
)]
[DependsOn(typeof(AbpFluentValidationModule))]
public class TimepieceBlazorModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
{
options.AddAssemblyResource(
typeof(TimepieceResource),
typeof(TimepieceDomainModule).Assembly,
typeof(TimepieceDomainSharedModule).Assembly,
typeof(TimepieceApplicationModule).Assembly,
typeof(TimepieceApplicationContractsModule).Assembly,
typeof(TimepieceBlazorModule).Assembly
);
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
ConfigureUrls(configuration);
ConfigureBundles();
ConfigureAuthentication(context, configuration);
ConfigureImpersonation(context, configuration);
ConfigureAutoMapper();
ConfigureVirtualFileSystem(hostingEnvironment);
ConfigureLocalizationServices();
ConfigureSwaggerServices(context.Services);
ConfigureExternalProviders(context, configuration);
ConfigureAutoApiControllers();
ConfigureBlazorise(context);
ConfigureRouter(context);
ConfigureMenu(context);
ConfigureLeptonTheme();
context.Services.AddSyncfusionBlazor();
context.Services.AddMudServices();
}
private void ConfigureUrls(IConfiguration configuration)
{
Configure<AppUrlOptions>(options =>
{
options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(','));
});
}
private void ConfigureBundles()
{
Configure<AbpBundlingOptions>(options =>
{
// MVC UI
options.StyleBundles.Configure(
LeptonThemeBundles.Styles.Global,
bundle =>
{
bundle.AddFiles("/global-styles.css");
}
);
// Blazor UI
options.StyleBundles.Configure(
BlazorLeptonThemeBundles.Styles.Global,
bundle =>
{
bundle.AddFiles("/blazor-global-styles.css");
//You can remove the following line if you don't use Blazor CSS isolation for components
bundle.AddFiles("/FM.Timepiece.Blazor.styles.css");
}
);
});
}
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication()
.AddJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
options.Audience = "Timepiece";
});
}
private void ConfigureImpersonation(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.Configure<SaasHostBlazorOptions>(options =>
{
options.EnableTenantImpersonation = true;
});
context.Services.Configure<AbpIdentityProBlazorOptions>(options =>
{
options.EnableUserImpersonation = true;
});
context.Services.Configure<AbpAccountOptions>(options =>
{
options.TenantAdminUserName = "admin";
options.ImpersonationTenantPermission = SaasHostPermissions.Tenants.Impersonation;
options.ImpersonationUserPermission = IdentityPermissions.Users.Impersonation;
});
}
private void ConfigureVirtualFileSystem(IWebHostEnvironment hostingEnvironment)
{
if (hostingEnvironment.IsDevelopment())
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.ReplaceEmbeddedByPhysical<TimepieceDomainSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}FM.Timepiece.Domain.Shared"));
options.FileSets.ReplaceEmbeddedByPhysical<TimepieceDomainModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}FM.Timepiece.Domain"));
options.FileSets.ReplaceEmbeddedByPhysical<TimepieceApplicationContractsModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}FM.Timepiece.Application.Contracts"));
options.FileSets.ReplaceEmbeddedByPhysical<TimepieceApplicationModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}FM.Timepiece.Application"));
options.FileSets.ReplaceEmbeddedByPhysical<TimepieceBlazorModule>(hostingEnvironment.ContentRootPath);
});
}
}
private void ConfigureSwaggerServices(IServiceCollection services)
{
services.AddAbpSwaggerGen(
options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Timepiece API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
options.CustomSchemaIds(type => type.FullName);
}
);
}
private void ConfigureExternalProviders(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication()
.AddGoogle(GoogleDefaults.AuthenticationScheme, _ => {})
.WithDynamicOptions<GoogleOptions, GoogleHandler>(
GoogleDefaults.AuthenticationScheme,
options =>
{
options.WithProperty(x => x.ClientId);
options.WithProperty(x => x.ClientSecret, isSecret: true);
}
)
.AddMicrosoftAccount(MicrosoftAccountDefaults.AuthenticationScheme, options =>
{
//Personal Microsoft accounts as an example.
options.AuthorizationEndpoint = "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize";
options.TokenEndpoint = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
})
.WithDynamicOptions<MicrosoftAccountOptions, MicrosoftAccountHandler>(
MicrosoftAccountDefaults.AuthenticationScheme,
options =>
{
options.WithProperty(x => x.ClientId);
options.WithProperty(x => x.ClientSecret, isSecret: true);
}
)
.AddTwitter(TwitterDefaults.AuthenticationScheme, options => options.RetrieveUserDetails = true)
.WithDynamicOptions<TwitterOptions, TwitterHandler>(
TwitterDefaults.AuthenticationScheme,
options =>
{
options.WithProperty(x => x.ConsumerKey);
options.WithProperty(x => x.ConsumerSecret, isSecret: true);
}
);
}
private void ConfigureLocalizationServices()
{
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("ar", "ar", "العربية", "ae"));
options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish", "fi"));
options.Languages.Add(new LanguageInfo("fr", "fr", "Français", "fr"));
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский", "ru"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak", "sk"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de"));
options.Languages.Add(new LanguageInfo("es", "es", "Español"));
});
}
private void ConfigureBlazorise(ServiceConfigurationContext context)
{
context.Services
.AddBootstrap5Providers()
.AddFontAwesomeIcons();
}
private void ConfigureMenu(ServiceConfigurationContext context)
{
Configure<AbpNavigationOptions>(options =>
{
options.MenuContributors.Add(new TimepieceMenuContributor());
});
}
private void ConfigureLeptonTheme()
{
Configure<Volo.Abp.AspNetCore.Components.Web.LeptonTheme.LeptonThemeOptions>(options =>
{
options.FooterComponent = typeof(MainFooterComponent);
});
}
private void ConfigureRouter(ServiceConfigurationContext context)
{
Configure<AbpRouterOptions>(options =>
{
options.AppAssembly = typeof(TimepieceBlazorModule).Assembly;
});
}
private void ConfigureAutoApiControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(TimepieceApplicationModule).Assembly);
});
}
private void ConfigureAutoMapper()
{
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<TimepieceBlazorModule>();
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var env = context.GetEnvironment();
var app = context.GetApplicationBuilder();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAbpRequestLocalization();
if (!env.IsDevelopment())
{
app.UseErrorPage();
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseCorrelationId();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseJwtTokenMiddleware();
if (MultiTenancyConsts.IsEnabled)
{
app.UseMultiTenancy();
}
app.UseUnitOfWork();
app.UseIdentityServer();
app.UseAuthorization();
app.UseSwagger();
app.UseAbpSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Timepiece API");
});
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseConfiguredEndpoints();
}
}
Do you use a tiered application template? Is Redis up and running?
Hi @gterdem, we do not used a tiered application template and we do not utilize Redis. We do, however, utilize the separated tenant schema option in our templated solution.
Thanks
Excellent, thanks guys!
For anyone running into this issue.. We resolved the issue by turning off the 'Show local variables for your application when an exception is shown' setting in Azure Application Insights.
Thanks Ma. We did this and things now work as expected.