9

I am building a scheduled jobs controller - these jobs will call a Controller and an Action capturing the result. I would rather have all this happen on the backend and not involve http calls.

Its kind of like what happens with Unit testing - for instance:

var controller = new TestController();
var result = controller.Index("TestParameter") as ViewResult;

The issue is in this example the controller and action are not dynamic, does anyone know how to initialize a controller and call an action with the name of the controller and action as string paramater? Such as -

public ActionResult run(string controllerName, string actionName)
{
    var controller = new Controller(controllerName);
    var result = controller.action(actionName).("TestParameter") as ViewResult;
    return Content(result);
}
7
  • A controller's purpose is to handle browser requests. Are you calling an MVC controller from another class? Commented Mar 10, 2015 at 15:25
  • Yes I want to call many controllers and actions from another single controller action such as the run action above. Commented Mar 10, 2015 at 15:31
  • 6
    The only thing that should be calling an MVC controller is the browser. Commented Mar 10, 2015 at 15:45
  • 1
    Your controller action handles a browser event. If you need your controller to execute something during that action, call another non-controller class. You should probably read up on MVC. Commented Mar 10, 2015 at 20:07
  • 1
    Oh well if it's the easiest solution. By all means, ignore how the MVC framework is designed. Commented Mar 11, 2015 at 16:02

2 Answers 2

15

Use the ControllerFactory along with the ActionDescriptor to dynamically execute the action:

public ActionResult Run(string controllerName, string actionName)
{
    // get the controller
    var ctrlFactory = ControllerBuilder.Current.GetControllerFactory();
    var ctrl = ctrlFactory.CreateController(this.Request.RequestContext, controllerName) as Controller;
    var ctrlContext = new ControllerContext(this.Request.RequestContext, ctrl);
    var ctrlDesc = new ReflectedControllerDescriptor(ctrl.GetType());

    // get the action
    var actionDesc = ctrlDesc.FindAction(ctrlContext, actionName);

    // execute
    var result = actionDesc.Execute(ctrlContext, new Dictionary<string, object>
    {
        { "parameterName", "TestParameter" }
    }) as ActionResult;

    // return the other action result as the current action result
    return result;
}

See MSDN

Sign up to request clarification or add additional context in comments.

1 Comment

I'd like to say, from the code above, I was able to build the Scheduled Jobs functionality into my application, and it has been running like a charm for many a months :) We can on the fly schedule any action to run on schedule, I think though thats not the way MVC was designed, this is a great solution. Cheers @haim770!
-3

I am not sure where is your real problem lies—do you want to test controller/action or do you want to test functionality of your jobs?

  1. If you need to test controller/action it would involve HttpContext.
  2. If you need to test your job functionality better way to separate that in your service / repository layer and you can do testing with using repository pattern.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.