Custom ASP.NET WEB API Controller Suffix

One constraint I found out with ASP.NET WEB API is that it forces us to have the suffix of "Controller" (i.e. ExpenseController) in our classes. When implementing it in the service layer of the layered architecture, this naming convention is somewhat confusing for me because I already have Controllers residing in the presentation layer. I would like to suffix my classes with "Service" instead, since I find that it is a more appropriate representation.

public class ExpenseService ApiController
{
    [HttpGet]
    public List<Expense> List()
    {
        var bc = new ExpenseComponent();
        return bc.List();
    }
}

Fortunately, we can fix the restriction with some code. Below is the ServiceControllerSelector class which I had simplified from here that replaces the default "Controller" suffix with "Service".

public class ServiceControllerSelectorDefaultHttpControllerSelector
{
    private const string CONTROLLER_SUFFIX = "Service";
    private static Dictionary<stringType> _controllerTypes;

    private readonly HttpConfiguration _configuration;

    public ServiceControllerSelector(HttpConfiguration configuration)
        : base(configuration)
    {
        this._configuration = configuration;

        if (_controllerTypes == null)
            _controllerTypes = LoadTypes();
    }

    private static Dictionary<stringType> LoadTypes()
    {
        var assemblies = AppDomain.CurrentDomain.GetAssemblies();

        // Reflect all types with the controller suffix.
        var types = assemblies.SelectMany(asm => asm.GetTypes()
            .Where(t => !t.IsAbstract && 
                t.Name.EndsWith(CONTROLLER_SUFFIX) && 
                typeof(ApiController).IsAssignableFrom(t)))
            .ToDictionary(t => t.FullName, t => t);

        return types;
    }

    public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
    {
        return GetController(request) ?? base.SelectController(request);
    }

    private HttpControllerDescriptor GetController(HttpRequestMessage request)
    {
        HttpControllerDescriptor descriptor = null;
        string controllerName = base.GetControllerName(request);

        string fullName = string.Format(".{0}{1}", controllerName, CONTROLLER_SUFFIX);

        // Search for the controller.
        var type = _controllerTypes.Where(
            t => t.Key.EndsWith(fullName, StringComparison.OrdinalIgnoreCase))
                    .Select(t => t.Value).FirstOrDefault();

        if (type != null)
            descriptor = new HttpControllerDescriptor(_configuration, controllerName, type);

        return descriptor;
    }
}

To use it, simply put the following line in the Application_Start event of the Global.asax.

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector),
   new ServiceControllerSelector(GlobalConfiguration.Configuration));

There you have it! Back to the preferred standard naming convention :)

No comments:

Post a Comment

Popular Post