How can I execute the ActionMethod program with software?

I am trying to execute Controller Action Method programmatically and I am not sure how to do it.

Scenario: When my ControllerFactory can't find the controller, I want it to manually execute one action method I have on a simple, custom controller. I don't want to rely on using any route data to define the controller / method .. because that route may not have been connected.

Eg.

// NOTE: Error handling removed from this example.
public class MyControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        IController result = null;

        // Try and load the controller, based on the controllerType argument.
        // ... snip
        // Did we retrieve a controller?
        if (controller == null)
        {
            result = new MyCustomController();
            ((MyCustomController)result).Execute404NotFound(); // <-- HERE!
        }

        return result;
    }
}

      

.. and this way ...

public static void Execute404NotFound(this Controller controller)
{
    result = new 404NotFound();
    // Setup any ViewData.Model stuff.
    result.ExecuteResult(controller.ControllerContext); // <-- RUNTIME 
                                                        //  ERROR HERE
}

      

Now when I run the controller factory, the controller cannot be found, then I manually create my own base controller. Then I call the extension method ' Execute404NotFound

' on that controller instance. That's fine .. until it executes the method ExecuteResult(..)

. What for? the controller has no data ControllerContext

. So it crashes ExecuteResult

because it takes multiple ControllerContext

.

So - can someone out there help me? see what i am doing wrong.

Remember -> I am trying to get my controller factory to manually / programmatically call a method on the controller, which will of course return an ActionResult.

Please, help!

UPDATE:

I also try to avoid the more common solutions of using catchall or throwing an exception that is handled in the Application_Exception section. I don’t believe they should be able to properly handle this problem .. given that we know what the problem is and as such we should handle it right there.

+2


a source to share


5 answers


If you create a controller manually, you also need to provide a context for the controller.

You are on the right track, but you will need some more code to complete it. I went through this a while ago and a whole bunch of code popped up in this thread on how to instantiate and fake a request to the controller .



If all you're doing is looking for a 404 code, your approach seems overkill. Could you do something like this ?

+1


a source


You can throw out new HttpException(404, "Not found")

of your custom controller instance which can be found in Application_Error

in global.asax and redirected to the page you want:



protected void Application_Error(object sender, EventArgs e)
{
    var exception = Server.GetLastError();
    Response.Clear();
    var httpException = exception as HttpException;
    var routeData = new RouteData();
    routeData.Values.Add("controller", "Error");

    if(httpException != null )
    {
        switch( httpException.GetHttpCode() )
        {
            case 404:
                // Page not found.
                routeData.Values.Add("action", "HttpError404" );
                break;
            case 500:
                // Server error.
                routeData.Values.Add("action", "HttpError500" );
                break;
            default:
                routeData.Values.Add("action", "General" );
                break;
        }
    }

    routeData.Values.Add("error", exception);
    Server.ClearError();
    var errorController = new ErrorController();
    errorController.Execute(new RequestContext(
        new HttpContextWrapper(Context), routeData ) );
}

      

+1


a source


The problem is that the factory manager's job is not to invoke action methods.

I can think of two ways to deal with this besides Application_Error:

  • override System.Web.Mvc.MvcHandler ProcessRequest method. This is a nuclear option in my opinion.

  • if no controller is found, return your 404 controller and there are a number of ways to make this the most straight forward, to override the ExecuteCore method of the controllers so that your action method is always called.

0


a source


How about a nice simple

RedirectToAction("ActionName");

Hope this helps?

0


a source


How about changing the route:

public class MyControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        IController result = null;

        // Try and load the controller, based on the controllerType argument.
        // ... snip
        // Did we retrieve a controller?
        if (controller == null)
        {
            result = new MyCustomController();
            requestContext.RouteData.Values["action"] = "My404Action";
        }

        return result;
    }
}

      

0


a source







All Articles