Thursday, July 28, 2016

Salesforce : DML currently not allowed

If you write create/update/delete operation in apex controller constructor then this error would be thrown.
You have to do some trick to get rid of this problem.
First create an action with your create/update/delete operations in your controller.
And then add the action name in your apex:page as attribute which will call with constructor.





<apex:page standardController="Account" extensions="APEX_CONTROLLER_CLASS_NAME" action="{!YOUR_ACTION_NAME}">
DO YOUR OTHER WORKS HERE...
</apex:page>

Monday, July 25, 2016

Parse JSON in Salesforce


public class CommonJsonParser {
    public cls_Parent[] parentList;
    class cls_Parent {
        public Integer intType;
        public Double doubleType;
        public String stringType;
        public cls_Child[] childList;
    }
    class cls_Child {
        public Integer param_1;
        public String param_2;
    }
    public static CommonJsonParser parse(String json){
        return (CommonJsonParser) System.JSON.deserialize(json, CommonJsonParser.class);
    }

    public static String test() {
        String json = '{"parentList":[' + 
            '{"intType":1,"doubleType":1.5,"stringType":"String_1",' + 
            '"childList":[' + 
                '{"param_1":1,"param_2":"String_100"},' + 
                '{"param_1":5,"param_2":"String_101"}]}'+
            ',{"intType":2,"doubleType":2.5,"stringType":"String_2",' + 
            '"childList":[' + 
                '{"param_1":6,"param_2":"String_102"},' + 
                '{"param_1":2,"param_2":"String_103"},' + 
                '{"param_1":1,"param_2":"String_104"}]}]}';
        CommonJsonParser obj = parse(json);
        
        String output = '';
        
        for(cls_Parent cParent : obj.parentList) {
            output += '<br/>';
            output += '[[ Integer_Value=' + cParent.intType;
            output += ', Double_Value=' + cParent.doubleType;
            output += ', String_Value=' + cParent.stringType + ' ]]';
            
            for(cls_Child cChild: cParent.childList) {
                output += '<br/>&nbsp;&nbsp;&nbsp;&nbsp;Param_1=' + cChild.param_1;
                output += ', Param_2=' + cChild.param_2;
            }
        }
        
        return output;
    }
}
Output would be like this:

[[ Integer_Value=1, Double_Value=1.5, String_Value=String_1 ]]
    Param_1=1, Param_2=String_100
    Param_1=5, Param_2=String_101
[[ Integer_Value=2, Double_Value=2.5, String_Value=String_2 ]]
    Param_1=6, Param_2=String_102
    Param_1=2, Param_2=String_103
    Param_1=1, Param_2=String_104 

Git: comparing remote branches, different between two remote branches

git diff --name-status origin/master...remotes/origin/2.0.0

git diff master remotes/origin/2.0.0 -- app/../File.name

Tuesday, July 19, 2016

Salesforce :: Can not add Visual Force page to Custom button

1. At first create a custom controller (Apex Class) with following contents:


public with sharing class CommonController {

    private ApexPages.StandardController standardController;
    
    public Account account { get; private set; }
    
    public CommonController (ApexPages.StandardController standardController) {
        this.standardController = standardController;
        Id recordId = standardController.getId();
        account = (Account) standardController.getRecord();
    }
    
    public PageReference doSomething() {
        //after some tasks return to Account details view
        return standardController.view();
    }
    
    public PageReference cancel() {
        // return to account details view
        return standardController.view();
    }
    
}


2. Create a "Visualforce Pages" page with following contents:

<apex:page standardController="Account" extensions="CommonController">
    Account_Selected=<b>{!Account.Name}</b><br/>
    <apex:form >
        <apex:commandButton value="Do something in CommonController.doSomething()" action="{!doSomething}"/>
        <apex:commandButton value="Cancel this process & return to details view" action="{!cancel}"/>
    </apex:form>
</apex:page>

3. Go to "setup/Customize/Accounts/Buttons, Links, and Actions" and click on "New button or link"
4. Select "Display Type" as "Detail Page Button"
5. Select "Behavior" as "Display in existing window without sidebar or header"
6. Select "Content Source" as "Visualforce Page"
7. And finally select a controller created before from "Content" dropdown.
8. Now go to "setup/Customize/Accounts/Page Layouts"
9. Edit any of your layout you used to test this case
10. Select "Buttons" panel and drop the button created before in details panel
11. Now go to your account details page and now you can see the button available.

