28

I have a base controller class:

And all my other controller inherits this BaseClass like this

All this works great in MVC3 (test again today, it really works) but it seems that the ExecuteCore in BaseController is not fired any more in MVC 4 beta.

Any idea? Or Anything huge has changed under the hood? Thanks very much.

public class BaseController : Controller
{
    private string _myData;

    public string MyData
    {
        get
        {
            return _myData;
        }
    }

    protected override void ExecuteCore()
    {
        _myData = "I am doing something";

        base.ExecuteCore();
    }
}


public class HomeController : BaseController
{
    public ActionResult Index()
    {
        ViewBag.MyData = MyData;
        // Doing something with value in BaseClass

        return View();
    }
}
BladeLeaf
  • 458
  • 1
  • 4
  • 8

3 Answers3

31

I was able to reproduce your problem. It seems that the usage of ExecuteCore is changed. But I haven't find any information about it. My guess it's related to the fact that now the Controller implements IAsyncController not the AsyncController.

However I've found a workaround to get the old behavior with MVC4:

Add this to the BaseContoller :

protected override bool DisableAsyncSupport
{
    get { return true; }
}

From The MSDN page for DisableAsyncSupport (emphasis add by me):

This flag is for backwards compatibility. ASP.NET MVC 4. allows a controller to support asynchronous patterns. This means ExecuteCore doesn't get called on derived classes. Derived classes can override this flag and set to true if they still need ExecuteCore to be called.

nemesv
  • 138,284
  • 16
  • 416
  • 359
  • 5
    Thanks for the comment. It seems that MVC team really changed something. I have another walkaround which may solve this: Instead of the ExecuteCore, I override the OnActionExecuting in the BaseClass, which get fired correctly. – BladeLeaf Mar 05 '12 at 01:48
  • 1
    At this moment, MSDN page is not empty and includes following remark: "This flag is for backwards compatibility. ASP.NET MVC 4. allows a controller to support asynchronous patterns. This means ExecuteCore doesn't get called on derived classes. Derived classes can override this flag and set to true if they still need ExecuteCore to be called." That means your solution/workaround is valid. – huhu78 Sep 14 '15 at 11:16
28

I voted nemesv answer because it gave me an explanation about what is going on. I have MVC3 and MVC4 projects and this this was driving me mad.

However I have another solution. Override Initialize method in the Controller class:

public abstract class BaseController : Controller
{
  protected override void Initialize(System.Web.Routing.RequestContext requestContext)
  {
     string languageId = "en";
     try{
       // all your code here. You have access to all the context information, 
       // like querystring values:
       string languageId = requestContext.HttpContext.Request.QueryString["lang"];
       Thread.CurrentThread.CurrentUICulture = 
          CultureInfo.CreateSpecificCulture(languageId);
     }
     finally
     {
       Thread.CurrentThread.CurrentUICulture = 
         CultureInfo.CreateSpecificCulture(languageId);
     }

     base.Initialize(requestContext);
  }
}

Then in your project just make your controllers inherit from BaseController and that is all, BaseController call works automatically passing the request context. It works for both MVC3 and MVC4.

Alfonso Muñoz
  • 1,609
  • 17
  • 24
  • Does this also works for custom model binders? Are the thread cultures correctly set when a model binder is invoked? – Rookian Dec 10 '13 at 16:25
  • Your solution is a great approach Alphonzo. It is exactly the right alternative to ExecuteCore() and works with MVC5. Here's the MSDN documentation for the Controller.Initialize Method: http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.initialize(v=vs.118).aspx – GDB Dec 19 '13 at 02:27
  • Nice to know, but it didn't work for me as I needed to access my db context and a session variable, which are not yet instantiated at the time Initialize is fired. BeginExecuteCore did the job for me instead. – ZipionLive May 01 '17 at 22:36
7

You can also use BeginExecuteCore

protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
{
    return base.BeginExecuteCore(callback, state);
}
Rikard
  • 3,828
  • 1
  • 24
  • 39
LungFungus
  • 141
  • 1
  • 4