Demystifying the PageReference

The PageReference is one of the most commonly used classes in Visualforce programming. In general, an instance of the PageReference class can be used to refer to another web page. This may be another Visualforce page, another standard page, or, it could be a web page outside your Salesforce org. The PageReference object functions less as a page reference mechanism, and more as a page redirection mechanism.

Action methods

In Visualforce, you can define action methods using the <apex:commandButton> and other tags. These action methods allow you to define certain tasks that should be carried out when the corresponding button or link is clicked on a visualforce page. One of the main differences between an action method and a regular method is that an action method should return an object of type PageReference upon completion. You can define an action method as returning nothing (void), but that is equivalent to returning a NULL PageReference object.

PageReference in action

In order to understand how the PageReference is used for page redirection in Visualforce, let us look at a simple example. I have created a simple Visualforce page that has a single commandbutton, which invokes an action method on the controller called "saveMethod()". The saveMethod returns a new PageReference object, that is instantiated as a reference to www.google.com.

Visualforce Page

    
     
 


Apex Controller
public class MyPage_Controller {
 public PageReference saveMethod()
    {
  PageReference pgref = new PageReference('http://www.google.com');
        pgref.setRedirect(true);
        return pgref;
    }
}

Create both the Visualforce page and controller above in your org. Browse to the Visualforce page and click the "Click Me" button. You should be automatically redirected to the google home page.

What's going on under the hood

In order to better understand what was going on, I tried to analyze the redirect using Fiddler. For those of you who are hearing about it for the first time, Fiddler is a web traffic analysis tool that allows you to look at the request/responses(and much more) of all web traffic on your computer. So, using Fiddler, I looked at the page submit action that happened when I clicked on the "Click Me" button, and this is what I saw :-



In the above screenshot, the top portion is indicates the "request", whereas the bottom portion indicates the "response". Look at the highlighted block in the top portion - this shows that the page /apex/MyPage was submitted via a POST request. The response is more interesting - the page returned a piece of javascript as the response, which basically did the job of redirecting the user to www.google.com (window.location.replace('http://www.google.com')).

To summarize, here's what happened-
A. User clicks on the button to submit the page via HTTP POST
B. The controller method "saveMethod" is executed, and the method returns a PageReference to www.google.com.
C. Visualforce detects the PageReference, and returns a script as a response that immediately redirects the user to www.google.com.

Redirecting to another page within Salesforce

Let us tweak the code a little bit to see what happens when the PageReference points to a Salesforce standard page. Replace your controller method with the below:-

Apex Controller
public class MyPage_Controller {
 public PageReference saveMethod()
    {
        Account acc = [select Id, Name from Account LIMIT 1];
        // Redirect to an account
  PageReference pgref = new PageReference('/' + acc.Id);
        pgref.setRedirect(true);
        return pgref;
    }
}

Checkout the Fiddler logs now -



As you can see from the highlighted response, the POST request again returned a javascript response that redirected the user to the correct account page. So, in most cases, the "modus operandi" here is that whenever you return a PageReference object from an action method, Salesforce sends some javascript as a response which redirects the user to another page. I said "in most cases" because there are some exceptions to this rule.

The setRedirect method

The PageReference class also provides the setRedirect method, that allows you to set the "redirect" flag to true or false. The Salesforce documentation on the use of setRedirect is quite ambiguous.
This page states that "Notice in the code above that the redirect attribute for the PageReference is set to true. If this attribute is not set, the PageReference is returned to the browser, but no navigation occurs—the URL for the original page remains the same. If you want to change the URL as a result of navigation, you have to set the redirect attribute". As we will see in a little bit, this is misleading. A more accurate description can be found at this page, which states that "If set to false, the redirect is a server-side forward that preserves the view state if and only if the target page uses the same controller and contains the proper subset of extensions used by the source page".

In order to understand the behavior of the setRedirect method, let us create a second Visualforce page that uses the same controller. We will then modify the controller "saveMethod" so that upon clicking the button on the first page, you will be redirected to the second page.