Monday, July 18, 2016

Salesforce create custom controller

1. Go to "setup/Develop/Apex Classes" and click "new"
2. Write the following code:


public class CustomController {

    public Account account { get; private set; }

    public NewAndExistingController() {
        Id id = ApexPages.currentPage().getParameters().get('id');
        account = (id == null) ? new Account() :
            [SELECT Name, Phone, Industry FROM Account WHERE Id = :id];
    }

    public PageReference save() {
        try {
            upsert(account);
        } 
        catch(System.DMLException e) {
            ApexPages.addMessages(e);
            return null;
        }
        //  After successful Save, navigate to the default view page
        PageReference r = new ApexPages.StandardController(Account).view();
        return (r);
    }
}


3. Go to "setup/Develop/Visualforce Pages" and click "new"
4. Write the following code:

<apex:page controller="CustomController" tabstyle="Account">
    <apex:form>
        <apex:pageBlock mode="edit">
            <apex:pageMessages/>
            <apex:pageBlockSection>
                <apex:inputField value="{!Account.name}"/>
                <apex:inputField value="{!Account.phone}"/>
                <apex:inputField value="{!Account.industry}"/>
            </apex:pageBlockSection>
            <apex:pageBlockButtons location="bottom">
                <apex:commandButton value="Save" action="{!save}"/>
            </apex:pageBlockButtons>
        </apex:pageBlock>
    </apex:form>
</apex:page>

5. Go to "setup/Create/Tabs" click on "new" under group "Visualforce Tabs"
6. Select "Visualforce Page" created before & provide other information & save.

7. Browse your custom tab to access the custom tab.


Show HTML string as an HTML output instead of plain text in Salesforce Visaul Force page

Write the following code snippet:


<apex:outputLabel escape="false" Value="{!html}" ></apex:outputLabel>


Instead of the following:

{!html} 

How to make a post or get request to some other server from apex class

1. Go to "setup/Develop/Apex Class"
2. Click "new"
3. Write code as following:


public class ApexClass_1 {
    @Future(callout=true)
    public static void c1(String Account_ID) {
        String name = '';
        try {
            HttpRequest req = new HttpRequest();
            req.setEndpoint('http://www.yahoo.com');
            req.setMethod('POST');
            req.setBody('Account_ID='+EncodingUtil.urlEncode(Account_ID, 'UTF-8')+'&other_param='+EncodingUtil.urlEncode('OTHER PARAM VALUE', 'UTF-8'));
            req.setCompressed(true);

            /* If you want to send basic authentication */
            String username = 'myname';
            String password = 'mypwd';
            Blob headerValue = Blob.valueOf(username + ':' + password);
            String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue);
            req.setHeader('Authorization', authorizationHeader);

            Http http = new Http();
            HTTPResponse res = http.send(req);
            name = 'Status_Code=' + res.getStatusCode();
            String responseBody = res.getBody();
        }
        catch(System.CalloutException e) {
            System.debug('Callout error: '+ e);
            name = ('Error=' + e.getMessage()).substring(0, 20);
        }

        /* Reading account object */
        Account account = [SELECT Id FROM Account WHERE Id = :Account_ID];
        account.Name = name;
        update op;
    }
}


4. Go to "setup/Security Controls/Remote Site Settings"
5. Click "New remote site" & enter the URL that you want to invoke from apex class.
6. Invoke method "ApexClass_1.c1" from wherever you want.

7. An example of invoke url in salesforce from apex sObjects trigger options
8. Go to "setup/Customize/Accounts/Triggers"
9. Click "new"
10. Write the following code:

trigger TriggerActionName on Account (before insert, after insert, after delete) {
    if (Trigger.isInsert) {
        if (Trigger.isAfter) {
            for (Account a : Trigger.New) {
                ApexClass_1.c1(a.Id);
            }
        }
    }
}


11. Once you create a new account the url would be invoked in a short time (Also you could write code for update & delete)
12. Apex trigger documentation: https://developer.salesforce.com/trailhead/en/apex_triggers/apex_triggers_intro