Search This Blog

Thursday, October 3, 2013

Incorrect way of instantiating Controllers in your custom code

I am posting this to help you avoid the subject and strange side effects with standard and custom Controllers in your applications while writing custom code. I am inspired by a customer who had a strange issue with non-working validation logic triggered by the the OK Action in a custom dialog window. The funny thing is that it all worked when the same dialog window was invoked via the standard PopupWindowShowAction instead of writing custom and configuring ShowViewParameters manually. Fortunately, I  knew what the problem is even without looking at the dialog window invocation code, which was really incorrect because of the following line:

DialogController dc = new DialogController();

It appears to be fully correct at first glance, but this is wrong, because by instantiating a Controller class this way a user left it unaware of the Application Model and other important XAF environment, which is responsible for many things like localization, validation, etc. As a result, no validation settings for the OK Action were taken into account...

The fix is also very easy: 

DialogController dc = this.Application.CreateController<DialogController>();


If you are curious and love to research how things are built, then you can look into the source code of this XafApplication's method to see that XAF passes the application model information while creating this guy internally:

public virtual ControllerType CreateController<ControllerType>() where ControllerType : Controller, new() {
ControllerType result;
if(controllersManager == null) {
result = new ControllerType();
}
else {
result = controllersManager.CreateController<ControllerType>(Model);
}
result.Application = this;
return result;
}

As you probably know, XafApplication provides various helper CreateXXX methods (CreateObjectSpace, CreateListView, CreateDetailView, CreateCollectionSource, CreateTemplate and much more), which I recommend you to use to save your time on initializing things correctly.

So, if you are reading this, use the Visual Studio Find & Replace dialog to locate all the "new DialogController()" occurrences and replace them with the correct code (of course make sure that the Application property is available in this context):


BTW, do you have any matches in your project?;-)

UPDATE:
Regardless you have any matches or not, feel free to track the
http://www.devexpress.com/issue=S172334 ticket I created to improve the lives of XAF developers in the future.

2 comments:

  1. Dennis,

    sorry for this - maybe dumb - question, but why don't you make this constructor private and create another one taking the application object as parameter that initializes the controller correctly?

    Gerhard

    ReplyDelete
  2. Thanks for the feedback, Gerhard. We cannot make the base Controller's constructor private because there may be other controllers, which do not require the application model. As for the DialogController, I think that we should obsolete its parameterless contstructor in the future. I have added a corresponding item in our TODO list for this: http://www.devexpress.com/Support/Center/Question/Details/S172334

    ReplyDelete