Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Way to reuse code inside my Controller action method

I have certain code with in the same controller class that looks almost the same, such as setting viewbags to populate all the drop down lists, the same code applies in my Post and get Create and Edit action methods. So I have created a private method at the end of my controller class as follow:-

private void populateViewBags()
{
    string controllerName = RouteData.Values["controller"].ToString();
    ViewBag.PossibleDataCenters = repository.AllDataCenter().OrderBy(a => a.Name).ToList();
    ViewBag.PossibleZones = repository.AllZone().OrderBy(a => a.Name).ToList();
    List<string> s = new List<string>();
    s.Add(controllerName.ToLower());
    ViewBag.Products = repository.GetProducts(s).OrderBy(a => a.COMPONENTNAME).ToList();
    ViewBag.Sites = repository.GetSDOrg().OrderBy(a => a.NAME).ToList();
    ViewBag.Customers = repository.FindAccountDefinition(null).ToList();
}

And I am calling this method inside my action method. So is it the right way to re-use the code? Thanks

like image 619
john Gu Avatar asked Oct 04 '22 06:10

john Gu


1 Answers

There are two standard ways you can do this.

1st approach - override OnActionExecuting and/or OnActionExecuted methods of your controller class:

public class HomeController: Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        string controllerName = RouteData.Values["controller"].ToString();
        ViewBag.ControllerName = controllerName;
    }

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        string controllerName = RouteData.Values["controller"].ToString();
        ViewBag.ControllerName = controllerName;
    }
}

You can also make abstract base controller which implements those methods and then inherit concrete controllers from abstract one, so that you don't duplicate code code in each controller.

2nd approach - make custom ActionFilter attribute and decorate each controller that needs to perform additional actions.

public class MyActionFilterAttribute: ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        string controllerName = filterContext.RouteData.Values["controller"].ToString();
        filterContext.Controller.ViewBag.ControllerName = controllerName;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        string controllerName = filterContext.RouteData.Values["controller"].ToString();
        filterContext.Controller.ViewBag.ControllerName = controllerName;
    }
}

Then just decorate controllers, like:

[MyActionFilter]
public class HomeController: Controller
{
    // ....
}

UPDATE: Additional flexibility of filter approach, if you need filter on per-action basis, instead of all actions in the controller, it's also possible:

public class HomeController: Controller
{
    [MyActionFilter]
    public ActionResult MyAction()
    {
        //...
    }
}
like image 163
Nenad Avatar answered Oct 06 '22 01:10

Nenad