Using 'UseMvc' to configure MVC is not supported while using Endpoint Routing
Asked Answered
H

11

276

I had an Asp.Net core 2.2 project.

Recently, I changed the version from .net core 2.2 to .net core 3.0 Preview 8. After this change I see this warning message:

using 'UseMvc' to configure MVC is not supported while using Endpoint Routing. To continue using 'UseMvc', please set 'MvcOptions.EnableEndpointRouting = false' inside 'ConfigureServices'.

I understand that by setting EnableEndpointRouting to false I can solve the issue, but I need to know what is the proper way to solve it and why Endpoint Routing does not need UseMvc() function.

Hedonics answered 28/8, 2019 at 1:48 Comment(1)
about proper way: this doc learn.microsoft.com/en-us/aspnet/core/migration/… states "migrate the app to Endpoint Routing if possible"Jarrod
C
44

but I need to know what is the proper way to solve it

In general, you should use EnableEndpointRouting instead of UseMvc, and you could refer Update routing startup code for detail steps to enable EnableEndpointRouting.

why Endpoint Routing does not need UseMvc() function.

For UseMvc, it uses the IRouter-based logic and EnableEndpointRouting uses endpoint-based logic. They are following different logic which could be found below:

if (options.Value.EnableEndpointRouting)
{
    var mvcEndpointDataSource = app.ApplicationServices
        .GetRequiredService<IEnumerable<EndpointDataSource>>()
        .OfType<MvcEndpointDataSource>()
        .First();
    var parameterPolicyFactory = app.ApplicationServices
        .GetRequiredService<ParameterPolicyFactory>();

    var endpointRouteBuilder = new EndpointRouteBuilder(app);

    configureRoutes(endpointRouteBuilder);

    foreach (var router in endpointRouteBuilder.Routes)
    {
        // Only accept Microsoft.AspNetCore.Routing.Route when converting to endpoint
        // Sub-types could have additional customization that we can't knowingly convert
        if (router is Route route && router.GetType() == typeof(Route))
        {
            var endpointInfo = new MvcEndpointInfo(
                route.Name,
                route.RouteTemplate,
                route.Defaults,
                route.Constraints.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value),
                route.DataTokens,
                parameterPolicyFactory);

            mvcEndpointDataSource.ConventionalEndpointInfos.Add(endpointInfo);
        }
        else
        {
            throw new InvalidOperationException($"Cannot use '{router.GetType().FullName}' with Endpoint Routing.");
        }
    }

    if (!app.Properties.TryGetValue(EndpointRoutingRegisteredKey, out _))
    {
        // Matching middleware has not been registered yet
        // For back-compat register middleware so an endpoint is matched and then immediately used
        app.UseEndpointRouting();
    }

    return app.UseEndpoint();
}
else
{
    var routes = new RouteBuilder(app)
    {
        DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
    };

    configureRoutes(routes);

    routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices));

    return app.UseRouter(routes.Build());
}

For EnableEndpointRouting, it uses EndpointMiddleware to route the request to the endpoints.

Cirrocumulus answered 29/8, 2019 at 8:13 Comment(0)
P
278

I found the solution, in the following official documentation "Migrate from ASP.NET Core 2.2 to 3.0":

There are 3 approaches:

  1. Replace UseMvc or UseSignalR with UseEndpoints.

In my case, the result looked like that

  public class Startup
{

    public void ConfigureServices(IServiceCollection services)
    {
        //Old Way
        services.AddMvc();
        // New Ways
        //services.AddRazorPages();
    }


    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseStaticFiles();
        app.UseRouting();
        app.UseCors();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}");
        });

    }
}

OR
2. Use AddControllers() and UseEndpoints()

public class Startup
{

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }


    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseStaticFiles();
        app.UseRouting();
        app.UseCors();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });

    }
}

OR
3. Disable endpoint Routing. As the exception message suggests and as mentioned in the following section of documentation: use mvcwithout endpoint routing


services.AddMvc(options => options.EnableEndpointRouting = false);
//OR
services.AddControllers(options => options.EnableEndpointRouting = false);
Poppas answered 7/10, 2019 at 10:6 Comment(5)
This works in asp.net core 3.0 and I can use this add web API easilyMauricio
It's recommended (on that page) to use services.AddRazorPages(); instead of services.AddMvc();Expeditionary
This is a good solution if you're going through the first mvc tutorial and upgrade from core2.1 to core3.0. This solved my issue immediately, thanks!Phlebitis
So they basically just slightly changed the syntax from UseMvc() to UseEndpoints().Quinn
I needed to adapt some ASP.NET Core 2.2 example code => ASP.NET 5. OLD: app.UseMvc(routes => {...}); NEW: app.UseEndpoints(endpoints => {...});. In other words: Option 1 worked like a charm! Thank you! Too bad this isn't the "accepted" reply.Crystallize
K
92

This worked for me (add in Startup.cs > ConfigureServices method):

services.AddMvc(option => option.EnableEndpointRouting = false)
Kersey answered 8/11, 2019 at 19:16 Comment(2)
Simple answer, but Great answer!Quintal
I would argue about the usefulness of this answer. This answers how not why...Otisotitis
C
44

but I need to know what is the proper way to solve it

