As you know, ASP.NET 5 supports POCO controllers. The controller classes doesn’t extend Controller base class. These controllers look a little bit different by some small aspects and sometime,s you may need to help framework detect our POCO controllers. In this post, I will give you complete overview of POCO controllers in ASP.NET 5.
Creating POCO controllers is simple. To use views and other goodies provided by controllers base class we have to use dependency injection to get required services to our POCO controller. If we don’t use MVC regular naming style for controllers we have to write action discovery convention and register it with built-in dependency injection service. To provide common strategy to detect POCO controllers with arbitrary names we can use special attribute or interface for this. We still can inherit our POCO controllers from classes we want. Here is the simple steps that you have to follow:
Simple POCO Controllers
First let’s define that simple controller doesn’t inherit from Controller base class. Follow the code below:
public class PocoController
{
public IActionResult Index()
{
return new ContentResult() { Content = “Hello from POCO controller!” };
}
}
And to make this controller work with views, you need some additional code.
public class PocoController
{
private readonly IModelMetadataProvider _metadataProvider;
public PocoController(IModelMetadataProvider metadataProvider)
{
_metadataProvider = metadataProvider;
}
public IActionResult Index()
{
var viewData = new ViewDataDictionary<string>(_metadataProvider);
viewData.Model = “Hello from POCO controller!”;
return new ViewResult() { ViewData = viewData };
}
}
Now, you have basic primitive POCO controller that you can use in ASP.NET 5.
The second thing that you have to is use a small trick and call our controller just as "POCO" using this code:
public class Poco
{
// …
}
When trying to use controller now you have run to problems like this. Why? Because ASP.NET cannot detect controller anymore.
How to make the controller is detected by default?
When sniffing around in MVC source you can find the method that MVC uses to find out if given type is controller type of not. It is done in DefaultActionDiscoveryConventions class.
public virtual bool IsController([NotNull] TypeInfo typeInfo)
{
if (!typeInfo.IsClass ||
typeInfo.IsAbstract ||
typeInfo.ContainsGenericParameters)
{
return false;
}
if (typeInfo.Name.Equals(“Controller”, StringComparison.OrdinalIgnoreCase))
{
return false;
}
return typeInfo.Name.EndsWith(“Controller”, StringComparison.OrdinalIgnoreCase) ||
typeof(Controller).GetTypeInfo().IsAssignableFrom(typeInfo);
If we have POCO controller andyou don’t name it as SomethingController then MVC is not considering our POCO controller as controller.
Using action discovery convention
If there are additional rules for detecting controllers, you can use action discovery conventions to tell MVC if class is constructor or not. Here is simple discovery convention class that works with our POCO controller.
public class MyActionDiscoveryConventions : DefaultActionDiscoveryConventions
{
public override bool IsController(TypeInfo typeInfo)
{
var isController = base.IsController(typeInfo);
return isController || typeInfo.Name.Equals(“Poco”, StringComparison.OrdinalIgnoreCase);
}
}
To make MVC use this class, you have to register it with built-in dependency injection system. You will do it in ConfigureServices() method of your Startup class by calling AddTransient() method.
public void ConfigureServices(IServiceCollection services)
{
// …
services.AddMvc();
services.AddTransient<IActionDiscoveryConventions, MyActionDiscoveryConventions>();
}
If you run your application now and try to use POCO controller it works again.
Defining ControllerAttribute
If you are building some extensible system and you need some better way how to detect controllers then besides naming controllers appropriately you can also define attribute in some API library that is available for developers.
public class ControllerAttribute : Attribute
{
}
Other developers who are building plugins for your system can decorate their controllers with this attribute.
[Controller]
public class Poco
{
// …
}
And here is how you can detect controller in action discovery convention.
public class MyActionDiscoveryConventions : DefaultActionDiscoveryConventions
{
public override bool IsController(TypeInfo typeInfo)
{
var isController = base.IsController(typeInfo);
return isController || HasControllerAttribute(typeInfo);
}
private bool HasControllerAttribute(TypeInfo typeInfo)
{
return typeInfo.GetCustomAttribute<ControllerAttribute>(true) != null;
}
}
You can also use marker interface for POCO controllers or some interface with properties and methods defined if your POCO controllers have to provide some functionalities.
HostForLIFE.eu ASP.NET 5 Hosting
HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes. We have customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.