Como você impõe o roteamento em minúsculas no ASP.NET Core?

94

No ASP.NET 4, isso era tão fácil quanto routes.LowercaseUrls = true;noRegisterRoutes manipulador do aplicativo.

Não consigo encontrar um equivalente no ASP.NET Core para conseguir isso. Eu acho que seria aqui:

app.UseMvc(configureRoutes =>
{
    configureRoutes.MapRoute("Default", "{controller=App}/{action=Index}/{id?}");
});

Mas nada configureRoutesparece permitir isso ... a menos que haja um método de extensão em algum lugar que eu não consigo encontrar nos documentos, talvez?

mariocatch
fonte

Respostas:

202

Para ASP.NET Core:

Adicione a seguinte linha ao ConfigureServicesmétodo da Startupclasse.

services.AddRouting(options => options.LowercaseUrls = true);

Obrigado a Skorunka pela resposta como um comentário. Achei que valia a pena promover para uma resposta real.

jogos artesanais
fonte
35
É importante notar que você deve colocar isso ANTES de realmente chamar AddMvc()seu Startup.ConfigureServices()método. AddRouting()que também é chamado de AddMvc()usa as Tryvariantes dos métodos para adicionar dependências à coleção de serviços. Portanto, quando ele vir que as dependências de roteamento já foram adicionadas, ele ignorará essas partes da AddMvc()lógica de configuração.
Nick Albrecht
Mudar para uma resposta correta, já que a minha foi durante a transição do asp 4 para o core.
mariocatch de
@NickAlbrecht não parece fazer diferença se for chamado antes ou depois (pelo menos a partir do ASP.NET Core 5.0). AddRouting () será chamado duas vezes de qualquer maneira, então não importa em que ordem.
Thomas Levesque
Acredito que isso tenha sido feito em torno do .NET Core 3.x. Eles mudaram para que o roteamento fosse um recurso autônomo em vez de empacotado com o MVC. Eu não acredito que o roteamento seja chamado do AddMvc(ou AddControllersWithViewsse você não precisar do RazorPages) mais. Portanto, a ordem só importa realmente se você estiver usando AspNetCore 2. (Não me lembro se essa era uma opção em 1.x). No entanto, eles fizeram dividir o comportamento minúsculas em duas configurações, então se você quiser endereços de caso totalmente inferiores, você precisa configurar tanto LowercaseUrlse LowercaseQueryStringspara true.
Nick Albrecht
37

Atualização na versão ASP.NET Core> = 2.2

No ASP.NET Core 2.2 , junto com letras minúsculas, você também pode fazer sua rota tracejada usando ConstraintMapque fará sua rota /Employee/EmployeeDetails/1para em /employee/employee-details/1vez de /employee/employeedetails/1.

Para fazer isso, primeiro crie a SlugifyParameterTransformerclasse deve ser da seguinte forma:

public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
    public string TransformOutbound(object value)
    {
        // Slugify value
        return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
    }
}

Para ASP.NET Core 2.2 MVC:

No ConfigureServicesmétodo da Startupaula:

services.AddRouting(option =>
{
    option.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
});

E a configuração da rota deve ser a seguinte:

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

Para ASP.NET Core 2.2 Web API:

No ConfigureServicesmétodo da Startupaula:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options => 
    {
        options.Conventions.Add(new RouteTokenTransformerConvention(new SlugifyParameterTransformer()));
    }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Para ASP.NET Core> = 3.0 MVC:

No ConfigureServicesmétodo da Startupaula:

services.AddRouting(option =>
{
    option.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
});

E a configuração da rota deve ser a seguinte:

app.UseEndpoints(endpoints =>
{
      endpoints.MapAreaControllerRoute(
          name: "AdminAreaRoute",
          areaName: "Admin",
          pattern: "admin/{controller:slugify=Dashboard}/{action:slugify=Index}/{id:slugify?}");

      endpoints.MapControllerRoute(
          name: "default",
          pattern: "{controller:slugify}/{action:slugify}/{id:slugify?}",
          defaults: new { controller = "Home", action = "Index" });
});