In general, you should use EnableEndpointRouting instead of UseMvc, and you could refer Update routing startup code for detail steps to enable EnableEndpointRouting.

why Endpoint Routing does not need UseMvc() function.

For UseMvc, it uses the IRouter-based logic and EnableEndpointRouting uses endpoint-based logic. They are following different logic which could be found below:

if (options.Value.EnableEndpointRouting)
{
    var mvcEndpointDataSource = app.ApplicationServices
        .GetRequiredService<IEnumerable<EndpointDataSource>>()
        .OfType<MvcEndpointDataSource>()
        .First();
    var parameterPolicyFactory = app.ApplicationServices
        .GetRequiredService<ParameterPolicyFactory>();

    var endpointRouteBuilder = new EndpointRouteBuilder(app);

    configureRoutes(endpointRouteBuilder);

    foreach (var router in endpointRouteBuilder.Routes)
    {
        // Only accept Microsoft.AspNetCore.Routing.Route when converting to endpoint
        // Sub-types could have additional customization that we can't knowingly convert
        if (router is Route route && router.GetType() == typeof(Route))
        {
            var endpointInfo = new MvcEndpointInfo(
                route.Name,
                route.RouteTemplate,
                route.Defaults,
                route.Constraints.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value),
                route.DataTokens,
                parameterPolicyFactory);

            mvcEndpointDataSource.ConventionalEndpointInfos.Add(endpointInfo);
        }
        else
        {
            throw new InvalidOperationException($"Cannot use '{router.GetType().FullName}' with Endpoint Routing.");
        }
    }

    if (!app.Properties.TryGetValue(EndpointRoutingRegisteredKey, out _))
    {
        // Matching middleware has not been registered yet
        // For back-compat register middleware so an endpoint is matched and then immediately used
        app.UseEndpointRouting();
    }

    return app.UseEndpoint();
}
else
{
    var routes = new RouteBuilder(app)
    {
        DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
    };

    configureRoutes(routes);

    routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices));

    return app.UseRouter(routes.Build());
}

For EnableEndpointRouting, it uses EndpointMiddleware to route the request to the endpoints.

Cirrocumulus answered 29/8, 2019 at 8:13 Comment(0)
R
20

The issue I found to be due to updates on the .NET Core framework. The latest .NET Core 3.0 released version requires explicit opt-in for using MVC.

This issue is most visible when one tries to migrate from older .NET Core(2.2 or preview 3.0 version) to .NET Core 3.0

If migrating from 2.2 to 3.0, please use the below code to fix the issue.

services.AddMvc(options => options.EnableEndpointRouting = false);

If using .NET Core 3.0 template,

services.AddControllers(options => options.EnableEndpointRouting = false);

ConfigServices method after fix as below,

enter image description here

Thank You

Retrogress answered 2/7, 2020 at 10:12 Comment(0)
V
13

Endpoint Routing is disabled by default on ASP.NET 5.0

Just configure as in Startup

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(options => options.EnableEndpointRouting = false);
    }
    

This worked for me

Vadose answered 6/4, 2021 at 15:31 Comment(0)
B
11

You can use : in ConfigureServices method:

services.AddControllersWithViews();

And for Configure method:

app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
Ballade answered 27/4, 2020 at 19:11 Comment(1)
This worked well for me, I needed to add app.UseRouting(); though.Obscure
P
7
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        //Old Way
        services.AddMvc();
        // New Ways
        //services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseStaticFiles();
        app.UseRouting();
        app.UseCors();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}");
        });
    }
}

This works also in .Net Core 5

Prescriptible answered 6/2, 2021 at 20:24 Comment(1)
What is the difference with NHARI Med answer ?Kronstadt
E
6

-> In ConfigureServices method - Startup.cs

        //*****REGISTER Routing Service*****
        services.AddMvc();
        services.AddControllers(options => options.EnableEndpointRouting = false);

-> In Configure Method - Startup.cs

       //*****USE Routing***** 
        app.UseMvc(Route =>{
            Route.MapRoute(
                name:"default",
                template: "{Controller=Name}/{action=Name}/{id?}"
            );
        });
Exorcise answered 18/9, 2021 at 23:17 Comment(0)
L
5

For DotNet Core 3.1

Use below

File : Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{         

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
       
    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthentication();
    app.UseHttpsRedirection();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}
Luellaluelle answered 6/6, 2020 at 23:3 Comment(1)
What to do with all the services configuration lines?Trinidad
M
-1

This worked for me

 services.AddMvc(options => options.EnableEndpointRouting = false); or 
 OR
 services.AddControllers(options => options.EnableEndpointRouting = false);
Milore answered 8/8, 2021 at 3:40 Comment(1)
What is the difference with option 3 in top Sergii Zhuravskyi answer? Yo can just upvote an existing answerKronstadt
B
-5

Use Below Code

app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
Broadspectrum answered 16/10, 2019 at 5:57 Comment(4)
It would help if you explained how this code solves the problem.Interlocutrix
Simply posting code is not a sufficient answer. Please explain what/why/how this code will answer the question.Ingrate
this is just boiler plate that comes out of the box and doesnt actually help the user with that they are adterTridentum
The above code will throw an error since it does not have {id? } as optional parameter app.UseEndpoints(endpoints => { endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/ {id?}"); });Curnin

© 2022 - 2024 — McMap. All rights reserved.