Second VF Page

    
     Hello, this is the second page.
     


Apex Controller
public class MyPage_Controller {
 public PageReference saveMethod()
    {
        // Checkout how you can refer to an existing VF page with Page.[VF Page Name]
  PageReference pgref = Page.MyPage_II;
        pgref.setRedirect(true);
        return pgref;
    }
}

If you look at the Fiddler logs now, it's similar to the previous ones, wherein a redirect is performed via client-side javascript.



However, let us now change the setRedirect to "false", and see the results.
public class MyPage_Controller {
 public PageReference saveMethod()
    {
  PageReference pgref = Page.MyPage_II;
        pgref.setRedirect(false);
        return pgref;
    }
}



Surprise, surprise. Instead of doing a client-side redirect, Salesforce did a server-side redirect and returned the HTML for the new page in the response. Note that the server-side redirect was done in this case because the MyPage_II page shared the same controller as the original page. So, the rule is if the page to which the redirect happens shares the same controller as the page that did the redirect, then Salesforce will do a server-side redirect. In all other cases, a client-side redirect is done by sending the redirection javascript in the response.

With that, I'm wrapping up my post on the PageReference. Hope you found it helpful.

Using Merge fields in Visualforce pages

Merge fields are an important part of building visualforce pages. They allow you to embed property or object values in your apex controller directly into the HTML generated by the corresponding Visualforce page. Let’s look at an example to understand that statement:
Visualforce Page
    
 
Apex Controller
public class MergeFields_Controller 
{    
    public DateTime CurrentTime
    {
        get{
            return DateTime.Now();
        }
    }
}


In the above sample, we have created a simple Visualforce page and its associated controller. CurrentTime is a read-only property defined in the controller that always returns the current date & time. The property is displayed on the page using the merge field expression {!CurrentTime}.
Type Conversions with merge fields

When displaying merge fields as text, Salesforce automatically converts the property value to String data type. This has the same effect as called the toString() method on the property. Example below:
Visualforce Page

    
    
    


Apex Controller
public class MergeFields_Controller 
{
    public class C1
    {
        public integer i;
        C1(integer val)
        {
            i=val;
        }
    }        
    public DateTime CurrentTime
    {
        get{
            return DateTime.Now();
        }
    }    
    public C1 theObject
    {
        get{
            return new C1(50);
        }
    }    
    public String theObject_String
    {
        get{
         return theObject.toString();
        }
    }
}


In the above code, I am rendering three different properties using merge fields. CurrentTime is of type DateTime, whereas theObject is of type C1, which is a new class that I have defined. Lastly, theObject_String is a String representation of theObject by calling the toString() method on the object. In the output below, you can see that the object is rendered as a string when used in a merge field.



image

Using Apex in merge fields

A common misunderstanding is trying to use Apex code in merge fields – merge fields do not allow Apex code. Instead, merge fields are similar to formula fields, and you can use most expressions used in formula fields with merge fields. For e.g., use the following expression to display the current date/time:
  
The above merge expression will display something like
8/10/2014 9:30 PM.

Not all functions that can be used in formula fields can be used in merge expressions. For e.g., the following will throw an error when used in a merge field, even though you can use it in a formula field:
 

A good rule of thumb is that formula expressions which do not add new non-text elements (like images, hyperlinks etc.) to the visualforce page are prohibited with merge fields.
Type Conversion **conditions apply
Not all merge field expressions are converted automatically to String. Automatic type conversion happens only when the property is used directly in the merge field, and is not used with any formulas. If used with formulas, the property value is not converted to string during formula evaluation. Rather, the formula expression is first evaluated, and the result is then converted to String. As an example, in the below code sample, the expression {!LEN(CurrentTime)} will not work because the LEN() function expects an argument of type String, whereas CurrentTime is of type DateTime. :
Visualforce Page


     

    

