Search code examples
razorroutes

How can I support a working URL on (edit, details and delete) even with an extension for culture switch


When I show the details of a contact the URL looks for example like this

https://localhost:44379/ContactsOverview/Details?id=-1455774161

When I change the culture via culture switch dropdown the URL gets extended by

https://localhost:44379/ContactsOverview/Details?culture=en and overrides my ?id=-1455774161

When I try manual URL in combination like

https://localhost:44379/ContactsOverview/Details?id=-1455774161?culture=en the page can not be retrieved

the same on https://localhost:44379/ContactsOverview/Details?culture=en?id=-1455774161 doesn't work either

I tried on @page with "id:min(1)}/{handler?}" it does not work either. How can I solve it?

====================================================== Update 3.2.2021 =====

I read this article and implemented according to https://www.mikesdotnetting.com/article/348/razor-pages-localisation-seo-friendly-urls

==== Sample code =====

using Microsoft.AspNetCore.Mvc.ApplicationModels;
 
namespace Localisation.RouteModelConventions
{
    public class CultureTemplatePageRouteModelConvention : IPageRouteModelConvention
    {
        public void Apply(PageRouteModel model)
        {
            var selectorCount = model.Selectors.Count;
 
            for (var i = 0; i < selectorCount; i++)
            {
                var selector = model.Selectors[i];
 
                model.Selectors.Add(new SelectorModel
                {
                    AttributeRouteModel = new AttributeRouteModel
                    { 
                        Order = -1,
                        Template = AttributeRouteModel.CombineTemplates("{culture?}", selector.AttributeRouteModel.Template),
                    }
                });
            }
        }
    }
}

and added in the startup

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages(options => {
        options.Conventions.Add(new CultureTemplatePageRouteModelConvention());
    });
}

As a result I achieved that the url manually works like I want to

https://localhost:44379/EN/Contacts/Edit?id=-1455774161

and the page starts every thing seems cool :-)

Now I tried as described to implement the Razor page url calling

I tried diffent kind of ways. However non works... Any Help?

Samples of what I tried

======== Index Razor Page ================

@page
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@model WorkCollaboration.Pages.ContactsOverview.IndexModel

@{
    ViewData["Title"] = "Index";
    var requestCultureFeature = HttpContext.Features.Get<IRequestCultureFeature>();
    var requestCulture = requestCultureFeature.RequestCulture;
}

@inject IViewLocalizer Localizer
@await Component.InvokeAsync("NToastNotify")

<h1>@Localizer["Index"]</h1>
<h4>@Localizer["Contacts Overview"]</h4>
<p>
    <a asp-page="/Contacts/Create">@Localizer["Create New"]</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.ContactsOverview[0].ContactId)<br />
                @Html.DisplayNameFor(model => model.ContactsOverview[0].FirstName)
                @Html.DisplayNameFor(model => model.ContactsOverview[0].LastName)<br />
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ContactsOverview[0].SupId)
                @Html.DisplayNameFor(model => model.ContactsOverview[0].SupName)<br />
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ContactsOverview[0].CusId)
                @Html.DisplayNameFor(model => model.ContactsOverview[0].CusName)<br />
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.ContactsOverview)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.ContactId)<br>
                    @Html.DisplayFor(modelItem => item.FirstName)
                    @Html.DisplayFor(modelItem => item.LastName)<br>
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.SupId)

                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.CusId)
                    @Html.DisplayFor(modelItem => item.CusName)<br>

                </td>
                <td>
                    @*<a asp-route-culture="@Request.RouteValues["culture"]" asp-page="@Localizer["UrlEdit"]" asp-route-id="@item.ContactId">@Localizer["Edit"]</a>
                    <a asp-route-culture="@Request.RouteValues["culture"]" asp-page="@Localizer.GetString("UrlEdit")">Test</a>
                    <a asp-page="/EN/Contacts/Edit" asp-route-id="@item.ContactId">@Localizer["Edit"]</a>*@
                    <a asp-page="/Contacts/Edit" asp-route-id="@item.ContactId">@Localizer["Edit"]</a>
                    <a asp-page="/ContactsOverview/Details" asp-route-id="@item.ContactId">@Localizer["Details"]</a>
                    <a asp-page="/Contacts/Delete" asp-route-id="@item.ContactId">@Localizer["Delete"]</a>
                </td>
            </tr>
        }
    </tbody>
</table>

So first variant is the straight one I just put the url in

<a asp-page="/EN/Contacts/Edit" asp-route-id="@item.ContactId">@Localizer["Edit"]</a>

:-(

2nd Varinat I tried concotinate the URL using my Ressource file

<a asp-route-culture="@Request.RouteValues["culture"]" asp-page="@Localizer["UrlEdit"]" asp-route-id="@item.ContactId">@Localizer["Edit"]</a>

3rd Varinat doesn't work either

<a asp-route-culture="@Request.RouteValues["culture"]" asp-page="@Localizer.GetString("UrlEdit")">Test</a>

Any Ideas?

In the description the refer to the script

<script>
    var segments = location.pathname.split('/');
    var el = document.getElementById("culture-options");
    el.addEventListener("change", () => {
        var culture = el.options[el.selectedIndex].value;
        if (segments.length > 2) {
            segments[1] = culture;
            location.href = segments.join('/');
        } else {
            location.href = '/' + culture + location.pathname;
        }
    });
</script>

I'm not really sure where to put it. My thoughts were to replace the one in default from commonswitchclass implementation. However this did not work either since then the ?id in the url is cut off

Help is appreciated very much


Solution

  • This description work many other don't

    Asp.net core Localization always returns english clulture

    :-(