Asp.net Core 3.1 realizes automatic generation of routing URL according to the namespace

Time:2021-2-20

PressAsp.net coreThe default interface writing, each interface controller must inherit fromControllerBaseClass, you also need to haveApiControllerCharacteristics andRoutecharacteristic,RouteThe routing rules have to be written manually. As shown in the figure below

 

I think it’s troublesome. Maybe I’m lazy. In fact, most of the interface paths I write follow certain rules. Generally, the path prefix is the namespace following the namespace controllers, and then the path prefix is the[controller]/[action]Routing rules.

For example, a namespaceLessSharp.WebApi.Controllers.SysBelowUserControllerBelow the controllerSaveInterface, then according to the sys following the namespace, the corresponding interface path value is/Sys/User/Save

Then I hope that by default, the path can be automatically generated according to my above rules. If there are special cases, I will add oneRouteFeature, manually write my routing rules, and the framework will give priority to meRouteThe routing path value defined by the attribute.

 

My implementation method mainly usesAsp.net CoreController model conventions providedControllerModelConventionFunction, with the help ofApiConventionControllerAs the base class of controller, routing generation will only be generated at system startup, so it has no impact on system performance.

Here’s howApiConventionControllerIn fact, this class is not very useful. It is mainly used as a marker. As long as the controller inherits from the base class of the controller, the above URL generation rules will be used.

namespace LessSharp.WebApi.Controllers
{
    /// 
    ///After inheriting this controller, the route will be automatically modified according to the namespace structure to add a prefix
    ///For example LessSharp.WebApi.Controllers The user controller in the. Sys. A.B namespace will generate a route like sys / A / B / user
    ///If the derived controller has a custom route feature, the prefix will not be added automatically
    /// 
    [Route("[controller]/[action]")]
    [ApiController]
    public abstract class AutoRouteControllerBase : ControllerBase
    {
    }

The following is the core class of this URL generation function: autoroutecontrollermodelconvention, which implements the icontrolermodelconvention interface

namespace LessSharp.WebApi.Conventions
{
    public class AutoRouteControllerModelConvention : IControllerModelConvention
    {
        /// 
        ///Path prefix
        /// 
        private readonly string _prefix;
        public AutoRouteControllerModelConvention (string prefix)
        {
            _prefix = prefix;
        }
        public void Apply(ControllerModel controller)
        {
            //Determine whether it is a derivative controller of apiconventioncontroller
            if (controller.ControllerType.BaseType != typeof(AutoRouteControllerBase))
            {
                return;
            }
            //Determine whether there is a custom route property
            if (controller.ControllerType.GetCustomAttributes(typeof(RouteAttribute), false).Length > 0)
            {
                return;
            }
            string controllerNamespace = controller.ControllerType.Namespace;
            string temp = "Controllers.";
            int index = controllerNamespace.IndexOf(temp);
            string prefix = _prefix.Trim('/');
            if (index > -1)
            {
                prefix += "/" + controllerNamespace.Substring(index + temp.Length);
            }
            if (string.IsNullOrEmpty(prefix))
            {
                return;
            }
            if (!string.IsNullOrEmpty(prefix))
            {
                prefix = prefix.Replace(".", "/");
            }
            
            foreach (var selector in controller.Selectors.Where(s => s.AttributeRouteModel != null))
            {
                selector.AttributeRouteModel.Template = prefix + "/" + selector.AttributeRouteModel.Template;
            }
        }
    }
}

 

Finally, add the contract in the configureservices method of startup. I also add the function of adding URL prefix according to the routeprefix value of the configuration file

services.AddControllers(o =>
{// add a conventor to add a routing prefix to the derived class of apiconventioncontroller
    o.Conventions.Add(new AutoRouteControllerModelConvention(Configuration.GetValue("RoutePrefix")));
})

 

Finally, you just need to use it like this, which saves a lot of code, ha ha ha