+ Start a Discussion
maxout2maxout2 

std controller save() didn't save the change of the field.

controller.save();  didn't save the change of the field.

Checking...

after clicking a button in a detail page

the VF page with this extension opened in a new window, showing some message correctly

close and go back to the detail page, do a refresh, the field remain the same as 'New'.

 

is it the way to call save() here?

 

[code partially]

 public RequestControllerExtension(ApexPages.StandardController stdController)
 {
  controller=stdController;

  doConfirm();
 }
 
 private void doConfirm()
 {
  this.req=(Request__c)controller.getRecord();
  if(req.Status__c=='New')
  {
   req.Status__c='Dispatched';
   controller.save();
   Msg='Change status:' + req.Status__c + '.';
  }
  else
  {
   Msg='Invalid status:' + req.Status__c + '.';
  }
 }

 

 

 

Question found after :

http://boards.developerforce.com/t5/General-Development/can-std-getrecord-be-used-in-extension-s-constructor/m-p/249103#M51890

Best Answer chosen by Admin (Salesforce Developers) 
maxout2maxout2

Test result:

 

DML is not allowed in constructor

or is call from a public attribute method which is call when the page is rendered.

error message is shown for direct DML call, but not always from MVC, eg. controller.save().

 

controller.save() does work when called from a button after a user's click.

didn't try DML, should work, I reckon.

 

could be a security reason with the public attribute method.

This error started when I wanted to keep the code simple at the beginning and put all in the costructor.

Thanks sebcos.

cheers

All Answers

sebcossebcos

Hi maxout2,

ApexPages.StandardController.save() method will only save the sObject (record) that is stored in the standardController object.

In your case, for the status field to change your code should look something like this:

 

private void doConfirm()
 {
  this.req=(Request__c)controller.getRecord();
  if(req.Status__c=='New')
  {
   
   req.Status__c='Dispatched';
   ApexPages.StandardController newController = new ApexPages.StandardController(req);
   //controller.save();
   newController.save();

 You need to reinitialise your controller with the new value that you have set on the record, otherwise you will save the old record only. In summary, getRecord() gives you a reference to an sObject but you need a new controller with a reference to the updated record to be able to save changes to it.

 

 

maxout2maxout2

Thanks.

 

It's something about the behaviour of MVC used at the platform.

If MVC is put aside, individual insert/update(DML) can also do the job.

 

The question is:

  if [this.req] received the object reference from the standard controller passed into the extension,

  they has a binding so that the std controller's [save()] should do the job instead of creating a new one or DML.

The MVC should meant to be, unless it's a restriction.

 

Test result:

No save with the extra new controller, and no error(seems like the error is hidden inside).

However, using DML like

  update req;

has an error: System.LimitException: DML currently not allowed

 which seems like a DML restriction in constructor.

 

???

sebcossebcos

Hi maxout2,

I should have said copy of the object instead of reference, apologies for the confusion.

You are correct you can either use MVC approach or DML statements.

Also, you are correct, it looks like DML is not allowed in constructors.

If you want to surface error messages to the UI also for the controller you should add to the page a tag on top like this:

<apex:page> ...

<apex:pagemessages/>

...

</apex:page>

 

maxout2maxout2

Test result:

 

DML is not allowed in constructor

or is call from a public attribute method which is call when the page is rendered.

error message is shown for direct DML call, but not always from MVC, eg. controller.save().

 

controller.save() does work when called from a button after a user's click.

didn't try DML, should work, I reckon.

 

could be a security reason with the public attribute method.

This error started when I wanted to keep the code simple at the beginning and put all in the costructor.

Thanks sebcos.

cheers

This was selected as the best answer
sebcossebcos

Hi maxout2,

no worries, I have stumbled upon this piece of documentation on the visualforce guide from http://www.salesforce.com/us/developer/docs/pages/Content/pages_controller_considerations.htm :

"You can't use data manipulation language (DML) operations in a constructor method in a controller."

Hope this clarifies the issue.