Apex Controller
public class MergeFields_Controller 
{       
    public DateTime CurrentTime
    {
        get{
            return DateTime.Now();
        }
    }
}
Input data using merge fields
Merge fields are also used to accept input data from users. For e.g., the below code accepts text input from the user using <apex:inputText>, and then displays the input text back on the screen using an <apex:outputText>.
Visualforce Page


    

    Enter the value of str :                  
    Enter the length of str :    

Apex Controller
public class MergeFields_Controller 
{
    public String str
    {
        get; set;
    }
}

Note that in the above example, we're accepting an input value in the , and assigning it to the property str. Also note that you cannot use formulas when using merge fields to accept user input.

Calling External Web Services from Salesforce.com – Part IV: Returning an array from the external web service

We went over the basics of invoking an external web service from Salesforce.com Apex code in Parts I, II & III of this series. In this article, we will go over returning an array from the external web service back to Salesforce.com.

Let’s dive into the specifics right away:

  • First, create your asp.net web service (I used Visual Studio 2008). I just created a basic asp.net web service called ArrayWebService, and changed the HelloWorld() method to the “GetArray()” method instead, with a string array as the return type. Here’s my web service code, I have highlighted the important parts:-
Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Services;
  6.  
  7. namespace ArrayWebService
  8. {
  9.     /// <summary>
  10.     /// Summary description for Service1
  11.     /// </summary>
  12.     [WebService(Namespace = "http://tempuri.org/")]
  13.     [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  14.     [System.ComponentModel.ToolboxItem(false)]
  15.     public class Service1 : System.Web.Services.WebService
  16.     {
  17.         [WebMethod]
  18.         public string[] GetArray()
  19.         {
  20.             return new String[] {
  21.                 "Empire State Building"
  22.                 , "Rockefeller Center"
  23.                 , "Wall Street"
  24.                 , "World Trade Center"
  25.                 , "Statue Of Liberty" };
  26.         }
  27.     }
  28. }
  • Next, publish your web service. In solution explorer, right-click on the web service, and select publish as shown in Figure 1 below. This is required to “publish” your web service to the local IIS. Prior to doing this, make sure you have a folder called “ArrayWebService” created under your local IIS folder (usually this is C:\InetPub\wwwroot).

image 

  • On the “Publish Web” screen, enter the path as shown in Figure # 2 below. Make sure that the options are selected as shown. Hit Publish – this should copy all of your project files under the C:\InetPub\wwwroot\ArrayWebService folder.                 

image

image

  • You need to now make sure that your web service is now callable by salesforce.com. In order for this to happen, your web service should be “exposed” to the internet. If you are on a company network, you are most likely behind a firewall and salesforce.com will not be able to access your web service. I would like to suggest here that you go through Part II of this article series to understand how to use port forwarding to expose your WS to Salesforce.com.
  • To test if your web service is working correctly, go to http://www.webpagetest.org/, and in the web site address, enter your web service’s address – this should be something like http://{your IP Address}/ArrayWebService/Service1.asmx.  
  • If you are able to run your web service locally, but are having trouble testing it from “webpagetest.org”, it is most likely that your web service is not yet exposed to the internet. Consult the network person at your firm to check how you can fix this.
  • Once you are able to successfully test the WS, try creating a class in Salesforce.com from the web service WSDL – detailed description of this process is covered in Part III of this series – go through it to understand how to create the class on the Salesforce side using your web service WSDL.
  • When you create the class in Salesforce, the code should look like the below. Take special note of the fact that I have modified the IP Address of the web service to go to my machine. Another thing to note here is that the “GetArray” method does not return a string array – instead, it returns an object of type “InvokeArrayWebService.ArrayOfString”. This means that when invoking the method, we will have to write one more extra step to extra the return result from the ArrayOfString return object.
Code Snippet
  1. //Generated by wsdl2apex
  2.  
  3. public class InvokeArrayWebService {
  4.     public class GetArrayResponse_element {
  5.         public InvokeArrayWebService.ArrayOfString GetArrayResult;
  6.         private String[] GetArrayResult_type_info = new String[]{'GetArrayResult','http://tempuri.org/','ArrayOfString','0','1','false'};
  7.         private String[] apex_schema_type_info = new String[]{'http://tempuri.org/','true','false'};
  8.         private String[] field_order_type_info = new String[]{'GetArrayResult'};
  9.     }
  10.     public class GetArray_element {
  11.         private String[] apex_schema_type_info = new String[]{'http://tempuri.org/','true','false'};
  12.         private String[] field_order_type_info = new String[]{};
  13.     }
  14.     public class ArrayOfString {
  15.         public String[] string_x;
  16.         private String[] string_x_type_info = new String[]{'string','http://www.w3.org/2001/XMLSchema','string','0','-1','true'};
  17.         private String[] apex_schema_type_info = new String[]{'http://tempuri.org/','true','false'};
  18.         private String[] field_order_type_info = new String[]{'string_x'};
  19.     }
  20.     public class Service1Soap {
  21.         public String endpoint_x = 'http://76.116.65.169/arraywebservice/service1.asmx';
  22.         public Map<String,String> inputHttpHeaders_x;
  23.         public Map<String,String> outputHttpHeaders_x;
  24.         public String clientCertName_x;
  25.         public String clientCert_x;
  26.         public String clientCertPasswd_x;
  27.         public Integer timeout_x;
  28.         private String[] ns_map_type_info = new String[]{'http://tempuri.org/', 'InvokeArrayWebService'};
  29.         public InvokeArrayWebService.ArrayOfString GetArray() {
  30.             InvokeArrayWebService.GetArray_element request_x = new InvokeArrayWebService.GetArray_element();
  31.             InvokeArrayWebService.GetArrayResponse_element response_x;
  32.             Map<String, InvokeArrayWebService.GetArrayResponse_element> response_map_x = new Map<String, InvokeArrayWebService.GetArrayResponse_element>();
  33.             response_map_x.put('response_x', response_x);
  34.             WebServiceCallout.invoke(
  35.               this,
  36.               request_x,
  37.               response_map_x,
  38.               new String[]{endpoint_x,
  39.               'http://tempuri.org/GetArray',
  40.               'http://tempuri.org/',
  41.               'GetArray',
  42.               'http://tempuri.org/',
  43.               'GetArrayResponse',
  44.               'InvokeArrayWebService.GetArrayResponse_element'}
  45.             );
  46.             response_x = response_map_x.get('response_x');
  47.             return response_x.GetArrayResult;
  48.         }
  49.     }
  50. }
  • Next, I created an anonymous code block with the below piece of code. Take special note of the highlighted portion – since the GetArray() method is returning an object of type “InvokeArrayWebService.ArrayOfString”, we cannot directly access the array being returned. We need to go into the “string_x” object inside the returned object to get the returned array.
Code Snippet
  1. InvokeArrayWebService.Service1Soap s1 = new InvokeArrayWebService.Service1Soap();
  2. InvokeArrayWebService.ArrayOfString arrayofstring;
  3. arrayofstring = s1.GetArray();
  4. String [] returnArray = arrayofstring.string_x;
  5. for(String s: returnArray)
  6. {
  7.     System.Debug('*****************' + s);
  8. }
  • If you look carefully at the class generated from the WSDL, you can figure it out yourself. The ArrayOfString object has a string[] named string_x – this is the object that will contain the return value. You can inspect the “field_order_type_info” object to deduce this.
Code Snippet
  1. public class ArrayOfString {
  2.     public String[] string_x;
  3.     private String[] string_x_type_info = new String[]{'string','http://www.w3.org/2001/XMLSchema','string','0','-1','true'};
  4.     private String[] apex_schema_type_info = new String[]{'http://tempuri.org/','true','false'};
  5.     private String[] field_order_type_info = new String[]{'string_x'};
  6. }
  • So, there you go, this is how you can return an array from an external web service to the Salesforce.com apex class.

Calling External Web Services from Salesforce.com – Part III: Building an Apex class that calls your web service

Part I: Hosting your web service
Part II: Opening your web service to the internet
Part III: Building an Apex class that calls your web service

In Part I & Part II of this series, I discussed the details of hosting a web service on your computer and exposing it to the internet. If you are working in an enterprise/corporate network environment, your web service is almost always not exposed to the internet. If so, I would encourage you to also read Part I & II of this series, so you get a basic idea on how to expose your web service so that Salesforce can connect to it. In this part, we will do the fun stuff – building an Apex class that can call this web service. Before we proceed, let us revise what happens when Salesforce calls our web service -

image

1 – Our custom Apex class hosted on the Salesforce.com platform makes an outbound web service call.
2 – The call reaches our modem that forwards it to the wireless router.
3 – Since port forwarding is turned on, the router then forwards the request to our computer’s IP Address.
4 - The computer’s firewall intercepts the request, and since we opened port 80 on the firewall, lets it pass through.
5 – The IIS on the computer receives the web service request, and services it.

Now that we have the basics cleared off, let’s get into the specifics – here are step-by-step instructions on building an Apex class that calls your web service :-

  • First, we need to get the WSDL file for our web service. The WSDL(Web service definition language) file is an XML-based representation of our web service – what methods it contains, data types of method parameters, return types, and the communication protocol related details.
  • To get the WSDL, simply open a browser and navigate to your web service, passing in ?wsdl as a query string parameter. For my web service, I navigated to http://localhost/MyWebService/Service1.asmx?wsdl (if you haven’t yet hosted the web service on your computer, read Part I of this article series.
  • If your web service is hosted correctly, you should see a block of XML in your browser window. Save this as a file with .wsdl extension.
  • Next, log into Salesforce.com, and go to Setup->Develop->Apex Classes. A list of classes shows up. Here, click on the “Generate from WSDL” button.

image

image

  • On the next screen, click the “Choose File” button, and select the WSDL file you had saved previously. Click the “Parse WSDL” button to check the validity of the WSDL file.
  • Did you get an error saying “Error: Failed to parse wsdl: Found more than one wsdl:binding. WSDL with multiple binding not supported” ? Well, that happens because the WSDL file generated for an Asp.Net web service has multiple bindings.
  • Let me get into a little more detail – if you open and inspect the WSDL file, you will see a <wsdl:binding> element. The binding element defines how to use the web service with a particular protocol (e.g. http), the XML encoding, the name of the operation, input/output parameters etc. For some reason, an asp.net web service WSDL file has multiple nodes for bindings. I don’t know why it does that – both nodes appear the same to me, so I don’t see the point of repeating the same information twice. Anyway, this confuses Salesforce.com when we try to import the WSDL to create an Apex class.

image

image

  • So, we do what any good software engineer would do – remove the extra binding and proceed :). So go ahead, delete the second <wsdl:binding> node. Also remove the corresponding <wsdl:port> node that was using this binding. Try parsing the file again in Salesforce.com – this should go through without errors. When it asked for Apex class name, I used “MyWebServiceApex”.
  • Navigate to the Apex class (MyWebServiceApex), and check out the code. Specially note my notes about using the correct IP Address – I cannot stress this enough. By default, Salesforce.com uses http://localhost as the address for the web service – you need to edit that in the class to make sure it is connecting to your web service.

