用于贷款支付计算的自定义 ASP.NET Ajax 控件






4.71/5 (4投票s)
2007年8月16日
4分钟阅读

51484

1191
本文介绍了一个自定义 ASP.NET Ajax 控件,用于计算贷款支付计划。
引言
我对 ASP.NET 还不太熟悉,但这项技术似乎非常有趣,所以我决定尝试构建一个自定义的 ASP.NET 控件。为了使这项任务更有趣,我尝试构建一个支持 Ajax 的控件。新控件必须能做一些有用的事情,所以我选择了构建一个抵押贷款(贷款)支付计划。最终的代码基于以下假设:
- 用于计算月供的贴现率使用以下公式计算:
((Math.Pow((1 + monthRate), monLength)) - 1) / (monthRate * (Math.Pow((1 + monthRate), monLength)))
- 月供中利息支付部分是通过将月利率乘以余额(尚未偿还的抵押贷款)来计算的。这意味着每个月,支付中的利息部分会减少,而抵押贷款偿还部分会增加。
这些假设在实践中可能不适用,但结果大致等于银行通常用于计算抵押贷款支付的金额。无论如何,此控件的目的不是要在官方网站上使用或做到完全精确,而是要实际了解自定义的 Ajax enabled ASP.NET 控件如何工作。我可以提前说,它工作得很好!
Using the Code
任何 Ajax 控件都由两大部分组成:服务器端(ASP.NET)和客户端(JavaScript)。要完全支持 Ajax,控件通常会将用户输入引起的任何 UI 渲染 - 在本例中,显示支付计划表 - 移至客户端。
为了最小化带宽,控件还应该只在 JavaScript 和服务器端代码之间交换数据,而不是标记。这意味着 UI 是使用 JavaScript 渲染的,而不是 HTML,而是调用网页 DOM 方法。当然,HTML 也可以由 JavaScript 构建,但这并不那么有趣或有效,对吧?
服务器端
主要的服务器端方法是 buildScheduleForClient
。此方法返回一个 JSON 编码的数据数组,该数据用于在客户端进行渲染,根据上述假设。当控件的特定实例发起回调时,此函数由 ASP.NET Ajax 架构调用 ICallbackEventHandler.GetCallbackResult()
调用。
private string buildScheduleForClient(int iMonthCount,
double dInterestRate, double dLoanAmount)
{
StringBuilder sb = new StringBuilder();
sb.Append("[");
sb.Append(String.Format("['{0}','{1}','{2}','{3}','{4}']",
_COL_MONTH, _COL_TOTAL_PAY, _COL_INTEREST_PAY,
_COL_LOAN_PAY, _COL_BAL));
double dDiscountRate =
LoanMath.CalculateDiscountRate(dInterestRate / 1200, iMonthCount);
double dMonthPayment = dLoanAmount / dDiscountRate;
double dMonthPaymentRounded = Math.Round(dMonthPayment, 2);
double balance = dLoanAmount;
for (int i = 1; i <= iMonthCount; i++)
{
double dInterestPayment = (dInterestRate / 1200) * balance;
double dCreaditRepayment = (dMonthPayment - dInterestPayment);
balance -= dCreaditRepayment;
sb.Append(String.Format(",['{0}','{1}','{2}','{3}','{4}']",
i.ToString(), dMonthPaymentRounded.ToString(),
Math.Round(dInterestPayment, 2).ToString(),
Math.Round(dCreaditRepayment, 2).ToString(),
Math.Ceiling(balance).ToString()));
if (i % 12 == 0)
{
sb.Append(String.Format(",['Year {0}, repayed {1}%']",
(i / 12),Math.Round((100 - ((balance / dLoanAmount) * 100)),
1)));
}
}
sb.Append("]");
return sb.ToString();
}
服务器端的另一个值得注意之处是如何包含所有相关的 CSS 和 JavaScript 资源。JavaScript 的包含比较容易:
- 将 *.js 文件添加到项目中。
- 将其“生成操作”更改为“嵌入的资源”。
- 添加一个带有媒体类型信息的属性 - 即
[assembly: WebResource("LoanCalculationControl.LoanCalculation.js", "application/x-javascript")]
- 到 AssemblyInfo 文件。 - 在控件的
OnPreRender
方法中添加以下代码。Page.ClientScript.RegisterClientScriptResource(this.GetType(), "LoanCalculationControl.LoanCalculation.js");
添加 CSS 会更复杂一些。OnPreRender
方法中的代码应该不同,并且您应该检查您的控件是否已有其他实例向页面添加了 CSS 引用。
// add css reference
string cssUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(),
"LoanCalculationControl.LoanCalculation.css");
LoanHtmlLink cssLink = new LoanHtmlLink();
cssLink.Href = cssUrl;
cssLink.Attributes.Add("rel", "stylesheet");
cssLink.Attributes.Add("type", "text/css");
bool cssAdded = false;
foreach(Control control in this.Page.Header.Controls)
{
if (control.Equals(cssLink))
{
cssAdded = true;
break;
}
}
if(!cssAdded)
this.Page.Header.Controls.Add(cssLink);
LoanHtmlLink
只是一个继承自 HtmlLink
并重写 Equals
方法的类。
客户端
与 Ajax 经常出现的情况一样,客户端更有趣(也更具挑战性)。客户端首先通过按钮的 onClick
事件包含一个适当的处理程序。ASP.NET 提供了一种方便的方法来输出适当的 JavaScript 以供回调调用。
Page.ClientScript.GetCallbackEventReference(this, null, "LoanCalculation.UpdateUI", String.Format("'{0}'", this.UniqueID), "LoanCalculation.CallbackError", true)
在方法参数中,我们列出了一个用于处理回调结果的 JavaScript 函数(LoanCalculation.UpdateUI
),上下文 - 在本例中是控件 ID,它是所有 UI 元素 ID 的一部分,以便在同一页面上包含多个控件实例 - 以及一个用于在 UI 中处理服务器错误的 JavaScript 函数。
在测试过程中,我了解到仅仅有正确的客户端回调是不够的。我无法让表单数据随回调一起传输。也就是说,输入控件的数据是存在的,但却是空的。通过浏览支持 ASP.NET Ajax 基础结构的 JavaScript,我了解到我们还需要调用 WebForm_InitCallback
函数,该函数将所有必需的输入数据填充到 __theFormPostData
变量中。
因此,所有必需的回调初始化都被包含在一个函数 LoanCalculation.InitRequest
中。
InitRequest: function(context)
{
__theFormPostData = '';
WebForm_InitCallback();
var divContents = document.getElementById(context+'_results');
var oldtable = document.getElementById(context+'_results_table');
if(oldtable!=null)
divContents.removeChild(oldtable);
divContents.innerHTML = "Requesting data...";
}
客户端的主要函数是 LoanCalculation.UpdateUI
。
UpdateUI: function(strData, context)
{
var divContents = document.getElementById(context+'_results');
var tbl = document.createElement('table');
tbl.className = 'LoanCalculationTable';
tbl.id = context+'_results_table';
var arData = eval(strData);
var cell;
var row;
var normalCellCount = 0;
for(var i=0;i<arData.length;i++)
{
row = tbl.insertRow(i);
if(i==0)
normalCellCount = arData[i].length;
for(var m=0;m<arData[i].length;m++)
{
cell = row.insertCell(m);
if(i==0)
cell.className = 'LoanCalculationTDFirst';
else
cell.className = 'LoanCalculationTD';
var textNode = document.createTextNode(arData[i][m]);
cell.appendChild(textNode);
}
if(m<normalCellCount)
{
cell.colSpan = (normalCellCount-m+1);
cell.className = 'LoanCalculationTDFirst';
}
}
divContents.innerHTML = "";
divContents.appendChild(tbl);
}
此函数评估接收到的字符串,该字符串构建 JavaScript 数组。该数组被解析,然后使用数据动态构建一个计划表。
另一件有趣的事情是,使用 ASP.NET Ajax,您实际上不需要在服务器端捕获所有异常。可以在 UI 中处理异常。此控件甚至在输入数据超出允许范围时显式引发异常。以下是用于向用户显示服务器错误的 JavaScript 函数:
CallbackError: function(error,context)
{
var divContents = document.getElementById(context+'_results');
if(divContents!=null)
divContents.innerHTML = ""+error+"";
}
关注点
最终的控件并不声称显示正确的结果 - 实际公式可能要复杂得多 - 但它提供了 Ajax 概念有多棒以及它与 ASP.NET 结合使用有多棒的示例。
历史
- 2007 年 8 月 16 日 - 发布原始版本