.net core replacement for MvcCodeRouting. Namespace based routing

Viewed 640

We have ASP.NET MVC 5 project, that we have plans to migrate to ASP.NET Core 3. Currently I gather dependency list and their equivalent replacements on the new new platform.

We are using MvcCodeRouting package to separate different workflows between different C# namespaces as was described in https://maxtoroq.github.io/2013/02/aspnet-mvc-workflow-per-controller.html.

Now with new platform in place, we need something similar. As last resort we could just specify all our namespaces in routing table, but I'd rather not to do so. Any suggestions on how accomplish similar behavior?

EDIT: I think with example it would be more understandable what I'm trying to accomplish.

We have following structure of controllers:

- Namespace1
-- Workflow1Controller.Index/Edit/Action
-- Workflow2Controller.Index/Edit/Action
-- Workflow3Controller.Index/Edit/Action
- Namespace2
-- Workflow4Controller.Index/Edit/Action

Workflow1Controller code:

namespace RootProjectNamespace.Controllers.Namespace1
{
    class Workflow1Controller : Controller
    {
         public ActionResult Index() {}
         // and so on
    }
}

Appropriate Views are placed in similar manner.

And using MvcCodeRouting we able to create Action urls by following:

Url.Action("Namespace1.Workflow1Controller", "Index") // Creates -> ~/Namespace1/Workflow1Controller/Index
Url.Action("Namespace2.Workflow4Controller", "Action") // Creates -> ~/Namespace2/Workflow4Controller/Index

Is there possibility to achieve similar in .net core without explicit hardcoding routes in route table?

2 Answers

As an start point for your solution, you can create a custom IApplicationModelConvention and change the routing to use namespace in the routing.

There's an example in docs showing how you can do this. To learn more you can take a look at this great docs article: Work with the application model in ASP.NET Core.

To do so, first create the following NamespaceRoutingConvention class:

using Microsoft.AspNetCore.Mvc.ApplicationModels;
using System.Linq;

public class NamespaceRoutingConvention : IApplicationModelConvention
{
    public void Apply(ApplicationModel application)
    {
        foreach (var controller in application.Controllers)
        {
            var hasAttributeRouteModels = controller.Selectors
                .Any(selector => selector.AttributeRouteModel != null);

            if (!hasAttributeRouteModels)
            {
                controller.Selectors[0].AttributeRouteModel = new AttributeRouteModel()
                {
                    Template = controller.ControllerType.Namespace.Replace('.', '/') 
                        + "/[controller]/[action]/{id?}"
                };
            }
        }
    }
}

Then in startup, register the convention like this:

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

Then you can browse:

http://localhost:xxxxx/SampleProject/Controllers/Home/Index

I have recently come across this issue.

An MVC .NET Framework project I had been working on needed migrating to .NET Core, however it was made up from lots of smaller assemblies (DLLs), each containing different parts of the overall codebase.

MvcCodeRouting was used to implement this, and provided a way for the assemblies to be utilised, routed, and also provided the ability for the central (core) project to utilise the relevant views, stored within the assemblies.

I have found that the .NET Core "Application Parts" feature seems to fulfill most of these points, with it having the ability for projects to be seperated between different assemblies, imported into a main project, and utilised.

The only real functional difference in using this method is that each "Application Part" generates two assemblies instead of one, with one containing the controllers and module logic, whilst the other contains the (Razor) views (if the specific module has any).

I'm still experimenting with this, however I thought I'd add this here for the sake of completeness.

Below are some useful links to documentation regarding this feature:

https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/app-parts?view=aspnetcore-1.0#sample-generic-controller-feature

This is the main documentation for the feature within the ASP.NET Core documentation.

https://docs.microsoft.com/en-us/aspnet/core/razor-pages/ui-class?view=aspnetcore-1.0&tabs=visual-studio

This tutorial demonstrated creating an assembly containing only Razor Views, if some of the modules require no logic.

Related