image 

Adding a Remote Endpoint

  • Before we run the code to call our web service, we also need to let Salesforce know that this web service could be trusted. For this, we define a “Remote Site” – go to Setup->Administration setup->Security Controls->Remote Site Settings.
  • Enter your web service address etc. here, and give it a unique name.

image

  • Now you can start testing your web service.

Testing our class via Anonymous blocks

  • Next, we will test the class we just created – launch the developer console (Setup->Developer console). Locate the “Execute” text block at the top – this is where we can put our anonymous code block.

image

  • Copy-Paste the below code into the anonymous code block -
Code Snippet
  1. MyWebServiceApex.Service1Soap s1 = new MyWebServiceApex.Service1Soap();
  2. String result;
  3. result = s1.HelloWorld();
  4. System.Debug(result);
  • When you execute the code, make sure to check the “Open Log” checkbox. This will launch your execution log file as soon as your anonymous block is executed. The piece of code here basically reaches out to the web service hosted on your computer, and invokes the “HelloWorld()” web method.

image

  • Verify the log file, and you should see the output of your “System.Debug” statement in the logs :-

image

So, these were the steps you can follow to invoke your web service from Salesforce.com. This approach has various applications – you could build an “event” mechanism so that external systems are alerted whenever something happens in Salesforce.com. Or, you could build an external logging facility that logs each and every page visit to an external database. We will explore some of the additional complexities of this process in the next post.

