You can move beyond the ECT and continue to use the same
WCF service that you deployed earlier to Windows Azure.
For example, what if you wanted to create a simple dashboard that
provided you with a view of customers from your external list and also retrieved each customer’s credit
score so that you could then dynamically update an Excel Services
model in SharePoint? This would mean that you could use the WCF service that you deployed to Windows Azure for dual
purposes: first, you can create a view of the latest list of customers
that are retrieved with your service, and then you could model, say, a
mortgage amortization schedule based on their credit scores.
This doesn’t require much more than what you’ve done already;
you’ve already deployed the WCF service to Windows Azure; you’ve
already got an external list; and you’ve already got a document
content type that also uses your ECT. What you could use, though, is
Excel Services along with some nifty jQuery and JavaScript to build a
dynamic amortization model that adjusts the interest rate based on a
credit score.
Excel Services provides a set of server-driven capabilities with
which you can build and deploy applications to SharePoint that take
advantage of the Excel engine. For example, with special Excel Web Access Web Parts, you can surface specific
objects, such as charts or named ranges. You can also take advantage of
Excel’s calculation engine and update tables in a Web Part
dynamically. You can also use the new REST capabilities to access
specific elements in an Excel spreadsheet and expose them in
SharePoint via REST URIs—another option beyond the Excel Web Access
Web Part. And finally, the calculation is not just read-only; you can
use the JavaScript object model to save changes back to an Excel
document.
To create a dashboard that achieves some of the above tasks,
you’d need to create an Excel document that can be used as the dynamic
model and a JavaScript application that calls the web service to get
the credit score. In this exercise, you’ll also create a simple
ASMX web service that mediates the cross-domain call to
the Windows Azure WCF service to retrieve the single integer value you’ll
need to update the model.
Create a Dynamic Mortgage Amortization Application by Using
Excel Services
-
Open the Visual Studio solution, right-click the solution,
select Add | New Web Site, and select ASP.NET Web Service.
Provide a name for the website (such as CreditScore), and click OK. -
When the project has been created, right-click the new
ASP.NET service and select Add Service Reference. Add a service
reference to the WCF service you deployed to Windows Azure, and
provide a descriptive namespace for the reference (such as
AzureServiceReference). -
In the App_Code folder, double-click the Service.cs file
and amend the code to reflect the following bolded code
snippet:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using AzureServiceReference;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class Service : System.Web.Services.WebService
{
public Service()
{
}
[WebMethod]
public int GetRate() {
int rate;
AzureServiceReference.GetCustomersClient myProxy = new GetCustomersClient();
rate = myProxy.GetPersonalCreditScore();
return rate;
}
} -
Next, create a directory on your local server and map that
server to a new Internet Information Services
(IIS) website. (That is,
open IIS, right-click Sites, and select Add Web Site. Then
provide a site name, the path to the directory you just created,
and a unique port number for the service. You might also want to
click Connect As and configure a specific test account—for
example, administrator—to run the service while you’re testing
it. You’d want to ensure that you don’t use an open security
account when deploying this in a production environment.) -
Return to your Visual Studio solution, right-click the
ASP.NET web service project, and select Publish Web Site. Browse
to the virtual directory you created and mapped to the IIS
website, and click OK. Your proxy service is now
published. -
Now that you’ve created the proxy service, which your
jQuery/JavaScript will use, the next step is to create an Excel
spreadsheet that you can use with this example. Refer to the
following image to create your spreadsheet for this example. As you can see, there
is a named range called Forecast that contains monthly estimates
for payments cutting across four years. Imagine that this
represents a four-year adjustable-rate mortgage (ARM), and that
depending on your credit score the interest rates (in the
Mortgage Interest cells B15, C15, D15, and E15) will be updated
dynamically using Excel Services in SharePoint. Save the Excel document as
Forecast.xlsx.
When you’ve saved the document, return to the Visual
Studio project. -
Right-click the solution and select Add | New Project.
Select SharePoint in the templates category, and then select
Empty SharePoint Project. Provide a name for the project (such
as JQueryServiceCall), and click
OK. Configure the project as a farm-level solution, and click
Finish to create the project. -
Right-click the newly created project, and select Add |
New Item. In the New Item dialog box, select SharePoint and then
Module. Provide a name for the module (such as ExcelDocument) and click Add. Do this two
more times, with the name of the second module being JavaScript and the third module being
jQueryFiles.
Modules, as you might know, support the deployment of
resources to SharePoint. In this example, you need to deploy
three files: an Excel document (the one you just created), a
JavaScript file, and the jQuery libraries. Modules are a great
way to deploy all of these files to a specific location in a
SharePoint site. When a module is added to a SharePoint project,
by default it adds a sample.txt file with some configuration
information (such as the deployment location of file) in an
Elements.xml file. -
In each of the modules, delete the sample.txt files that
were created by default. -
In the ExcelDocument module,
right-click the module and select Add | Existing Item. Navigate
to where you saved the Excel document, and add it to the module.
Amend the XML in the Elements.xml file as shown in the following
code snippet:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="ExcelDocument" Url="SiteAssets">
<File Path="ExcelDocument\Forecast.xlsx" Url="SiteAssets/Forecast.xlsx"
Type="GhostableInLibrary" />
</Module>
</Elements> -
In the jQueryFiles module, add the
jquery-1.4.2.js library. (You can download the libraries from
http://docs.jquery.com/Downloading_jQuery). To
add the file, right-click the module and select Add | Existing
Item. Navigate to where you downloaded the jQuery library, and
add it to the module. Your elements.xml file should look like
the following code snippet:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="jQueryFiles" Url="SiteAssets">
<File Path="jQueryFiles\jquery-1.4.2.js" Url="SiteAssets/jquery-1.4.2.js"
Type="GhostableInLibrary" />
</Module>
</Elements> -
In the JavaScript module, right-click
the module and select Add | New Item. Select Web and then HTML
page. Provide a name for the HTML page (such as AzureServiceCall.html) and click Add. The
elements.xml file for the newly added HTML file should look like
the following:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="JavaScript" Url="SiteAssets">
<File Path="JavaScript\AzureServiceCall.html" Url="SiteAssets/AzureServiceCall.
html" Type="GhostableInLibrary"/>
</Module>
</Elements> -
In the JavaScript module,
double-click the newly added HTML page and add the following
code:
<html >
<head runat="server">
<title></title>
<script type="text/javascript" src="http://blueyonderdemo/SiteAssets/SiteAssets/
jquery-1.4.2.js"></script>
<script language="javascript" type="text/javascript">
var ewa = null;
var credScore = null;
var fiscalYear = new Array();
var soapEnv = "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/
XMLSchema-instance' \
xmlns:xsd='http://www.w3.org/2001/XMLSchema' \
xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'> \
<soap:Body> \
<GetRate xmlns='http://tempuri.org/' /> \
</soap:Body> \
</soap:Envelope>";
if (window.attachEvent) {
window.attachEvent("onload", ewaOmPageLoad);
}
else {
window.addEventListener("DOMContentLoaded", ewaOmPageLoad, false);
}
function ewaOmPageLoad() {
if (typeof (Ewa) != "undefined") {
Ewa.EwaControl.add_applicationReady(ewaApplicationReady);
}
else {
alert("Error");
}
}
function ewaApplicationReady() {
ewa = Ewa.EwaControl.getInstances().getItem(0);
}
function btnGetData_onclick() {
jQuery.ajax({
url: "http://contosohockey:44321/Service.asmx",
type: "POST",
dataType: "xml",
data: soapEnv,
success: processResult,
contentType: "text/xml; charset=\"utf-8\""
});
return false;
}
function processResult(xData, status) {
var msg = $(xData);
credScore = parseInt(msg[0].text);
if (credScore<620)
{
fiscalYear[0] = "5";
fiscalYear[1] = "6";
fiscalYear[2] = "7";
fiscalYear[3] = "8";
}
else
{
fiscalYear[0] = "3";
fiscalYear[1] = "4";
fiscalYear[2] = "5";
fiscalYear[3] = "6";
}
document.getElementById("txtbxFY1").value = fiscalYear[0] + "%";
document.getElementById("txtbxFY2").value = fiscalYear[1] + "%";
document.getElementById("txtbxFY3").value = fiscalYear[2] + "%";
document.getElementById("txtbxFY4").value = fiscalYear[3] + "%";
ewa.getActiveWorkbook().getRangeA1Async("'Forecast'!Q1_Forecast",
getRangeComplete, [[fiscalYear[0]]]);
ewa.getActiveWorkbook().getRangeA1Async("'Forecast'!Q2_Forecast",
getRangeComplete, [[fiscalYear[1]]]);
ewa.getActiveWorkbook().getRangeA1Async("'Forecast'!Q3_Forecast",
getRangeComplete, [[fiscalYear[2]]]);
ewa.getActiveWorkbook().getRangeA1Async("'Forecast'!Q4_Forecast",
getRangeComplete, [[fiscalYear[3]]]);
}
function getRangeComplete(asyncResult) {
var range = asyncResult.getReturnValue();
var value = asyncResult.getUserContext();
var values = [[value]];
range.setValuesAsync(values);
range.activateAsync();
}
</script>
<style type="text/css">
//Removed styles to reduce length of code snippet.
//You can get the styles from the companion code.
...
</style>
</head>
<body>
<div>
<table>
<tr>
<td class="style3"><p class="style7">Mortgage Calculator</p></td>
</tr>
</table>
<div class="style9" style="width: 870px">
Enter your name, address and SSN and click Get Data to retrieve your credit scores
and create a mortgage model based on that credit score.
</div>
<table>
<tr>
<td class="style1">Name:</td>
<td><input name="Name" type="text" style="width: 316px" /></td>
</tr>
<tr>
<td class="style1">Address:</td>
<td><input name="Address" type="text" style="width: 316px" /> </td>
</tr>
<tr>
<td class="style1">SSN:</td>
<td><input name="SSB" type="password" style="width: 195px" /></td>
</tr>
</table>
<table>
<tr>
<td class="style10"></td>
<td><input class="style7" id="btnGetData" type="button" value="Get Data"
onclick="btnGetData_onclick();" /></td>
<td class="style8"></td>
</tr>
</table>
<div class="style9" style="width: 870px">
Based on your credit score, your 4-YR ARM mortgage rates are as follows:
</div>
<table>
<tr>
<td class="style1"> <strong>Y1</strong></td>
<td class="style1"> <strong>Y2</strong></td>
<td class="style1"> <strong> Y3</strong></td>
<td class="style1"> <strong>Y4</strong></td>
</tr>
<tr>
<td>
<input id="txtbxFY1" type="text" disabled="disabled" style="width: 62px" /></td>
<td><input id="txtbxFY2" type="text" disabled="disabled" style="width: 62px" />
</td>
<td><input id="txtbxFY3" type="text" disabled="disabled" style="width: 62px" />
</td>
<td><input id="txtbxFY4" type="text" disabled="disabled" style="width: 62px" />
</td>
</tr>
</table>
</div>
</body>
</html>
There’s quite a bit of JavaScript and jQuery code here,
but in essence it accomplishes three things:
-
It calls the proxy web service to retrieve the credit score
from the WCF service deployed to Windows Azure. -
It then provides some conditional logic to determine a
specific interest rate based on the random number that’s
returned from the WCF service deployed to Windows Azure. -
Using the Excel Services JavaScript object model, it
updates the Excel Web Access Web Part that is on the same
page.
To manage interaction with the proxy web service, the code
contains several key variables that are used to instantiate the
Excel Web Access Web Part (ewa) and
calculate interest rates from the credit score
(credScore). Also, when it is parsing SOAP calls by using jQuery, this code uses a
string to represent the return information
(soapEnv). What might be new to you,
though, is the use of jQuery with SharePoint. You can use jQuery
to execute client-side scripts and add more processing power to
those client-side scripts. For example, the following
jQuery.ajax function provides a way to
parse the return integer from the service proxy, which can then
be used in the resulting JavaScript. On the successful calling
of the service, the btnGetData_onClick
event calls the processResult
function:
...
function btnGetData_onclick() {
jQuery.ajax({
url: "http://contosohockey:44321/Service.asmx",
type: "POST",
dataType: "xml",
data: soapEnv,
success: processResult,
contentType: "text/xml; charset=\"utf-8\""
});
...
The processResult function extracts
the credit score (msg = $(xData)) and then
uses that as a conditional value to determine the interest rate.
In this case, if the customer’s credit score is less than 620,
he is hit with higher interest rates. The fiscalYear
Array object is used to store the different interest
rates, which will then be used to update the different cells
exposed in the Excel Web Access Web Part:
...
function processResult(xData, status) {
var msg = $(xData);
credScore = parseInt(msg[0].text);
if (credScore<620)
{
fiscalYear[0] = "5";
fiscalYear[1] = "6";
fiscalYear[2] = "7";
fiscalYear[3] = "8";
}
else
{
fiscalYear[0] = "3";
fiscalYear[1] = "4";
fiscalYear[2] = "5";
fiscalYear[3] = "6";
}
...
After the conditional logic determines the interest rate
from the credit score, the code then reflects the rates in the
HTML page by setting the value property of a specific DOM element. After the rates are set, the
getActiveWorkbook method is called on the
ewa object (which represents the active
Excel Web Access object on the SharePoint page) and sets the
named cell with a specific value (such as
FY1 or FY2) using the
getRangeComplete function:
document.getElementById("txtbxFY1").value = fiscalYear[0] + "%";
document.getElementById("txtbxFY2").value = fiscalYear[1] + "%";
document.getElementById("txtbxFY3").value = fiscalYear[2] + "%";
document.getElementById("txtbxFY4").value = fiscalYear[3] + "%";
ewa.getActiveWorkbook().getRangeA1Async("'Forecast'!Q1_Forecast",
getRangeComplete, [[fiscalYear[0]]]);
ewa.getActiveWorkbook().getRangeA1Async("'Forecast'!Q2_Forecast",
getRangeComplete, [[fiscalYear[1]]]);
ewa.getActiveWorkbook().getRangeA1Async("'Forecast'!Q3_Forecast",
getRangeComplete, [[fiscalYear[2]]]);
ewa.getActiveWorkbook().getRangeA1Async("'Forecast'!Q4_Forecast",
getRangeComplete, [[fiscalYear[3]]]);
}
function getRangeComplete(asyncResult) {
var range = asyncResult.getReturnValue();
var value = asyncResult.getUserContext();
var values = [[value]];
range.setValuesAsync(values);
range.activateAsync();
}
All this JavaScript and HTML code combined provides you
with the ability to load the credit score from the WCF service in Windows Azure and dynamically
update a dashboard in SharePoint. -
After you’ve added this code, you’re ready to deploy the
code to SharePoint. To do this, right-click the SharePoint
project and select Deploy. All of the files that you created
will be deployed to a folder called SiteAssets. -
Navigate to the SiteAssets folder, click the Options menu
beside the Forecast.xlsx document, and select Edit In Microsoft
Excel. Click the File tab and then select Save & Send. Click
Save To SharePoint, click the Publish Options button, and then
ensure that the Forecast named range is selected as an option to
publish to Excel Services. When it is, save the document back to
SharePoint. -
You can now create your SharePoint dashboard. To do this,
create a new SharePoint Web Part page or site. Click Site
Actions and then Edit Page. -
Click the Insert tab and select Web Part. Navigate to the
Media And Content category, select Content Editor Web Part, and
click Add. -
When the Web Part has been added, click Edit Web Part, and
in the Content Link field provide a link to the deployed
AzureServiceCall.html file. -
Click OK to finish. The HTML page you deployed to
SharePoint should now load. -
Before you test the JavaScript code, select the Insert tab
and click Web Part. -
In the Business Data category, select Excel Web Access Web Part
and click Add. -
Select Click Here To Open Tool Pane. In the Tool Pane, add
a link to the Forecast workbook in the Workbook field and
Forecast (the named range you
want to surface in the Excel Web Access Web Part) as the named
item. Click OK. -
Finally, click Insert to add one last Web Part. Select
Business Data List in the Business Data category. Click Open The
Tool Pane to configure the ECT you created earlier. -
Click the Select A Content Type button, and then choose
the AzureCustomers content type and leave
the other defaults, as shown in the next image. -
Click OK to exit the Tool Pane when done.
You now have a SharePoint site that surfaces customer data
from Windows Azure through the external list (calling the WCF service), enables data entry (but more importantly
the calling of the proxy service to get the credit score), and
allows the updating of the Excel Web Access Web Part from the data
retrieved from Windows Azure—Figure 1 shows each of
these.
If you take a closer look at the Excel portion of the site, as
shown in Figure 2, you can see
that when you click the Get Data button, the
local service proxy calls out to Windows Azure, gets the credit
score, and updates the Excel Web Access Web Part with a set of
interest rates that provides an aggregate of what a customer would
pay.
Admittedly, you could do more to tighten the code. For
example, data from the ECT was not coded to autopopulate fields in
the Content Editor Web Part, and you’re limited in the parameters
that are passed to the WCF services.
|