Ich versuche, eine ASP.NET MVC-Core Site-Setup beispielsweise mehrsprachig für mehrere Länder zu unterstützen:ASP.NET MVC Core-Strecke Problem
- www.test.com/au/en (Australien , englisch)
- www.test.com/au/de (Australien, Deutsch)
Um die Kultur für den aktuellen Benutzer festgelegt, fand ich diesen Code
public static class GetRoutesMiddlewareExtensions
{
public static IApplicationBuilder UseGetRoutesMiddleware(this IApplicationBuilder app, Action<IRouteBuilder> configureRoutes)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
var routes = new RouteBuilder(app)
{
DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
};
configureRoutes(routes);
routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices));
var router = routes.Build();
return app.UseMiddleware<GetRoutesMiddleware>(router);
}
}
public class GetRoutesMiddleware
{
private readonly RequestDelegate next;
private readonly IRouter _router;
public GetRoutesMiddleware(RequestDelegate next, IRouter router)
{
this.next = next;
_router = router;
}
public async Task Invoke(HttpContext httpContext)
{
var context = new RouteContext(httpContext);
context.RouteData.Routers.Add(_router);
await _router.RouteAsync(context);
if (context.Handler != null)
{
httpContext.Features[typeof(IRoutingFeature)] = new RoutingFeature()
{
RouteData = context.RouteData,
};
}
// proceed to next...
await next(httpContext);
}
}
habe ich eine RequestCultureProvider, die wie folgt aussieht:
public class RequestCultureProvider : IRequestCultureProvider
{
public Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
{
if (httpContext.GetRouteValue("language") == null)
{
return Task.FromResult(new ProviderCultureResult("en", "en"));
}
var langauge = httpContext.GetRouteValue("language").ToString().ToLower();
return Task.FromResult(new ProviderCultureResult(langauge, langauge));
}
}
Um Setup-Routen habe ich diese Methode:
private readonly Action<IRouteBuilder> GetRoutes =
routes =>
{
routes.MapRoute(name: "Default",
template: "{area}/{language}/{controller}/{action}",
defaults: new { area = "au", language = "en", controller = "home", action = "Index" },
constraints: new { area = new RequiredRouteConstraint(), language = new RegexRouteConstraint("^(en|de)$") });
};
Dann in Startup.cs im Configure, dann habe ich
// setup routes
app.UseGetRoutesMiddleware(GetRoutes);
// add localization
var supportedCultures = new List<CultureInfo>() {
new CultureInfo("en"),
new CultureInfo("de"),
};
var requestLocalizationOptions = new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(supportedCultures.First()),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures,
};
requestLocalizationOptions.RequestCultureProviders.Clear();
requestLocalizationOptions.RequestCultureProviders.Add(
new RequestCultureProvider()
);
app.UseRequestLocalization(requestLocalizationOptions);
Ich bin nicht sicher, ob es relevant ist, aber um meine Ansichten in einer organisierten Weise zu gestalten, habe ich einen CultureViewExpander eingerichtet, der so aussieht:
public class CultureViewExpander : IViewLocationExpander
{
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
return viewLocations.Select(s => s.Replace("%1", CultureInfo.CurrentUICulture.TwoLetterISOLanguageName));
}
public void PopulateValues(ViewLocationExpanderContext context)
{
context.Values.Add("Language", CultureInfo.CurrentUICulture.TwoLetterISOLanguageName);
}
}
und es ist in der Startup.cs, in dem ConfigureServices als
services.Configure<RazorViewEngineOptions>(o =>
{
o.ViewLocationExpanders.Add(new CultureViewExpander());
// {0} for the action
// {1} for the controller
// {2} for the area
// %1 for language
o.ViewLocationFormats.Clear();
o.ViewLocationFormats.Add("/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
o.AreaViewLocationFormats.Clear();
o.AreaViewLocationFormats.Insert(0, "/Areas/{2}/Views/{1}/%1/{0}" + RazorViewEngine.ViewExtension);
});
Die unterstützten Sprachen funktionieren umgesetzt, aber wenn ich navigieren zu www.test.com/au/fr, habe ich einfach bekomme einen leeren Bildschirm, aber ich brauche es, um eine 404 zurückzugeben. Wie kann ich es bekommen, um eine 404 für einen ungültigen Routenwert zurückzugeben?
Könnten Sie den Teil des Codes zeigen, dass die 'language' an den UI-Kultur abbildet? –