Calling External Web Services from Salesforce.com – Part II: Opening your web service to the internet

Part I: Hosting your web service
Part II: Opening your web service to the internet
Part III: Building an Apex class that calls your web service

I have to be honest – I did not know how to do this. Having always programmed in an enterprise environment, I never gave it a thought on hosting something that is open to the internet. Fine, everybody can’t know everything, right ? Anyways, I figured there would be others as ignorant as I am (was :)), so here’s step-by-step instructions on exposing your webservice to  the internet.

  • Disclaimer – the below description is for a specific setup – where you are on a home computer with a wireless router. Be prepared to adjust the process if your setup is different.
  • First, make sure you do this on your home computer, or a place where you have full control over the network setup, environment etc.
  • We will be using port forwarding to open up the web service hosted on the IIS on your machine to the internet. To understand what is port forwarding, start by looking at the diagram below. Your home computer is actually hosted behind a few things – firewall, modem, maybe a wireless router.
  • This ensures that nothing on the internet can directly connect to your computer. It will always have to go through the modem, and the firewall. If any malicious attempt is made, the firewall will block it. The exact details are much more sophisticated than this, but this much suffices for what we are trying to do.

image

  • This setup also affects the IP address of your computer. Open command prompt (Start->{type cmd}), and run “ipconfig”. Notice your IP Address - it will be something like 192.168.1.3. This is not a real IP address on the internet – instead, it is the “internal” IP address assigned to your computer by your modem.
  • So what is your real IP address ? Go to http://www.whatsmyip.org/ – this will show your real IP address. I found mine- it was 75.123.65.169. This again is a temporary IP address – the internet service provider can switch it at any time.

