Map controller routes with configurable path in library

Viewed 2099

My utility library is offering multiple actions that should be usable in different ASP.Net Core applications. So far, an extension method for IApplicationBuilder is used to configure the routes:

public static void UseUtility(this IApplicationBuilder app)
{
    app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                "default",
                "api/{controller=Home}/{action=Index}/{id?}");
            endpoints.MapDefaultControllerRoute().RequireAuthorization();
        }
    );
}

In order to register these routes with a configurable path (e.g. utility/), the hosting application calls Map on its IApplicationBuilder:

app.Map("utility", hostingApp => { hostingApp.UseUtility(); });

The problem is, according to Routing in ASP.NET Core a library is not supposed to call UseEndpoints, but offer an extension method for IEndpointRouteBuilder. So I tried the following:

public static void MapUtility(this IEndpointRouteBuilder routeBuilder)
{
    routeBuilder.MapControllerRoute(
        "default",
        "api/{controller=Home}/{action=Index}/{id?}");
    routeBuilder.MapDefaultControllerRoute().RequireAuthorization();
}

The hosting application calls it in Configure()

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

Two questions arise here:

  1. How can I add the utility/ to the beginning of the routing path?
  2. How to register only the enpoints/controllers of my utility library with the given route and not the controlles of the hosting application?
2 Answers

1.Create UtilityImporter static method to add Endpoints.

public static class UtilityImporter
{
    public static void Use(IEndpointRouteBuilder endpoints)
    {
        endpoints.MapAreaControllerRoute(name: "area_utility", areaName: "Utility",
              pattern: "utility/{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" });

    }
}

2.Use UtilityImporter in Startup.cs.

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

            UtilityImporter.Use(endpoints);

        });
  1. Add your controllers in Areas/Utility/Controllers/ here.

enter image description here

Screenshot of Test:

enter image description here

If you want asp.net core to exclude host assembly and use only dependencies Assemblies for MVC Controller Discovery. You can configure the ApplicationPartManager to exclude the host assembly.

AspNet Core 3.0 discovers dependencies that reference MVC features. Make sure you refer to the library in host assembly. When the ASP.NET Core application starts, it uses the ApplicationPartManger for adding external assembly as ApplicationParts. Hence utility library will be added to discovery. we need to remove only host assembly.

In the case, my Host Assembly is "ControllerTest". Add the below code into the ConfigureServices method.

services.AddMvc().ConfigureApplicationPartManager(a =>
            {
                var appPart = a.ApplicationParts.FirstOrDefault(ap => ap.Name == "ControllerTest");
                if (appPart != null)
                {
                    a.ApplicationParts.Remove(appPart);
                }
            });
Related