ASP.Net Core Controllers
Up to ASP.net 4.6, MVC used a "Controller" base class while WebApi had an "ApiController" base class. For Core, MVC and Api moved to a single base class, "Controller" (and they can use POCO controllers, with no base class).
For Net 6+ we effectively use 2 base classes again (or Minimal Api!)
- API controler: ControllerBase and has [ApiController] attribute, which dictates attribute routing (not endpoint routing)
- MVC controller: Controller (which :ControllerBase)
Dependency Injection
- In Startup.ConfigureServices add your services: services.AddTransient<IService, MyService>()
- Read it in:
- Ctor injection- standard constructor
You can also accept an IOptions<settings> instance to read your settings (configured in Startup.ConfigureServices) - Method argument injection - public IActionResult Get([FromServices] IService service)
- Ctor injection- standard constructor
Poco controllers
You don't have to inherit from Controller (which are in Microsoft.AspNetCore.Mvc.ViewFeatures, not Microsoft.AspNetCore.Mvc.Core), but pocos probably need extra information to be injected.
Poco controllers get property injection for 3 properties: ActionContext (which gives you HttpContext), ViewData (ViewDataDictionary) and Url (IUrlHelper). At which point, you might as well inherit from controller.
public class MyPocoController
{
[ActionContext]
public ActionContext ActionContext { get; set; }
public string Get()
{
var user = ActionContext.HttpContext.User;
if (user.HasClaim("Role", "Admin"))
Actions
Ideally return IActionResult (in MVC 5 we used ActionResult - you can still return a string or model).
WebApi routing
MVC5 automagically mapped HTTP verbs to action names (Get, Post). Now we have to use explicit [HttpGet] and [HttpPost] attributes (and mapping with attributes seems to be preferred generally)
Partial (Child) Actions - use ViewComponents
You cannot use MVC 5 partial actions - @Html.Action / [ChildActionOnly] / return PartialView
Use viewcomponents instead: @Component.Invoke("name",model) / component inherits from ViewComponent and implements Invoke(args)
Dependency Injection
ILogger and IOptions are built in. You can also get the root path via IWebHostEnvironment (NB: create a wwwroot folder in the project or it doesn't work)
See Microsoft docs
private readonly IWebHostEnvironment _webHostEnvironment;
public UserManualController(
ILogger<UserManualController> logger,
IWebHostEnvironment webHostEnvironment)
{
_logger = logger;
_webHostEnvironment = webHostEnvironment;
}
[HttpGet("/Download")]
public IActionResult Download()
{
//you must have a wwwroot folder otherwise WebRootPath is null
var path = Path.Combine(Path.Combine(_webHostEnvironment.WebRootPath, "Manual"), "userguide.pdf");
_logger.LogInformation($"Downloading {path}");
var fileStream = System.IO.File.OpenRead(path);
return File(fileStream, "application/pdf");
}