image

  • Given that the modem is our “face” to the internet, any request that comes to the IP Address 75.123.65.169 is routed to my modem. The modem may choose to either discard the request, OR, it may choose to forward the request to specific devices connected to it.
  • This is where port forwarding comes in – we basically “tell” the modem/router to forward any requests that come in from the internet on a specific port, to our computer. If we turn this on for port 80, which is used by web services, it means that any incoming web service call will be forwarded to our computer.
  • Enabling port forwarding is different for each setup, so I will walk you through what I did, and leave it to you to fill in the gaps for your particular network setup. First, I opened the administration page for my wireless router- this can be usually accessed by using the first 3 digits of your IP address + 1. For e.g., in my case, since my computer’s IP was 192.168.1.3, I opened my wireless router admin screen by visiting http://192.168.1.1 in the browser.
  • It may ask you for username/password – username is usually “admin”, you will need to know the password here – I did not know of any other way around it.
  • Once you are logged in, the screen looks like this for me:-

image

  • Next, I went to the “Advanced” tab –> “Advanced Settings” –> Port forwarding”. Here I configured it forward all HTTP requests (port 80) to my computer. This is how my setup looks like -

image

  • That’s it, all incoming HTTP requests will be forwarded to your computer now. However, we’re not done yet – these incoming requests will be blocked by your computer’s firewall. We need to open port 80 on the firewall as well.
  • Open Windows Firewall configuration - If you are on Windows 7, go to Control Panel->System & Security->Windows Firewall. From the left hand menu, choose “Allow a program or feature through Windows firewall”.

