0

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?

+0

Könnten Sie den Teil des Codes zeigen, dass die 'language' an den UI-Kultur abbildet? –

Antwort

0

ASP.NET Core gibt 404 Fehler für nicht übereinstimmende URL wie www.test.com/fr korrekt zurück. Es ist Sache des Browsers, mit einer solchen Antwort umzugehen. Firefox zeigt nur eine leere Seite an, wie Sie beschrieben haben. IE, Chrome und Opera zeigt Seite mit Fehlerbeschreibung, wie:

enter image description here

Sie könnten ASP.NET Core-Verhalten anpassen, wenn Fehlercode zurückgegeben werden soll.

app.UseStatusCodePages("text/plain", "Status code page, status code: {0}"); 

Sie auch Benutzer, um benutzerdefinierte Fehlerseiten bei Anforderungsfehler umleiten könnte:

app.UseStatusCodePagesWithRedirects("/error/{0}"); 

Stellen Sie sicher, Pfad /error/404 korrekt aufgelöst Sie entweder einfache Textnachrichten durch Hinzufügen UseStatusCodePages zu Anwendungskonfiguration verwenden könnte Andernfalls erhalten Sie eine unbegrenzte Umleitung zu dieser Seite.

prüfen Sie diesen Artikel für weitere Informationen: Error Handling in ASP.NET Core