wake-up-neo.com

Leere href nach dem Upgrade auf asp.net core 2.2

Wir haben eine ASP.NET Core 2.1-Website erstellt, auf der URLs wie www.example.org/uk und www.example.org/de funktionieren, welche resx-Dateien und Inhalte angezeigt werden sollen. Nach dem Upgrade auf ASP.NET Core 2.2 werden die Seiten geladen, aber alle generierten Links erzeugen leere/leere Href's.

Zum Beispiel ein Link dies:

<a asp-controller="Home" asp-action="Contact">@Res.ContactUs</a>

wird in 2.2 eine leere href erzeugen wie folgt:

<a href="">Contact us</a>

Aber in 2.1 bekommen wir richtige href:

<a href="/uk/contact">Contact us</a>

Wir verwenden eine Constraint Map , um die URL-basierte Sprachfunktion zu verwalten - hier ist der Code:

Startup.cs

// configure route options {lang}, e.g. /uk, /de, /es etc
services.Configure<RouteOptions>(options =>
{
    options.LowercaseUrls = true;
    options.AppendTrailingSlash = false;
    options.ConstraintMap.Add("lang", typeof(LanguageRouteConstraint));
 });

 ...

app.UseMvc(routes =>
{
    routes.MapRoute(
       name: "LocalizedDefault",
       template: "{lang:lang}/{controller=Home}/{action=Index}/{id?}");
}

LanguageRouteConstraint.cs

public class LanguageRouteConstraint : IRouteConstraint
{
    private readonly AppLanguages _languageSettings;

    public LanguageRouteConstraint(IHostingEnvironment hostingEnvironment)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(hostingEnvironment.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

        IConfigurationRoot configuration = builder.Build();

        _languageSettings = new AppLanguages();
        configuration.GetSection("AppLanguages").Bind(_languageSettings);
    }

    public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (!values.ContainsKey("lang"))
        {
            return false;
        }

        var lang = values["lang"].ToString();
        foreach (Language lang_in_app in _languageSettings.Dict.Values)
        {
            if (lang == lang_in_app.Icc)
            {
                return true;
            }
        }
        return false;
    }
}

Ich habe das Problem eingegrenzt, aber keinen Weg gefunden, es zu lösen. Grundsätzlich in 2.2. Einige Parameter werden in der obigen IRouteConstraint Match-Methode nicht festgelegt, z. 

httpContext = null
route = {Microsoft.AspNetCore.Routing.NullRouter)

In 2.1 

 httpContext = {Microsoft.AspNetCore.Http.DefaultHttpContext}
 route = {{lang:lang}/{controller=Home}/{action=Index}/{id?}}

Der einzige Unterschied zwischen 2.1 und 2.2 besteht darin, dass ich mich geändert habe 

var builder = new ConfigurationBuilder()
   .SetBasePath(Directory.GetCurrentDirectory())
   .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

folgendes (aufgrund von https://github.com/aspnet/AspNetCore/issues/4206 )

 var builder = new ConfigurationBuilder()
    .SetBasePath(hostingEnvironment.ContentRootPath) // using IHostingEnvironment 
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

Irgendwelche Ideen?

Update Gemäß https://docs.Microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-2.2#parameter-transformer-reference ASP .NET Core 2.2 verwendet EndpointRouting, während 2.1 die Basislogik von IRouter verwendet. Das erklärt mein Problem. Nun, meine Frage wäre dann, wie wird der Code für 2.2 aussehen, um das neue EndpointRouting zu verwenden?

4
Sha
// Use the routing logic of ASP.NET Core 2.1 or earlier:
services.AddMvc(options => options.EnableEndpointRouting = false)
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
1
Diyar

Unterschiede zu früheren Versionen von Routing erklärt, was hier passiert (Schwerpunkt meines):

Die Verbindungsgenerierung Algorithmus für ungültigen Umgebungswert verhält sich bei Verwendung des Endpunktrouting anders.

Ambient value invalidation ist der Algorithmus, der entscheidet, welche Routenwerte aus der aktuell ausgeführten Anforderung (die Umgebungswerte) in Verbindungserzeugungsvorgängen verwendet werden können. Beim konventionellen Routing werden bei der Verknüpfung mit einer anderen Aktion immer zusätzliche Routenwerte für ungültig erklärt. Das Attributrouting hatte dieses Verhalten vor der Veröffentlichung von ASP.NET Core 2.2 nicht. In früheren Versionen von ASP.NET Core führten Verknüpfungen zu einer anderen Aktion, die dieselben Routenparameternamen verwenden, zu Verbindungserzeugungsfehlern. In ASP.NET Core 2.2 oder höher machen beide Formen des Routings Werte ungültig, wenn eine Verknüpfung zu einer anderen Aktion hergestellt wird.

...

Ambient-Werte werden nicht wiederverwendet, wenn das verknüpfte Ziel eine andere Aktion oder Seite ist.

In Ihrem Beispiel ist lang ein Umgebungswert und wird daher nicht wiederverwendet, wenn Sie von Home/Index zu Home/About wechseln (andere Aktion). Ohne einen für lang angegebenen Wert gibt es keine übereinstimmende Aktion. Daher wird eine leere href generiert. Dies wird auch in den Dokumenten als ein Unterschied des Endpunktroutings beschrieben:

Endpunkt-Routing erzeugt jedoch eine leere Zeichenfolge, wenn die Aktion nicht vorhanden ist. Endpunkt-Routing nimmt nicht an, dass der Endpunkt vorhanden ist, wenn die Aktion nicht vorhanden ist.

Wenn Sie das Endpunktrouting weiterhin verwenden möchten, müssen Sie den Wert lang von Ihrem Controller in Ihre Ansicht übergeben und dann explizit festlegen. Hier ist ein Beispiel:

public class HomeController : Controller
{
    public IActionResult Index(string lang)
    {
        ViewData["lang"] = lang; // Using ViewData just for demonstration purposes.
        return View();
    }
}
<a asp-controller="Home" asp-action="Contact"
    asp-route-lang="@ViewData["lang"]">@Res.ContactUs</a>

Sie können dies mit z. ein Aktionsfilter, aber die Konzepte sind immer noch die gleichen. Ich kann nicht erkennen, dass es einen anderen Weg gibt, um damit umzugehen (z. B. einen bestimmten Wert als "Ambient" kennzeichnen zu können), aber vielleicht kann jemand anderes dazu beitragen.

1
Kirk Larkin