Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8415833
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 10, 20262026-06-10T01:33:41+00:00 2026-06-10T01:33:41+00:00

I am currently working on a ASP.NET MVC 4 Web Application project that must

  • 0

I am currently working on a ASP.NET MVC 4 Web Application project that must adhere to the following design decisions:

  • The main MVC application resides in the root of the solution.
  • All administrator functionality resides in a separate area.
  • Each external party (e.g. suppliers) has its own area.
  • Each area, including the root, constitutes a well separated
    functional block. Functionality from one area may not be exposed to
    another area. This is to prevent unauthorized access of data.
  • Each area, including the root, has its own RESTfull API (Web API).

All normal controllers in all areas, including the root, work as expected. However, some of my Web API controllers exhibit unexpected behaviour. For instance, having two Web API controllers with the same name but in different areas produces the following exception:

Multiple types were found that match the controller named ‘clients’.
This can happen if the route that services this request
(‘api/{controller}/{id}’) found multiple controllers defined with the
same name but differing namespaces, which is not supported.

The request for ‘clients’ has found the following matching controllers:
MvcApplication.Areas.Administration.Controllers.Api.ClientsController
MvcApplication.Controllers.Api.ClientsController

This seems strange since I have distinct routes that should separate both. Here is my AreaRegistration for the Administration section:

public class AdministrationAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Administration";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.Routes.MapHttpRoute(
            name: "Administration_DefaultApi",
            routeTemplate: "Administration/api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        context.MapRoute(
            "Administration_default",
            "Administration/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }
        );
    }
}

Moreover, I notice that I can access Area specific Web API’s while omitting the name of the area from the call.

