Currently to return view, I have to write one method in all the controllers. That is "Index" action method. It has nothing to do except returning their respective views.
So is it possible to make them common?
I have inherited one common basecontroller which is inherited from apicontroller. So is there a way that I write base index method. and i can override it as well if needed?
You can create a BaseController class like this:
public class BaseController : Controller
{
public virtual IActionResult Index()
{
return View();
}
}
Then inherit your controller clasess from base controller:
public class CustomersController : BaseController
{
}
You can override the Index method like this:
public class HomeController : BaseController
{
public override IActionResult Index()
{
return View("About");
}
}
Related
I have multiple classes (more than 100) which inherit from my base class BaseController. All my classes are their logics and models but format's response (200, 404, 500, ...) are always the same.
But when I inherit from my base class, in my swagger documentation I see my endpoints but the details of the response are not there. How can I do this?
public class BaseController : Controller
{
public BaseController() {}
[Produces("application/json")]
[SwaggerResponse(StatusCodes.Status200OK)]
[SwaggerResponse(StatusCodes.Status404NotFound)]
protected async Task<IActionResult> Get(int id)
{
...
}
}
public class MyController : BaseController
{
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id)
{
return await base.Get(id).ConfigureAwait(false);
}
}
As #Helder Sepulveda Said, this goes beyond swashbuckle.
I Think you can use IActionModelConvention to simulate inherit the action attributes.
Use Action.Filters like this
public class ActionMethodConvention : IActionModelConvention
{
public void Apply(ActionModel action)
{
var actonBaseResponses = new List<SwaggerResponseAttribute>();//some code to get baseAction reflections
foreach (var attr in actonBaseResponses)
{
action.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(actonBaseResponses.StatusCode));
}
}
I have a base AsyncController
BaseController : AsyncController
{
[Authorize("Admin")]
public virtual async Task<ActionResult> SomeMethod()
{
//code
}
}
How it is correct to inheritance and override SomeMethod?
UserController : BaseController
{
[Authorize("User")]
public override Task<ActionResult> SomeMethod()
{
return base.SomeMethod()
}
}
OR
UserController : BaseController
{
[Authorize("User")]
public override async Task<ActionResult> SomeMethod()
{
return await base.SomeMethod()
}
}
P.S. Sorry for my english
SomeMethod() is defined within your BaseController class. Therefore child classes should inherit from BaseController rather than AsyncController. To override the method, just add virtual keyword into the definition.
BaseController : AsyncController
{
[Authorize("Admin")]
public virtual async Task<ActionResult> SomeMethod()
{
//code
}
}
Inheritance and override
UserController : BaseController
{
[Authorize("User")]
public override Task<ActionResult> SomeMethod()
{
return base.SomeMethod()
}
}
Also I have noticed something odd in your Authorize attributes. If the base method is allow to Admin only and the child method is allow to User only, then you most likely end up being unable to execute the base method from the child class.
I search about base controller in asp.net mvc 6 however there is no any source (as far as i check).So how can i add base controller in asp.net mvc and use services on constuctor method or create new methods in base controller or any idea in order to use anything like base controller?
Any help will be appreciated.
Thanks.
You can add base controller in the following way:
public class BaseController : Controller
{
public IService Service { get; }
public BaseController(IService service)
{
Service = service;
}
}
Then, you can create your own controller and inherit BaseController instead of Controller class.
public class NewController : BaseController
{
public NewController(IService service) : base(service)
{
}
public IActionResult NewAction()
{
var result = Service.ServiceMethod();
}
}
With Microsoft.Extensions.DependencyInjection name space gives us access to the following extension method HttpContext.RequestServices.GetService
Here’s the source code of our BaseController class
public abstract class BaseController<T> : Controller where T : BaseController<T>
{
private IService service;
protected IService _service => telemetryInitializer ?? (telemetryInitializer = HttpContext.RequestServices.GetService<West.TelemetryService.ITelemetryHelper>());
}
The OrderController class extends this abstract BaseController
public class OrderController : BaseController<OrderController>
{
private readonly IOrderManager _orderManager;
public OrderController(IOrderManager orderManager)
{
_orderManager = orderManager;
}
[HttpGet]
public string Get()
{
Logger.LogInformation("Hello World!");
return "Inside the Get method of OrderController";
}
}
Let's say I have many Controllers, and a lot of this Controllers share common Action. What is the best way to share these common Actions to eliminate duplicating the code?
One way I know is to refactor these common Actions into parent abstract Controller, like so..
public abstract class BaseController : Controller {
//handles common help page for all controllers
public ActionResult Help(string helpTopic) {
..open help page..
return View(page);
}
}
//now Controller1 and Controller2 has the help page for free!
public class Controller1: BaseController {
}
public class Controller2: BaseController {
}
But if I attempt to override the Help action within any of the sub controllers like so..
//customized help page for Controller1
public class Controller1: BaseController {
public new ActionResult Help(string helpTopic) {
.. my own customized help page..
return View(page);
}
}
I will get error The current request for action 'Help' on controller type 'Controller1' is ambiguous between....
So how do I override parent controller method?
What I did to successfully override a parent controller's method is to mark the method as virtual and use the override keyword in the child controller method, like so...
public abstract class BaseController : Controller {
//handles common help page for all controllers
public virtual ActionResult Help(string helpTopic) {
..open help page..
return View(page);
}
}
//Controller1 has a customized help page
public class Controller1: BaseController {
public override ActionResult Help(string helpTopic) {
.. my own customized help page..
return View(page);
}
}
//Controller2 has help page for free!
public class Controller2: BaseController {
}
Suppose I have following Controller and action with authorization Attribute:
public class IndexController : Controller
{
//
// GET: /Index/
[Authorize(Roles="Registered")]
public ActionResult Index()
{
return View();
}
}
I've searched over the entire Internet and not found an answer for this simple question: how to get the roles annotated to an especific Action/Controller? In this case: Index Action has: string[] = {"Registered"}
Finally I found the solution! Was more easy than I thought! ahahha I need extend a class from AuthorizeAttribute and use it in actions. The information I need is the attribute "Roles" of the inherited class:
public class CustomAuthorizationAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var roles = this.Roles;
base.OnAuthorization(filterContext);
}
}
And on Index Controller:
public class IndexController : Controller
{
//
// GET: /Index/
[CustomAuthorizationAttribute(Roles = "Registered")]
public ActionResult Index()
{
return View();
}
}