image

  • In the list of services that comes up, go to the last one (World Wide Web Services (HTTP)), and check both the private and public checkboxes.

image

  • Now we’re done – your web service is now callable from the internet.
  • To test this, visit http://www.webpagetest.org/, and put your web service URL. Your web service URL is - http://{your ip address}/MyWebService/Service1.asmx. For e.g., my web service IP address is - http://75.123.65.169/MyWebService/Service1.asmx.
  • So there you go, your web service should now be accessible from the internet. It is also now ready to be called by Salesforce. In my next post, we will go over the basics of calling this web service from Salesforce.com.

Calling External Web Services from Salesforce.com – Part I: Hosting your web service

Part I: Hosting your web service
Part II: Opening your web service to the internet
Part III: Building an Apex class that calls your web service

The other day, I read about the ability to call external web services from Salesforce.com, and decided to give it a try. I come from a Microsoft programming background, so I expected it to be simple & straightforward. I ended up jumping through hoops, and by the end of it, I had already decided to write this post to save others the trouble.

I decided to break the whole process down into four parts -
Part 1 – will focus on how to build the webservice that we will be using.
Part 2 – will focus on how to make the webservice accessible to Salesforce.com from the Internet.
Part 3 – will focus on the Apex code etc. required on the Salesforce side to call the web service.
Part 4 – will focus on advanced issues like error handling, arrays etc.

