Author : MD TAREQ HASSAN | Updated : 2020/06/23

Global route prefix

Create Extention Method

MvcOptionsExtensions.cs

namespace Kintai.Api.Extensions
{
    public static class MvcOptionsExtensions
    {
        public static void UseGeneralRoutePrefix(this MvcOptions opts, IRouteTemplateProvider routeAttribute)
        {
            opts.Conventions.Add(new RoutePrefixConvention(routeAttribute));
        }

        public static void UseGeneralRoutePrefix(this MvcOptions opts, string prefix)
        {
            opts.UseGeneralRoutePrefix(new RouteAttribute(prefix));
        }
    }

    public class RoutePrefixConvention : IApplicationModelConvention
    {
        private readonly AttributeRouteModel _routePrefix;

        public RoutePrefixConvention(IRouteTemplateProvider route)
        {
            _routePrefix = new AttributeRouteModel(route);
        }

        public void Apply(ApplicationModel application)
        {
            foreach (var selector in application.Controllers.SelectMany(c => c.Selectors))
            {
                if (selector.AttributeRouteModel != null)
                {
                    selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(_routePrefix, selector.AttributeRouteModel);
                }
                else
                {
                    selector.AttributeRouteModel = _routePrefix;
                }
            }
        }
    }
}

Setup in Startup

Startup.cs

public void ConfigureServices(IServiceCollection services)
{

	services.AddMvc(o => { o.UseGeneralRoutePrefix(AppConstants.ApiRoot + "/v{version:apiVersion}"); })
		.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
		
	services.AddApiVersioning(o => o.ReportApiVersions = true);
	
	// ... ... ...
}

Use Versioning in Controller

EmployeesController.cs

[ApiController]
[ApiVersion("1")]
[Route("employees")]
public class EmployeesController : ControllerBase
{
  // .. ... ...
}

Query Mutator

Using Query Mutator

// filter criteria - statregy design pattern
var searchFieldMutators = new List<SearchFieldMutator<Employee, EmployeeSearchModel>>();
searchFieldMutators.Add(new SearchFieldMutator<Employee, EmployeeSearchModel>(search => !string.IsNullOrWhiteSpace(search.FirstName), (query, search) => query.Where(e => e.FirstName.Contains(search.FirstName))));
searchFieldMutators.Add(new SearchFieldMutator<Employee, EmployeeSearchModel>(search => !string.IsNullOrWhiteSpace(search.LastName), (query, search) => query.Where(e => e.FirstName.Contains(search.LastName))));

var pageMutators = new List<SearchFieldMutator<Employee, int?>>();
pageMutators.Add(new SearchFieldMutator<Employee, int?>(pageNo => page.HasValue && page.Value >= 1, (query, pageNo) => query.Skip(AppConstants.PageSize * (page.Value - 1)).Take(AppConstants.PageSize)));