368

The developer community, including those vested deeply in the Microsoft .NET platform, has expressed particular interest in using Force.com Web Services to expose data and business logic from the Force.com platform to custom, external applications.

This article will show you how to create custom Force.com logic that you can call from within a Force.com application or from within a custom ASP.NET application hosted outside Salesforce.com. You will learn how to do the following:

  • Create a custom Force.com function and expose it as a Web Service.
  • Create a Visualforce application that calls the custom Force.com function and displays the results within a Visualforce page.
  • Create a Microsoft ASP.NET Web form that retrieves data from the Force.com Web Service account and displays the results within an ASP.NET Web page.
  • Use an email address to look up a lead in a Salesforce.com account and return the lead’s listed mailing address, which can be used to pre-populate an online order form.

When finished with the article, you will understand how to do the following:

  • Use Apex code (a procedural on-demand language that is part of the Force.com platform) to expose a Simple Object Access Protocol (SOAP)-based Web Service from within Force.com.
  • Use Visualforce to consume the SOAP-based Web Service in a Force.com application.
  • Use Microsoft Visual Studio 2005 to consume the SOAP-based application from an external ASP.NET Web site.

This article provides a basic, high-level demonstration of Visualforce. For a more comprehensive introduction to Visualforce, I suggest that you read Jon Mountjoy’s Force.com Tutorial: An Introduction to Visualforce.

Getting Started

Before we move forward, let’s define exactly what “calling custom Force.com logic from Visualforce pages and ASP.NET Web forms” actually looks like. Figure 1 illustrates how Force.com Apex code, exposed as a Web Service to an ASP.NET Web form, pulls data out of Salesforce.com and displays it to a user viewing an ASP.NET Web page.

DotNet image1.gif
Figure 1. Pulling data from a Force.com Web Service to an ASP.NET Web form

In order to make this process happen, several systems must connect:

  • Your lead data stored in Force.com
  • A Force.com Web Service, which queries your Force.com data and exposes it outside of the Force.com platform
  • An ASP.NET Web Page that retrieves the data from the Web Service and displays it in a Web browser

Assembling Your Tools

For this walk-through, you will need Visual Studio 2005 (using Microsoft Visual Basic) and Visualforce. If you don’t already have Visual Studio, you can download a free copy of Microsoft Visual Web Developer 2005 Express Edition. You can use Visualforce to create unique user experiences and data interactions for use within your Force.com applications. Unlike Visual Studio, Force.com applications are available on-demand, through your Web browser. There is no software to install. Of course, you will need a Salesforce.com Developer Edition account with Visualforce enabled.

Getting a Free Force.com Developer Edition Account Login

You don’t need to use live company data and risk making a mess of things: Force.com Developer Edition accounts are free and easy to create. By joining the developer.force.com (DFC), you get a Developer Edition account as well as access to developer forums and other member benefits. Signup for your free Force.com Developer Edition account.

Force.com Web Services

