Visualforce DML – DML Not Allowed in Page Action

So I understand DML Operations aren't allowed in getters/setters,constructors but it was my understanding that they were allowed in methods that were invoked by page-actions like so:

page:

<apex:page controller="mycontroller" action="{!init}">...</apex:page>

controller:

public mycontroller(){
   public void init(){
        //perform some DML, in my case inserting a custom setting if one doesn't exist...
        insert whatever...;
   }
}

This worked fine for a while, but than when I attempted to deploy my app into a Spring '13 sandbox org I get an exception:

DML currently not allowed An unexpected error has occurred. Your
development organization has been notified.

Has this always been the case and I'm doing something different I didn't realize?

If not some suggestions how I could create my necessary custom settings if they don't exist on page-init would be great.

Best Answer

I once started seeing this error and couldn't work out for the life of me why... I eventually realised I was being a bit dim, and following my oft-used practice had a call to Init() inside a constructor, and you can't perform DML operations like this inside the constructor!

Update Jan 2014 - Something else to watch out for!

Almost a year after writing this answer I hit a similar issue yesterday, this time because the controller was for a Visualforce component as opposed to a page. In a component you must explicitly allow DML like so:

<apex:component controller="myController" allowDML="true">
Related Topic