asp:Feature
Force.com for ASP.NET Developers
By Dave Nielsen
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 ll learn how to:
- 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 e-mail 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:
- 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.
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.
Figure 1: Pulling data from a
Force.com Web service to an ASP.NET Web form.
Several systems must connect to make this process happen:
- Your lead data stored in Force.com
- A Force.com Web service, which queries your Force.com data and exposes it outside 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 ll need Visual Studio 2005 (using Microsoft Visual Basic) and Visualforce. If you don t already have Visual Studio, you can get 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 ll 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 Apex Developer Network (ADN), you get a Developer Edition account as well as access to developer forums and other member benefits. Sign up for your free Force.com Developer Edition account.
Enable the Visualforce Developer Preview
Joining ADN gets you a Developer Edition account, but you ll still need access to the Visualforce Developer Preview. You ll receive a notification that Visualforce has been added to your account.
Next, use your new ADN credentials to log in to your Salesforce.com account. To enable development mode, click Setup | My Personal Information | Personal Information. Select the Development Mode checkbox, then click Save.
To confirm that Visualforce is now enabled, visit https://na2.salesforce.com/apex/LookupAddress1 (replace na2 with the sub-domain you see in the URL of your Developer Edition account). Note the Salesforce.com message. If the message says Page Sample1 does not exist ... Create page LookupAddress1 then Visualforce is enabled. If you do not see this message, then Visualforce is not enabled correctly. Repeat the process and confirm that the correct settings are selected.
Creating Visualforce pages is similar to creating a new ADN wiki page. Simply enter the URL you want to create and Visualforce offers to create the page for you!
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 set up and configuration for you. Furthermore, Salesforce.com handles future upgrades, so 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
You have two choices to expose business logic from Force.com to your application:
- You can create a Force.com class object.
- You can create a Force.com Web service.
You ll 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 ll show you how to use the global keyword with your class so 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.
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 in to 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 e-mail address. The query returns a lead object with only the Street, City, State, and PostalCode attributes.
Figure 3: Apex Class with
getLeadAddressByEmail method.
Creating a Force.com Web Service from Your Apex Class
To expose the methods in your Apex class as a Force.com Web Service, all you need to do is use the webService annotation within a global class. Also, be sure to use the static keyword, which is required for all Force.com Web services. And of course, you ll need to write the Web service code. The following code is the same as in the previous sample:
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;
}
}
Once you ve created your Force.com Web Service, you can generate the Web Service Definition Language (WSDL) document that describes the Web Service. This document will come in handy later in the process, when you use the Visual Studio Web Reference wizard to access the Force.com Web Service.
Visualforce
During Dreamforce 2007, Salesforce.com announced Visualforce: a new tool to create custom user interfaces and data interactions for the Force.com platform. Visualforce is a feature that developers can use to 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 also can use Visualforce to blend data from Web services into your applications so you can create special-purpose mash-up applications.
Let s create a Visualforce page that enables you to use an e-mail 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 ) 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.
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. Just type in the URL of the page you want to create, for example, https://na2.salesforce.com/apex/leadLookup1 (again, replace na2 with the subdomain that you see when you are logged into salesforce.com). You should see a page similar to Figure 5.
Figure 5: Visualforce creates pages
for you.
Click Create page leadLookup1 to create your page. You ll 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.
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. 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 you created in the previous section. Next, add the following code to your Page Editor:
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:
As soon as you click Save, you ll receive an error message stating Error: Apex class leadLookupController does not exist . This is expected behavior. Click Create Apex class leadLookupController . You ll get another error message stating Error: Unknown property leadLookupController1.searchString . Again, this is expected behavior. Click Create Apex method leadLookupController1.getSearchString . You ll 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, searchString 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 setSearchString(String val) {
emailString = val;
}
'''public''' String getSearchString() {
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 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:
The code uses the outputLabel values to output the results from the e-mail search by displaying the results from the getLeadAddressByEmail method of the getLeadInfo class.
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, I ll 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 checkbox is selected.
Next, add to your form a textbox, named txtEmail, and its associated label. This field will be used to look up the lead according to e-mail address. Then, add to your form textboxes named txtAddress, txtCity, txtState, and txtZip, along with the associated labels. These fields will be prefilled when the provided e-mail 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 e-mail 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, make sure that the class object is a global class and 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 two 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 log-in method of the Salesforce.com API. The log-in 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 must 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 ll 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 ll 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 textbox labeled URL. Type (or paste) the enterprise.wsdl file path into the URL textbox, 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 ll 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 log-in method and retrieve the session ID. The following code uses the sforce proxy object 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 ll 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 in to the URL textbox, 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 ll see the getLeadInfo proxy library created within the project s Web References folder.
Getting a Mailing Address from an E-mail Address
The connection from your Web form to your custom Force.com Web service is almost complete. The following code sample uses the getLeadInfo proxy object you created to query your custom Force.com Web service with the lead s e-mail 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 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 ve 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 in Figure 7.
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.
The code samples for this article are available for download.