Code that is written in a Microsoft .NET language (such as Visual Basic.NET or C#) is compiled into a Microsoft .NET assembly (a file with an.exe or .dll extension). Microsoft .NET assemblies are hosted by the Microsoft .NET Runtime, which must be installed on your computer (or Web server, if your application is an ASP.NET Web application). This Microsoft .NET runtime provides services to your application, manages memory and security to the user’s computer, and so forth.

Similarly, Force.com pages are hosted by the Force.com platform, which provides services such as security and memory management to your application. The primary difference between these two approaches is that you don’t need to set up any servers or configure any software to begin coding with Force.com. Salesforce.com does all the setup and configuration for you. Furthermore, Salesforce.com handles future upgrades so that you don’t have to worry about software updates, patches, or service packs.

Apex code, the procedural language that is a part of the Force.com platform, is very rigorous. You host your code in the Force.com platform, which in turn is hosted by Salesforce.com, so the code is checked for consistency and syntax when it is compiled for you. The code runs on Salesforce.com servers and therefore is multi-tenant and automatically upgradeable. Your custom methods and objects get all the scalability of the Force.com platform. Your Apex code won’t break when Salesforce.com introduces a new release of Force.com.

You don’t need to know how Force.com works internally to be productive and build applications quickly … but a little knowledge won’t hurt. For more information about the Force.com platform, visit the Platform page and read the Force.com whitepaper

Using Apex Code To Create a Force.com Web Service

To expose business logic from Force.com to your application, you have two choices:

  • You can create a Force.com class object.
  • You can create a Force.com Web Service.

You will use the Apex Class Editor in either option, but a Force.com Web Service provides the additional benefit of letting external applications access your Force.com business logic and data.

Fortunately, you can take advantage of both options simply by adding the global keyword in front of the class name, as Figure 2 shows. In this article, I will show you how to use the global keyword with your class so that your service can be available to your Visualforce application as well as to the ASP.NET Web page that we’ll create by using Visual Studio .NET.

DotNet image2.gif
Figure 2. Apex class with global keyword

Creating Your First Apex Class

To create a Force.com Web Service, you must first create an Apex class. To create an Apex class, log into your Developer Edition account, click Setup / App Setup / Build / Code, then click New. Next, add the following code into the body of the Apex Class Editor:

global class getLeadInfo {

}

Click Save.

Creating a Custom Apex Method

You put your Force.com business logic into a custom Apex method. To create your method, you’ll use Apex code, which runs within the Force.com platform and is available within other Force.com classes. As Figure 3 shows, this code contains a method called getLeadAddressByEmail, which uses Salesforce Object Query Language (SOQL) to look up a Lead record based on an email address. The query returns a lead object with only the Street, City, State, and PostalCode attributes.

DotNet image3.gif
Figure 3. Apex Class with getLeadAddressByEmail method



global class getLeadInfo {

  WebService static Lead getLeadAddressByEmail(string LeadEmail) {
    Lead c = [SELECT Street, City, State, PostalCode from Lead WHERE Email = :LeadEmail];
    Lead l = new Lead(Street = c.Street, City = c.City, State = c.State, PostalCode = c.PostalCode);
    
   return l; 

  }
}

Visualforce

Visualforce lets you create a customized application user interface. You can use Visualforce to shape the presentation of your Force.com applications by combining data from multiple Force.com objects. You can also use Visualforce to blend data from Web Services into your applications so that you can create special-purpose mash-up applications.

Let’s create a Visualforce page that enables you to use an email address to look up a lead in Salesforce.com and return the lead’s mailing address. We will use the Force.com Apex Class (“getLeadInfo”) that we created in the previous section. Figure 4 illustrates how a Force.com Web Service, exposed to a Visualforce page, pulls data out of Salesforce.com and displays it to the user.

DotNet image4.gif
Figure 4. Pulling data from a Force.com Web Service to a Visualforce page

Creating Your First Visualforce Page

To get started, create a Web page. As I mentioned earlier, creating a Force.com page within Visualforce is easy.

Go to Setup -> Develop -> Pages -> click on New button.

You will see a page similar to the one in Figure 6. Drag the top of the lower frame a few inches higher to see the Visualforce Page Editor.

DotNet image6.gif
Figure 6. Your first Visualforce page

In the lower frame, the Visualforce Page Editor shows you the code that makes up your page; in the upper frame, you’ll see a preview of the page. As you can see from the Visualforce Page Editor, a page is a combination of standard HTML elements and Apex tags. Visualforce also supports JavaScript, style sheets, Cascading Style Sheets (CSS), and most other capabilities with which Web developers are familiar, such as those available in Adobe Flash and Microsoft Silverlight.

Understanding Model-View-Controller

To understand Visualforce, it is helpful to understand the Model-View-Controller (MVC) design pattern. MVC is a common way of architecting applications and is used in a variety of application development frameworks. Many developers will find this pattern familiar.

At the heart of MVC is the idea of separating the user experience into three component roles:

  • The Model role, which represents the data used by the application.
  • The View role, which represents the application display of that data.
  • The Controller role, which handles the business logic that decides how the application behaves when it is engaged by the user.

For those of you familiar with ASP.NET, the role of Model is often played by a DataSet or DataTable. A typed ASP.NET DataSet, for example, can play the Model role by representing the data in your database. The View and Controller roles, however, can be translated only loosely into ASP.NET. The View role, for example, is usually handled by the .aspx file, and the role of Controller is partially handled by the code-behind page (e.g., .aspx.vb).

In Visualforce, the MVC roles are clearer. Standard and custom Salesforce objects play the Model role is. The Visualforce page handles the View role. And the Visualforce Controller handles the Controller role.

Note that in an October 2007 blog post, Scott Guthrie discussed the announcement that Microsoft is in the process of creating an ASP.NET MVC framework for developers to use within Visual Studio. While this framework won’t be on demand like Visualforce, it may make it easier for developers to switch back and forth between the two environments.

Calling Your Force.com Web Service from Your Visualforce Page

To access your Apex class (which has been exposed as a Web Service) from within Visualforce, you first need to create an entry page. Let’s use the leadLookup1 page that you created in the previous section. Next, add the following code to your Page Editor:

 <apex:page controller="leadLookupController">
	<apex:form>
		<apex:pageBlock title="Lead Search">
		<apex:outputLabel value="Email" />:
		<apex:inputText value="{!emailString}" />
		<apex:facet name="footer">
			<apex:outputPanel>
				<apex:commandButton action="{!step2}" value="Search" />
			</apex:outputPanel>
		</apex:facet>
		</apex:pageBlock>
	</apex:form>
 </apex:page>

Each Apex tag represents a Visualforce Component. For example, an outputLabel is an HTML control used to display a label for another component, such as the inputText. An inputText is an HTML control that acts as an input box for submitting information, such as the searchString variable. A commandButton is a control similar to an HTML button and can be set to submit, reset, or image. For a list of all Visualforce Components, click Component Reference ( in the same Web page section as Save).

This code sample also includes a reference to the page controller. To create a controller, add the controller attribute to the Apex page tag, as follows:

<apex:page controller="leadLookupController">

As soon as you click Save, you will receive an error message stating “Error: Apex class 'leadLookupController' does not exist”. This is expected behavior. Click Create Apex class 'leadLookupController'. You will get another error message stating “Error: Unknown property 'leadLookupController1.emailString'”. Again, this is expected behavior. Click Create Apex method 'leadLookupController1.getEmailString'. You will get a third error message stating “Error: Unknown method 'leadLookupController1.step2()'”. Once again, this is expected behavior. Click Create Apex method 'leadLookupController1.step2'. Your controller, emailString property, and step2 method all will be created.

Click the new Controller button (next to Page Editor) to see the code within the leadLookupController class. Next, add the code for the Controller:

 public class leadLookupController {
       private String emailString;
 
       public void setEmailString(String val) {
           emailString = val;
       }
 
       public String getEmailString() {
            return emailString ;
       }
 
 	public Lead getLead() {
	Lead lead = getLeadInfo.getLeadAddressByEmail(emailString);
	return lead;
	}
 
	public PageReference step2() {
	return Page.leadLookup2;
	}
 }

The getLead method calls the getLeadAddressByEmail method that you created earlier as a part of the getLeadInfo class, then returns an object of type Lead.

The PageReference step2 method redirects the application to leadLookup2 to display the search results. However, leadLookup2 doesn’t exist yet; you’ll need to add it. Follow the same steps you used to create leadLookup1. Paste the following code into your Visualforce Page Editor:

 <apex:page controller="leadLookupController">
	<apex:form>
		<apex:outputLabel value="Email" />: 
		<apex:outputLabel value="{!emailString}" /><br/>
		<apex:outputLabel value="Street" />: 
		<apex:outputLabel value="{!Lead.street}" /><br/>
		<apex:outputLabel value="City" />: 
		<apex:outputLabel value="{!Lead.city}" /><br/>
		<apex:outputLabel value="State" />: 
		<apex:outputLabel value="{!Lead.state}" /><br/>
		<apex:outputLabel value="Zip" />: 
		<apex:outputLabel value="{!Lead.postalcode}" /><br/>
	</apex:form>
 </apex:page>
 

The code uses the outputLabel values to output the results from the email search by displaying the results from the getLeadAddressByEmail method of the getLeadInfo class.

ASP.NET Web Form

Now you understand how to call your custom Force.com logic from within Visualforce. But as mentioned earlier, you may not be able to move your existing application and logic to Force.com overnight. In this next section, we will show you how to call your Force.com code from an external ASP.NET Web application. Create an ASP.NET Web Form

For the purposes of this article, we’re going to keep the Web form simple: a standard ASP.NET Web form in an ASP.NET Web site. Later, you can convert this Web form to an AJAX widget or business object. To create your Web form, first create a new ASP.NET Web site called SFLeadLookup.

Verify that the Default.aspx Web form has been generated. If you add a new Web form, make sure that the Place code in separate file check box is selected.

Next, add a text box, named txtEmail, and its associated label to your form. This field will be used to look up the lead according to email address. Then, add text boxes named txtAddress, txtCity, txtState, and txtZip, along with the associated labels, to your form. These fields will be prefilled when the provided email address is found.

Add a button to the form. Name the button cmdSubmit.

You are now ready to add the functionality to use a lead’s email to look up the lead’s address. This process requires the custom business logic that you created earlier. To access this custom business logic from ASP.NET, you must make sure that the class object is a global class and that the service is identified as static, as Figure 3 shows.

You can confirm and update as necessary by using Setup / App Setup / Build / Code and clicking Edit for the getLeadInfo class. Your business functionality is now ready to be accessed by your ASP.NET application or by any external application that has the appropriate credentials.

Web Service Enabling Your Web Form

To access your Force.com Web Service, your application must provide the user ID and password from a valid Salesforce.com account that has API access enabled. For this example, you’ll use your existing Developer Edition account because the API Enabled option is already selected. For production, you should create a custom profile to use only for accessing the API; this profile should have the API Only User property selected.

Your application must also pass a session ID string with each Web Service call. A session ID is a temporary ID provided by Salesforce. By default, session ID is valid for 2 hours. With Administration privileges, you can change the session expiration timeout through the Setup / Administration Setup / Security Controls / Session Settings interface.

Obtaining a session ID can be a challenge. Your ASP.NET Web form can request a session ID by making a Web Service call from Salesforce, using the user ID and password from your API-enabled account. This session ID can be stored locally in a database, text file, or application-level variable. It can be re-used by your application until the session expires, at which time your API-enabled user ID and password account may generate another session ID.

Obtaining a Session ID

To obtain a session ID, your application must query the login method of the Salesforce.com API. The login method will return a session ID, which your application will use to access your custom Force.com Web Service. To access the Salesforce.com API by using ASP.NET, you need to create a Web Reference.

To create a Web Reference from your ASP.NET application to the Salesforce.com API, you first must export the application’s WSDL document. To do this, visit Setup / App Setup / Integrate / API and click Download Enterprise WSDL. You will see the XML that describes this Web Service API. You can use the Enterprise WSDL document to access data directly from Salesforce.com, but for now, you will use this service to create a session ID.

Next, create a Web Reference within your Visual Studio project. Right-click the project name (e.g., SFLeadLookup) and select Add Web Reference. In the Add Web Reference dialog box, there is a text box labeled URL. Type (or paste) the enterprise.wsdl file path into the URL text box, then click Go. You should see the SForceService description displayed in the Add Web Reference window, along with many methods. Change the Web Reference name to sforce and click Add Reference. You will see the sforce proxy library created within your project’s Web References folder.

Next, you must add code to your Web form to access the SForceService login method and retrieve the session ID. The following code uses the sforce proxy object that you created to obtain a session ID.

Imports sforce

Partial Class _Default
   Inherits System.Web.UI.Page
   Private _userId As String = "[email protected]"
   Private _password As String = "mypassword"
   Private _sessionId As String
   Private _serverUrl As String
   Private _nextLoginTime As DateTime

   Protected Sub cmdSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles  cmdSubmit.Click
       ' See if Session ID exists
       _sessionId = IIf(Application("_sessionId") Is Nothing, Application("_sessionId"), "")
       _serverUrl = IIf(Application("_serverUrl") Is Nothing, Application("_serverUrl"), "")
       _nextLoginTime = IIf(Application("_nextLoginTime") Is Nothing, Application("_nextLoginTime"),   #1/1/2000#)
       If (Not isConnected()) Then
           getSessionInfo()
       End If

   End Sub

   Public Function isConnected() As Boolean
       If _sessionId <> "" And _sessionId <> Nothing Then
           If Now() > _nextLoginTime Then
               isConnected = False
           Else
               isConnected = True
           End If
       Else
           isConnected = False
       End If
   End Function

   Sub getSessionInfo()
       Dim lr As sforce.LoginResult
       Dim ss As sforce.SforceService = New sforce.SforceService
       lr = ss.login(_userId, _password)
       _sessionId = lr.sessionId
       Application("_sessionId") = lr.sessionId
       _serverUrl = lr.serverUrl
       Application("_serverUrl") = lr.serverUrl
       Application("_nextLoginTime") = Now()
   End Sub

End Class

Creating a Force.com Web Service Reference

The process of creating a Web Reference from your ASP.NET application to your Force.com Web Service is similar to creating a Web reference to the Salesforce.com API. First, you must export the WSDL document for the getLeadInfo class. Visit Setup / App Setup / Build and click WSDL (next to getLeadInfo). You will see the XML that describes the Web Service. Save the document to a location on your computer’s hard drive (e.g., c:\getLeadInfo.wsdl).

Next, create a Web Reference within your Visual Studio project. Right-click your project name and select Add Web Reference. In the Add Web Reference dialog box, type (or paste) the getLeadInfo.wsdl file path into the URL text box, then click Go. You should see your getLeadInfoService displayed in the Add Web Reference window, along with the getLeadAddressByEmail method. To make the Web Reference name more descriptive, change it to getLeadInfo and click Add Reference. You will see the getLeadInfo proxy library created within the project’s Web References folder.

Getting a Mailing Address from an Email Address

The connection from your Web form to your custom Force.com Web Service is almost complete. The red code in the following code sample uses the getLeadInfo proxy object that you created to query your custom Force.com Web Service with the lead’s email address (e.g., [email protected]). If the lead is found, the code displays the address (street, city, state, and zip code) for the lead. To keep things simple, no error trapping has been provided.

Add the following lines of red code to your Default.aspx code-behind page.

Imports sforce
Imports getLeadInfo


Partial Class _Default
   Inherits System.Web.UI.Page
   Private _userId As String = "[email protected]"
   Private _password As String = "mypassword"
   Private _sessionId As String
   Private _serverUrl As String
   Private _nextLoginTime As DateTime
   Private _leadEmail As String


   Protected Sub cmdSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdSubmit.Click
       ' Confirm Lead Email Exists
       _leadEmail = Me.txtEmail.Text
       ' See if Session ID exists
       _sessionId = IIf(Application("_sessionId") Is Nothing, Application("_sessionId"), "")
       _serverUrl = IIf(Application("_serverUrl") Is Nothing, Application("_serverUrl"), "")
       _nextLoginTime = IIf(Application("_nextLoginTime") Is Nothing, Application("_nextLoginTime"), #1/1/2000#)
       If (Not isConnected()) Then
           getSessionInfo()
       End If
       ' Call getLeadInfo Web Service
       Dim getLeadInfo As getLeadInfoService = New getLeadInfoService
       getLeadInfo.SessionHeaderValue = New getLeadInfo.SessionHeader
       getLeadInfo.SessionHeaderValue.sessionId = Me._sessionId

       Dim getLeadInfoResponse As getLeadInfo.Lead
       getLeadInfoResponse = getLeadInfo.getLeadAddressByEmail(_leadEmail)
       Me.txtAddress.Text = getLeadInfoResponse.Street.ToString
       Me.txtCity.Text = getLeadInfoResponse.City.ToString
       Me.txtState.Text = getLeadInfoResponse.State.ToString
       Me.txtZip.Text = getLeadInfoResponse.PostalCode.ToString
   End Sub

   Public Function isConnected() As Boolean
       If _sessionId <> "" And _sessionId <> Nothing Then
           If Now() > _nextLoginTime Then
               isConnected = False
           Else
               isConnected = True
           End If
       Else
           isConnected = False
       End If
   End Function

   Sub getSessionInfo()
       Dim lr As sforce.LoginResult
       Dim ss As sforce.SforceService = New sforce.SforceService
       lr = ss.login(_userId, _password)
       _sessionId = lr.sessionId
       Application("_sessionId") = lr.sessionId
       _serverUrl = lr.serverUrl
       Application("_serverUrl") = lr.serverUrl
       Application("_nextLoginTime") = Now()
   End Sub

End Class

Putting It All Together

Now that you have completed the coding, the only thing left to do is to build and run your project. The URL to your project will look something like the following:

http://localhost:3187/SFLeadLookup/default.aspx

The input and output will look like the Web form that Figure 7 shows.

DotNet image7.gif
Figure 7. ASP.NET Web form in action

Conclusion

With the release of the Force.com platform, Salesforce is demonstrating its commitment and ability to provide a complete development environment for building and delivering applications on the Force.com PaaS. You can take full advantage of the platform and build complete applications upon it or, as demonstrated in this article, you can extend the power of the Force.com platform to your ASP.NET Web applications.


Author -Dave Nielsen

For Further Reading

Code Download

Download the complete code samples for this article.