Para ASP.NET Core> = 3.0 API da Web:

No ConfigureServicesmétodo da Startupaula:

services.AddControllers(options => 
{
    options.Conventions.Add(new RouteTokenTransformerConvention(new SlugifyParameterTransformer()));
});

Para ASP.NET Core> = 3.0 Páginas Razor:

No ConfigureServicesmétodo da Startupaula:

services.AddRazorPages(options => 
{
    options.Conventions.Add(new PageRouteTransformerConvention(new SlugifyParameterTransformer()));
})

Isto fará o /Employee/EmployeeDetails/1caminho para/employee/employee-details/1

TanvirArjel
fonte
Tentei este código e também o código oficial da Microsoft, mas o transformador de parâmetro "slugify" não surtiu efeito. É apenas ignorado pelo sistema de roteamento (para que os URLs não sejam substituídos por tracejados). Para verificar a mim mesmo, coloquei o logger no método TransformOutbound (), mas nenhuma chamada de lá.
user3172616
OK! Deixa eu verificar, por favor!
TanvirArjel
@ user3172616 Eu verifiquei agora mesmo! está funcionando como esperado! como gerar rota como employee-details. Você poderia me mostrar sua configuração, por favor?
TanvirArjel
@ user3172616 você está usando o roteamento de atributo na rota que testou?
TanvirArjel de
Eu uso a abordagem de roteamento padrão (não o roteamento de atributo) em uma nova solução v2.2 principal no Visual Studio. Existem duas capturas de tela (código c # e código .cshtml). Tentei gerar links de maneiras diferentes sem nenhum efeito. imgur.com/a/L8dCF6c
user3172616
21

Como outras respostas indicam, acrescentando:

services.Configure<RouteOptions>(options => options.LowercaseUrls = true);

antes

services.AddMvc(...)

funciona muito bem, mas também quero acrescentar que, se você usar o Identity, também precisará de:

services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
    var appCookie = options.Cookies.ApplicationCookie;
    appCookie.LoginPath = appCookie.LoginPath.ToString().ToLowerInvariant();
    appCookie.LogoutPath = appCookie.LogoutPath.ToString().ToLowerInvariant();
    appCookie.ReturnUrlParameter = appCookie.ReturnUrlParameter.ToString().ToLowerInvariant();
});

E, obviamente, substitua ambos IdentityUsere IdentityRolepor suas próprias classes, se necessário.

Acabei de testar isso com o .NET Core SDK 1.0.4 e o runtime 1.0.5.

Jorge Yanes Diez
fonte
Configure <RouteOptions> () é a melhor resposta imho: minúsculo e direto ao ponto (testado em mvc core 3.1)
T-moty
12

Encontrei a solução.

No assembly: Microsoft.AspNet.Routinge no Microsoft.Extensions.DependencyInjectionnamespace, você pode fazer isso em seu ConfigureServices(IServiceCollection services)método:

services.ConfigureRouting(setupAction =>
{
    setupAction.LowercaseUrls = true;
});
mariocatch
fonte
15
Para ASP NET MVC CORE: services.AddRouting (options => {options.LowercaseUrls = true;});
Skorunka František
Microsoft.Extensions.DependencyInjection em Microsoft.AspNetCore.Routing.dll
Skorunka František
3
Isso era verdade antes do RTM, agora você deve usar .AddRouting em vez de .ConfigureRouting
Yves Schelpe
0

Para identidade, a resposta de @Jorge Yanes Diez não funciona em ASP.NET Core 2.2( acho que 2.x ), então, se você usar Identity e ASP.NET Core 2.2 (2.x), aqui está a solução:

services.ConfigureApplicationCookie(options =>
{
    options.LoginPath = "/account/login";
    options.ReturnUrlParameter = "returnurl";
    ...
});

Ref: Configurar Identidade ASP.NET Core

Mehdi Dehghani
fonte
-1

Tive isso em RegisterRoutes :: RouteConfig:

routes.LowercaseUrls = true;

paburgos
fonte