Westwind.Globalization
Localization Admin is not working
Hello, I have a Web API project in whose wwwroot the LocalizationAdmin folder is located. The LocalizationAdmin works locally, but as soon as the project is hosted on Azure, the same problem occurs as here: https://support.west-wind.com/Thread4M60DB5NJ.wwt When hosting, a VueJS project is copied to the wwwroot folder and then hosted together. Maybe this is the problem.
This is our configuration:
public static void AddLocalizationServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddLocalization(options => options.ResourcesPath = "Properties");
services.AddSingleton(typeof(IStringLocalizerFactory), typeof(DbResStringLocalizerFactory));
services.AddSingleton(typeof(IHtmlLocalizerFactory), typeof(DbResHtmlLocalizerFactory));
services.AddWestwindGlobalization(opt =>
{
opt.ResourceAccessMode = ResourceAccessMode.DbResourceManager;
opt.ConnectionString = configuration.GetConnectionString("DefaultConnection");
// Database provider used - Sql Server is the default
opt.DataProvider = DbResourceProviderTypes.SqlServer;
// The table in which resources are stored
opt.ResourceTableName = "qscLocalizations";
opt.AddMissingResources = false;
opt.ResxBaseFolder = "~/Properties/";
// Set up security for Localization Administration form
opt.ConfigureAuthorizeLocalizationAdministration(actionContext =>
{
// return true or false whether this request is authorized
return true; //actionContext.HttpContext.User.Identity.IsAuthenticated;
});
});
services.AddMvc()
.AddNewtonsoftJson()
.AddViewLocalization()
.AddDataAnnotationsLocalization();
services.AddTransient<IViewLocalizer, DbResViewLocalizer>();
}
We also had to write this because there were problems with Swagger:
public void Apply(ApplicationModel application)
{
if (application != null)
{
application.Controllers.FirstOrDefault(c => c.ControllerName == "LocalizationAdministration").ApiExplorer.IsVisible = false;
application.Controllers.FirstOrDefault(c => c.ControllerName == "JavaScriptLocalizationResources").ApiExplorer.IsVisible = false;
}
}

I don't know.
The admin page should be fully self-contained from any other client side libraries.
+++ Rick ---
This seems to be the error:
"Exception": {
"Type": "FileNotFoundException",
"Message": "Could not find file 'C:\\home\\site\\wwwroot\\Properties'.",
"StackTrace": " at System.IO.FileSystem.CreateDirectory(String fullPath, Byte[] securityDescriptor)\r\n at System.IO.DirectoryInfo.Create()\r\n at Westwind.Globalization.DbResXConverter.FormatResourceSetPath(String resourceSet) in D:\\projects\\Libraries\\Westwind.Globalization\\src\\Westwind.Globalization\\Utilities\\DbResXConverter.cs:line 549\r\n at WestWind.Globalization.AspNetCore.Controllers.JavaScriptLocalizationResourcesController.ProcessRequest() in D:\\projects\\Libraries\\Westwind.Globalization\\src\\NetCore\\Westwind.Globalization.AspnetCore\\Controllers\\JavaScriptLocalizationResourcesController.cs:line 137\r\n at lambda_method586(Closure, Object, Object[])\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()\r\n--- End of stack trace from previous location ---\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()\r\n--- End of stack trace from previous location ---\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()\r\n--- End of stack trace from previous location ---\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)\r\n at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)\r\n at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)\r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)\r\n at Program.<>c__DisplayClass0_0.<<<Main>$>b__2>d.MoveNext() in D:\\a\\1\\s\\qsc.fendt.Backend\\Program.cs:line 70\r\n--- End of stack trace from previous location ---\r\n at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)\r\n at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()"
},
services.AddLocalization(options => options.ResourcesPath = "Properties");
services.AddSingleton(typeof(IStringLocalizerFactory), typeof(DbResStringLocalizerFactory));
services.AddSingleton(typeof(IHtmlLocalizerFactory), typeof(DbResHtmlLocalizerFactory));
services.AddWestwindGlobalization(opt =>
{
opt.ResourceAccessMode = ResourceAccessMode.DbResourceManager;
opt.ConnectionString = configuration.GetConnectionString("DefaultConnection");
// Database provider used - Sql Server is the default
opt.DataProvider = DbResourceProviderTypes.SqlServer;
// The table in which resources are stored
opt.ResourceTableName = "qscLocalizations";
opt.AddMissingResources = false;
opt.ResxBaseFolder = "~/Properties/";
// Set up security for Localization Administration form
opt.ConfigureAuthorizeLocalizationAdministration(actionContext =>
{
// return true or false whether this request is authorized
return true; //actionContext.HttpContext.User.Identity.IsAuthenticated;
});
});
services.AddMvc()
.AddNewtonsoftJson()
.AddViewLocalization()
.AddDataAnnotationsLocalization();
services.AddTransient<IViewLocalizer, DbResViewLocalizer>();
Do we need the "Properties" Folder, if we do not use resx?