In this part, we will simply build an old-fashioned asp.net web service. Since this is a fairly routine task for any programmer worth his salt, I will keep the instructions as concise as I can. So, here goes:-

  • Launch Visual Studio – I am using Visual Studio 2008. Create a new Asp.Net web service (File->New->Project->Visual C#->Asp.Net Web Service Application). Name it “MyWebService”, and hit Ok.

image 

  • Hitting Ok should automatically generate a basic asp.net web service. In the solution explorer (View->Solution Explorer), there should already by a web service file named [Service1.asmx], and the corresponding C# code file [Service1.asmx.cs].
  • Hit F5, or go to Debug->Start Debugging from the menu to execute the web service. It should show you a page like the one below -

image

  • Next, you need to make sure that IIS is running on your machine. You can go to Start->{Type IIS in the search box}. This should launch IIS on your machine. If you don’t have it installed, you can visit this link to see how to install IIS.
  • Navigate to the IIS root folder- this is usually C:\inetpub\wwwroot. Create a new directory called “MyWebService” here. You will need administrative privileges on the machine for this.

image

  • Next, we are going to “Publish” the web service. Publishing is the process where the web service is actually “hosted” on IIS, instead of within visual studio.
  • In Solution Explorer, right-click on the project name, and select “Publish…”. In the “Publish Web” dialog box that comes up, click the ellipsis next to “Target location”, and navigate to the folder we just created.

image 
image

  • Make sure that you select the option “All project files” in the “Copy” section on the dialog box. and click “Publish”.
  • Once the publish is done, try navigating to http://localhost/MyWebService/Service1.asmx. If everything is setup correctly, this should bring up the web service page.

That wraps up our first part – creating a bare bones web service. In the next post, we will see how to expose this web service to the internet so that Salesforce.com can call it.

Prepopulating fields using URL hacking – Part 5: Multi-Select picklists

URL Hacking Series
Prepopulating fields using URL hacking – Part 1: The Basics
Prepopulating fields using URL hacking – Part 2: Prepopulating custom fields
Prepopulating fields using URL hacking – Part 3: Handling Special Characters
Prepopulating fields using URL hacking – Part 4: Passing in the Record Type
Prepopulating fields using URL hacking – Part 5: Multi-Select picklists
If you have been following my series on URL hacking, you must be an expert reading salesforce URLs by now. However, I recently found that you can never learn enough – one of my project requirements was to pre-populate the value for a multi-select picklist.
Here’s the situation, I added a custom multi-select picklist to the Contact object – here’s how it looks:-
image 
With this setup, suppose I want the Contact Edit page to load with the first two values in the “MyMultiSelectPicklist” field selected. Here’s the URL to do it:-
https://na9.salesforce.com/003E000000HCekT/e?retURL=%2F003E000000HCekT&00NE0000004AOP9=Value%201&00NE0000004AOP9=Value%202&00NE0000004AOP9=Value%205
Let’s go one by one – look at the highlighted part in the above URL. Here, “00NE0000004AOP9” is the ID of the multi-select picklist. How did I know ? To understand, first right-click on the multi-select picklist, and select “Inspect Element”. I’m assuming you are using Firefox or Chrome as your browser. Here’s how it looks in my chrome browser:-
image
If you look at the highlighted sections, it is clear that the ID for the multi-select picklist’s left side list box is “00NE0000004AOP9_unselected”, and that of it’s right-side list box is “00NE0000004AOP9_selected”. Multi-select picklists are a little special – you can get the ID of the multi-select picklist by removing the “_selected” or “_unselected”. So, that is how we get the ID “00NE0000004AOP9” as the ID for our picklist.
Next, look at the value being passed - “Value%205”. If you have read this article in this series, you would be able to spot that this is a URL encoded string. So, the “%20” in this case is the URL encoded value for a white space character. So in reality, the parameter value that we are passing is “Value 5”.
Let’s look at the URL again -
https://na9.salesforce.com/003E000000HCekT/e?retURL=%2F003E000000HCekT&00NE0000004AOP9=Value%201&00NE0000004AOP9=Value%202&00NE0000004AOP9=Value%205
As is clear from the highlighted values above, we are passing the same ID three times, with different values. And this is how you pass values for the multi-select picklists – you pass multiple values for the same picklist ID. So, in the above example, I am passing in values “Value 1”, “Value 2” & “Value 5”. Here’s what it looks like in my org when I visit that URL-
image
So there you go, you can now even pass in URL values for multi-select picklists.





Prepopulating fields using URL hacking – Part 4: Passing in the Record Type

URL Hacking Series
Prepopulating fields using URL hacking – Part 1: The Basics
Prepopulating fields using URL hacking – Part 2: Prepopulating custom fields
Prepopulating fields using URL hacking – Part 3: Handling Special Characters
Prepopulating fields using URL hacking – Part 4: Passing in the Record Type
Prepopulating fields using URL hacking – Part 5: Multi-Select picklists

In my series of posts on URL hacking, I explored how to pre-populate fields on Salesforce pages by passing the values in the page URL. In most Salesforce environments, there are multiple record types created on several objects. This can cause an issue with passing values in the URL, because whenever you visit an object create page, it first asks you for a record type.

For e.g., I set up two record types called “Internal” and “External” for the contact object, and it prompts me to choose the record type before proceeding.
image

To get around this, I started passing in the record type in the URL itself. Below is the URL I am using :-

https://na9.salesforce.com/003/e?retURL=%2F003%2Fo&RecordType=012E00000001nGY&ent=Contact&name_firstcon2=TestFName&name_lastcon2=TestLName

As highlighted above, you can actually pass in the record type ID in the URL. This will “preselect” what record type object you are creating, and hence you would not have to explicitly select the record type.

Since Salesforce requires that the Record type ID be passed, how do we get the record type ID ? Simply go into Setup—> Create –> Objects –> Record Types. When you look at the record type definition in Salesforce, the URL contains an ID field – this is the ID for your record type.

As an example, when I look at my record type, it’s URL is this (record type ID is highlighted) :-

https://na9.salesforce.com/setup/ui/recordtypefields.jsp?id=012E00000001nGY&type=Contact&setupid=ContactRecords

So this way, you can easily pass the record type in the URL itself, to avoid explicitly selecting the record type.