Asp.net mvc 3- get the current controller instance

2020-02-03 13:10发布

问题:

I know how to get the current controller name

HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();

But is there any way to get the current controller instance in some class (not in an action and not in a view)?

回答1:

By default you can only access the current Controller inside a controller with ControllerContext.Controller or inside a view with ViewContext.Context. To access it from some class you need to implement a custom ControllerFactory which stores the controller instance somewhere and retrieve it from there. E.g in the Request.Items:

public class MyControllerFactory : DefaultControllerFactory
{
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var controller = base.CreateController(requestContext, controllerName);
        HttpContext.Current.Items["controllerInstance"] = controller;
        return controller;
    }
}

Then you register it in your Application_Start:

ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());

And you can get the controller instance later:

public class SomeClass
{
    public SomeClass()
    {
        var controller = (IController)HttpContext.Current.Items["controllerInstance"];
    }
}

But I would find some another way to pass the controller instance to my class instead of this "hacky" workaround.



回答2:

Someone will have to correct me if what I am doing is detrimental to the whole Asp.Net page life cycle / whatever but surely you can do this:

In controller

ViewBag.CurrentController = this;

In view

var c = ViewBag.CurrentController;
var m1 = BaseController.RenderViewToString(c, "~/Views/Test/_Partial.cshtml", null);

In my case, I had a base controller that all controllers extend. In that base controller lived a static method called RenderViewToString and it required a controller. Since I figured I could just instantiate a new instance of an empty controller at this point for c, I just sent it to the view in the lovely ViewBag container that exists in the world of Asp.Net MVC. For reasons I could not go into now, I could not retrieve the string in the controller and send just that back to the view (this was what I had done earlier before requirements changed).

The reason I have done it this way is in other languages like PHP and JS, there are similar simple ways to transfer classes around.