What is going on here?
How do I get my Web API Controllers to behave just like normal ASP.NET MVC controllers?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-10T01:33:42+00:00Added an answer on June 10, 2026 at 1:33 am

    ASP.NET MVC 4 does not support the partitioning of Web API controllers across Areas.

    You may place WebApi controllers in different Api folders in different Areas, but ASP.NET MVC will treat as if they are all in the same place.

    Fortunately, you can overcome this limitation by overriding a part of the ASP.NET MVC infrastructure. For more information about the limitation and the solution, please read my blog post ‘ASP.NET MVC 4 RC: Getting WebApi and Areas to play nicely‘. If you are only interested in the solution, read on:

    Step 1. Make your routes Area aware

    Add the following extension methods to your ASP.NET MVC application and make sure they are accessible from your AreaRegistration classes:

    public static class AreaRegistrationContextExtensions
    {
        public static Route MapHttpRoute(this AreaRegistrationContext context, string name, string routeTemplate)
        {
            return context.MapHttpRoute(name, routeTemplate, null, null);
        }
    
        public static Route MapHttpRoute(this AreaRegistrationContext context, string name, string routeTemplate, object defaults)
        {
            return context.MapHttpRoute(name, routeTemplate, defaults, null);
        }
    
        public static Route MapHttpRoute(this AreaRegistrationContext context, string name, string routeTemplate, object defaults, object constraints)
        {
            var route = context.Routes.MapHttpRoute(name, routeTemplate, defaults, constraints);
            if (route.DataTokens == null)
            {
                route.DataTokens = new RouteValueDictionary();
            }
            route.DataTokens.Add("area", context.AreaName);
            return route;
        }
    }
    

    To use the new extension method, remove the Routes property from the call chain:

    context.MapHttpRoute( /* <-- .Routes removed */
        name: "Administration_DefaultApi",
        routeTemplate: "Administration/api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
    

    Step 2. Make Web API controller selector Area aware

    Add the following class to your ASP.NET MVC application and make sure it is accessible from the Global.asax

    namespace MvcApplication.Infrastructure.Dispatcher
    {
        using System;
        using System.Collections.Concurrent;
        using System.Collections.Generic;
        using System.Globalization;
        using System.Linq;
        using System.Net.Http;
        using System.Web.Http;
        using System.Web.Http.Controllers;
        using System.Web.Http.Dispatcher;
    
        public class AreaHttpControllerSelector : DefaultHttpControllerSelector
        {
            private const string AreaRouteVariableName = "area";
    
            private readonly HttpConfiguration _configuration;
            private readonly Lazy<ConcurrentDictionary<string, Type>> _apiControllerTypes;
    
            public AreaHttpControllerSelector(HttpConfiguration configuration)
                : base(configuration)
            {
                _configuration = configuration;
                _apiControllerTypes = new Lazy<ConcurrentDictionary<string, Type>>(GetControllerTypes);
            }
    
            public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
            {
                return this.GetApiController(request);
            }
    
            private static string GetAreaName(HttpRequestMessage request)
            {
                var data = request.GetRouteData();
                if (data.Route.DataTokens == null)
                {
                    return null;
                } 
                else 
                {
                    object areaName;
                    return data.Route.DataTokens.TryGetValue(AreaRouteVariableName, out areaName) ? areaName.ToString() : null;
                }
            }
    
            private static ConcurrentDictionary<string, Type> GetControllerTypes()
            {
                var assemblies = AppDomain.CurrentDomain.GetAssemblies();
    
                var types = assemblies
                    .SelectMany(a => a
                        .GetTypes().Where(t =>
                            !t.IsAbstract &&
                            t.Name.EndsWith(ControllerSuffix, StringComparison.OrdinalIgnoreCase) &&
                            typeof(IHttpController).IsAssignableFrom(t)))
                    .ToDictionary(t => t.FullName, t => t);
    
                return new ConcurrentDictionary<string, Type>(types);
            }
    
            private HttpControllerDescriptor GetApiController(HttpRequestMessage request)
            {
                var areaName = GetAreaName(request);
                var controllerName = GetControllerName(request);
                var type = GetControllerType(areaName, controllerName);
    
                return new HttpControllerDescriptor(_configuration, controllerName, type);
            }
    
            private Type GetControllerType(string areaName, string controllerName)
            {
                var query = _apiControllerTypes.Value.AsEnumerable();
    
                if (string.IsNullOrEmpty(areaName))
                {
                    query = query.WithoutAreaName();
                }
                else
                {
                    query = query.ByAreaName(areaName);
                }
    
                return query
                    .ByControllerName(controllerName)
                    .Select(x => x.Value)
                    .Single();
            }
        }
    
        public static class ControllerTypeSpecifications
        {
            public static IEnumerable<KeyValuePair<string, Type>> ByAreaName(this IEnumerable<KeyValuePair<string, Type>> query, string areaName)
            {
                var areaNameToFind = string.Format(CultureInfo.InvariantCulture, ".{0}.", areaName);
    
                return query.Where(x => x.Key.IndexOf(areaNameToFind, StringComparison.OrdinalIgnoreCase) != -1);
            }
    
            public static IEnumerable<KeyValuePair<string, Type>> WithoutAreaName(this IEnumerable<KeyValuePair<string, Type>> query)
            {
                return query.Where(x => x.Key.IndexOf(".areas.", StringComparison.OrdinalIgnoreCase) == -1);
            }
    
            public static IEnumerable<KeyValuePair<string, Type>> ByControllerName(this IEnumerable<KeyValuePair<string, Type>> query, string controllerName)
            {
                var controllerNameToFind = string.Format(CultureInfo.InvariantCulture, ".{0}{1}", controllerName, AreaHttpControllerSelector.ControllerSuffix);
    
                return query.Where(x => x.Key.EndsWith(controllerNameToFind, StringComparison.OrdinalIgnoreCase));
            }
        }
    }
    

    Override the DefaultHttpControllerSelector by adding the following line to the Application_Start method in the Global.asax.

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

    Congratulations, your Web API controllers will now respect the rules of your areas just like your normal MVC controllers do!

    UPDATE: 6 september 2012

    Several developers have contacted me about a scenario they encountered where the DataTokens property of the route variable is null. My implementation assumes that the DataTokens property is always initialized and will not function properly if this property is null. This behavior is most likely caused by recent changes in the ASP.NET MVC framework and may be actually be a bug in the framework. I’ve updated my code to handle this scenario.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm currently working on an Asp.net MVC Web application. In my solution, there're two
I am currently working on a project that consists of an ASP.NET MVC 2.0
i am working on an asp.net MVC web application , currently i am managing
I'm looking for a working sample of an ASP.NET MVC web application that uses
I am working on an asp.net MVC 3 web application, i have the following
I am currently working on an ASP.NET MVC project. Some developers on the team
I'm currently working on an ASP.Net WebForms application that allows a user to select
The ASP.NET web app project I'm currently working on is getting slower over time
I'm currently working on an C#/ASP.NET project that will host several differents e-commerce websites,
First some background, I am currently working on a relatively large Asp.Net MVC application

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.