You need to sign in to do that
Don't have an account?
Douglas Molina
Problem generating PDF attachment with onComplete commandButton
Hi!
In my org, I have the Opportunity object, that has a related list from a custom object named Proposta__c.
Proposta__c stores some Opportunity fields values, and a custom PDF as attachment, that contains other Opportunity informations.
Proposta__c records are generated only by a button, embedded in the Opportunity layout, as a Visualforce page commandButton (not a object's custom buttom).
So, in the Opportunity, the user clicks on this button, it calls a Apex extension class that I wrote, that creates a Proposta__c record with its fields, and generates/attach the PDF on this record.
Until here, everything is working as expected.
But, after create a Proposta__c record, I need open It, so I decided to use the onComplete commandButton property to do It.
The onComplete works fine to open the new Proposta__c record, but, when I use onComplete, the PDF attachment is generated as a blank page.
Even if I include the onComplete with no actions on it, the PDF still generate as a blank page.
If I remove only the onComplete property, the PDF is generated perfectly, with all its contents.
The point is: How can I generate correctly the regs and PDF, and then open it? maybe with a onComplete alternative..
Bellow are some tests fragments codes, to make it clearer:
proposta_pdf: The Apex extension class, that generates the Proposta__c record and its PDF attachment:
Proposta_Mestre: The Visualforce page, rendered as PDF. The Proposta__c attachment:
proposta_botoes: The visualforce page that contains the button, embedded in Opportunity layout:
This is what the Opportunity detail page looks like:
And the Proposta__c record, created by the button:
When I do NOT use the onComplete in the button, the PDF is generated in the right way:
And finally, if I add the onComplete in the commandButton, only a blank page is generated:
Additionally, I already tried:
- Add the extensions="proposta_pdf" in the Visualforce PDF page
- Use the controller.addFields() method to pass the required fields
With no sucess.
I'm preety new in Apex development, so this can be just a detail that I didn't notice, or some mistake.. but after days searching a solution, I'm still not able to figure out how to fix it.
I'd apreciate some sugestions..
And sorry for my bad english, I'm still beginner :)
Thanks.
In my org, I have the Opportunity object, that has a related list from a custom object named Proposta__c.
Proposta__c stores some Opportunity fields values, and a custom PDF as attachment, that contains other Opportunity informations.
Proposta__c records are generated only by a button, embedded in the Opportunity layout, as a Visualforce page commandButton (not a object's custom buttom).
So, in the Opportunity, the user clicks on this button, it calls a Apex extension class that I wrote, that creates a Proposta__c record with its fields, and generates/attach the PDF on this record.
Until here, everything is working as expected.
But, after create a Proposta__c record, I need open It, so I decided to use the onComplete commandButton property to do It.
The onComplete works fine to open the new Proposta__c record, but, when I use onComplete, the PDF attachment is generated as a blank page.
Even if I include the onComplete with no actions on it, the PDF still generate as a blank page.
If I remove only the onComplete property, the PDF is generated perfectly, with all its contents.
The point is: How can I generate correctly the regs and PDF, and then open it? maybe with a onComplete alternative..
Bellow are some tests fragments codes, to make it clearer:
proposta_pdf: The Apex extension class, that generates the Proposta__c record and its PDF attachment:
public class proposta_pdf{ public Opportunity opp_temp, opp_reg; public Id prop_reg_id {get;set;} public String url_base {get;set;} // constructor ============================== public proposta_pdf(ApexPages.StandardController controller) { // Get base URL (+prefix, if community) this.url_base = URL.getSalesforceBaseUrl().toExternalForm() + Site.getPathPrefix(); // Get other values this.opp_temp = (Opportunity)controller.getRecord(); this.opp_reg = [ SELECT Id, Name, Amount, Prop_Versao__c FROM Opportunity WHERE Id =: this.opp_temp.Id ]; } // geenerate PDF bin ======================== public Blob gera_prop_blob(){ PageReference prop_pag = Page.Proposta_Mestre; prop_pag.getParameters().put('id',opp_reg.Id); Blob prop_blob; if(!Test.isRunningTest()) prop_blob = prop_pag.getContentAsPDF(); else prop_blob = Blob.valueOf('Este e um teste.'); return prop_blob; } // create Proposta__c reg + PDF attachment ====== public void salva_proposta_registro(){ // validation if(this.opp_reg.Prop_Versao__c == NULL) this.opp_reg.Prop_Versao__c = 0; else this.opp_reg.Prop_Versao__c++; // create/save Proposta__c reg Proposta__c prop_reg = new Proposta__c( Oportunidade__c = this.opp_reg.Id, Name = this.opp_reg.Name + ' Ver:' + this.opp_reg.Prop_Versao__c, Versao__c = this.opp_reg.Prop_Versao__c, Valor__c = this.opp_reg.Amount ); insert prop_reg; // update Proposta__c version stored in a Opportunity field update this.opp_reg; // create/save/attach PDF in Proposta__c reg Attachment prop_anex = new Attachment( ParentId = prop_reg.Id, Body = gera_prop_blob(), Name = this.opp_reg.Name + ' Ver:' + this.opp_reg.Prop_Versao__c + '.pdf' ); insert prop_anex; // retur ID to open new reg prop_reg_id = prop_reg.Id; } }
Proposta_Mestre: The Visualforce page, rendered as PDF. The Proposta__c attachment:
<apex:page standardController="Opportunity" renderAs="pdf" applyHtmlTag="false" showHeader="false"> Testing Opportunity My PDF <br/>ID: {!Opportunity.Id} <br/>Name: {!Opportunity.Name} <br/> <br/>End. </apex:page>
proposta_botoes: The visualforce page that contains the button, embedded in Opportunity layout:
<apex:page standardController="Opportunity" extensions="proposta_pdf"> <apex:form> <apex:inputHidden value="{!Opportunity.Id}"/> <apex:commandButton value="Save" action="{!salva_proposta_registro}" onComplete="window.top.location.replace('{!url_base}/{!prop_reg_id}');" /> </apex:form> </apex:page>
This is what the Opportunity detail page looks like:
And the Proposta__c record, created by the button:
When I do NOT use the onComplete in the button, the PDF is generated in the right way:
And finally, if I add the onComplete in the commandButton, only a blank page is generated:
Additionally, I already tried:
- Add the extensions="proposta_pdf" in the Visualforce PDF page
- Use the controller.addFields() method to pass the required fields
With no sucess.
I'm preety new in Apex development, so this can be just a detail that I didn't notice, or some mistake.. but after days searching a solution, I'm still not able to figure out how to fix it.
I'd apreciate some sugestions..
And sorry for my bad english, I'm still beginner :)
Thanks.
Instead of using on complete why don't you try returning pagereference from salva_proposta_registro method
public PageReference salva_proposta_registro(){
PageReference pdf = Page.Proposta_Mestre;
//your insertion logic here
prop_reg_id = prop_reg.Id;
eturn new PageReference('/'+prop_reg_id);
}
Let me know this works .
Thank you, your suggestion solved part of the problem.
I made the changes you said, and added this lines in my embedded visualforce page, to open the next page in the parent window, Instead of opening inside the iframe, where the visualforce button page is located in:
But now, I'm facing another problem..
This functionality will be avaliable for partner users, in a Force.com site. (something like https://myorgname.force.com/sitename/)
In Internal Org, this works fine, but, when I log in to this partner site, and try to do the same, I recieve this error:
At the top, It says "The page you submitted was invalid for your session. Please click Save again to confirm your change"
I gave a search, and found some topics covering the same situation, some of then refering it as a kind of bug, and linking it to this know issue:
Spring 14 regression- getContentAsPDF() not working with PageReference(‘partialURL’):
https://success.salesforce.com/issues_view?id=a1p30000000T3HFAA0
They say, as a workaround: "Use Page.existingPageName" instead, but i think it wont work in my case.
I already tried the follow:
- Disable "PageReference getContent() and getContentAsPDF() Methods Behave as Callouts" critical update, but it's not avaliable to disable anymore
- The same with "Enable CSRF protection on GET and POST requests", no more avaliable.
- Give the users/site profiles, all access to the visualforce pages and apex classes.
- Check the "Available for Salesforce mobile apps and Lightning Pages" and uncheck the "Require CSRF protection on GET requests" properties in all visualforce pages.
- Remove the "<base target="_parent"/>", the problem continues, but inside the a iframe.
Any other sugestion to fix or workaround It?
Thanks.
Some other thing I could try ?