Learning Routing and AttributeRouting Web API 2 Controllers in MVC with Areas
💻 coding

Learning Routing and AttributeRouting Web API 2 Controllers in MVC with Areas

2 min read 406 words
2 min read
ShareWhatsAppPost on X
  • 1Web API 2 controllers can now be used within Areas in ASP.NET MVC5 projects, resolving limitations from previous versions.
  • 2Proper configuration and order of routing setup is crucial to avoid 404 errors when using AttributeRouting with Web API 2.
  • 3Setting JSON as the default return format helps prevent circular reference issues in Web API responses.

AI-generated summary · May not capture all nuances

Key Insight
AskGif

"Web API 2 controllers can now be used within Areas in ASP.NET MVC5 projects, resolving limitations from previous versions."

Learning Routing and AttributeRouting Web API 2 Controllers in MVC with Areas

The Acumen ASP.NET MVC development team started working with the new Web API 2 controllers released with Visual Studio 2013, and quickly hit some important issues that took some research to resolve.

Routing and AttributeRouting and using Web API 2 controllers inside an Area in an ASP.NET MVC5 project

Currently, this IS possible. It was not possible with Web API and it seems like it was also not possible in beta, but this can be done with Web API 2 and MVC 5. I used the following configurations:

// File: ~/Areas/API/APIAreaRegistration.cs
 using System.Web.Http;
 using System.Web.Mvc;

 namespace MySolution.Areas.API {
 public class APIAreaRegistration : AreaRegistration {
 public override string AreaName {
 get {
 return "API";
 }
 }

 public override void RegisterArea(AreaRegistrationContext context) {
 context.Routes.MapMvcAttributeRoutes();
 context.Routes.MapHttpRoute(
 name: this.AreaName,
 routeTemplate: this.AreaName + "/{controller}/{id}",
 defaults: new { id = RouteParameter.Optional }
 );
 }
 }
 }
// File: ~/Global.asax.cs
 using System.Linq;
 using System.Web.Http;
 using System.Web.Mvc;
 using System.Web.Routing;
 using Newtonsoft.Json.Serialization;
 using WebMatrix.WebData;
 using AcumenSystem5.Models;
 using System.Threading;
 using System.Web.Optimization;

 namespace MySolution {
 public class MvcApplication : System.Web.HttpApplication {
 protected void Application_Start() {
 AreaRegistration.RegisterAllAreas();
 GlobalConfiguration.Configure(config => { // This HAS to be here. Having it last caused routing to not work.
 config.MapHttpAttributeRoutes(); // This allows us to use AttributeRouting

 // This sets JSON as the default return format and removes any circular references
 var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
 config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
 var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
 json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
 config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 
 });
 RouteConfig.RegisterRoutes(RouteTable.Routes);
 BundleConfig.RegisterBundles(BundleTable.Bundles);
 LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
 }
 }
 }

AttributeRouting and WebAPI Routing not working correctly and returning 404 Errors

After struggling with areas, I hit this issue when adding the Web API 2 controller to the root controllers folder. I discovered that the ordering of configuration mattered. So,

protected void Application_Start() {
	// Full file code in example above
 AreaRegistration.RegisterAllAreas();
 GlobalConfiguration.Configure(config => { // This HAS to be here. Having it last caused routing to not work.
 config.MapHttpAttributeRoutes(); // This allows us to use AttributeRouting

 config.Routes.MapHttpRoute( // This allows us to use conventional HTTP routing
 name: "Name",
 routeTemplate: "api/{controller}/{id}",
 defaults: new { id = RouteParameter.Optional }
 ); ;

 // This sets JSON as the default return format and removes any circular references
 var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
 config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
 var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
 json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
 config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 
 });
 RouteConfig.RegisterRoutes(RouteTable.Routes);
 BundleConfig.RegisterBundles(BundleTable.Bundles);
 LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
 }

as shown in the Global.asax.cs above, the order needs to be as follows to work correctly:

Enjoyed this article?

Share it with someone who'd find it useful.

ShareWhatsAppPost on X

AskGif

Published on 23 March 2019 · 2 min read · 406 words

Part of AskGif Blog · coding

You might also like

Learning Routing and AttributeRouting Web API 2 Controllers in MVC with Areas | AskGif Blog