ARTICLE

Convert Currency Values with a Custom Control

Posted by Scott Lysle Articles | ASP.NET using VB.NET November 06, 2006
This article describes the details for constructing a custom ASP.NET 2.0 composite control used to convert one form of currency into another. The control consumes a public web service in order to calculate the exchange rate and uses the exchange rate returned from the web service to calculate the value of the exchanged currency.
Download Files:
 
Reader Level:

Introduction:

This article describes the details for constructing a custom ASP.NET 2.0 composite control used to convert one form of currency into another. The control consumes a public web service in order to calculate the exchange rate and uses the exchange rate returned from the web service to calculate the value of the exchanged currency.

The operation of the control is simple enough, the user keys in the amount of money to be exchanged, then, using drop down lists, sets the currency type to exchange from and exchange to; once these three values are set, the user may click on the submit button at the bottom of the control. On submit the control will evoke the web service, passing it the two currency formats; the web service then returns the exchange rate. The control then uses the exchange rate to calculate the value of the currency once converted to the new currency type. This information is then all displayed to the end user.

As a composite control, it may be dropped onto to any web page and used to provide that functionality to the page with no additional coding required.

The demonstration control library contains only the single control; the control itself maintains state through the use of ASP.NET 2.0 control state. The rendering of the control was kept simple. The attached files also include a sample website that is merely used as a container for the demonstration control.

An example of the control in use on a web page is provided in the following figure (figure 1).

Figure 1:  Currency Conversion Custom Control in Use

Getting Started:

The files included with this project include a web control library project and a demonstration web site. In order to get started, open the included zip file and install the two projects onto your file system. Open IIS and create a virtual directory for the web application. Open the solution into Visual 2005 and make any changes necessary to bring both projects into the solution. Once properly configured, your solution explorer should show these projects, references, and files:

Figure 2:  Solution Explorer with Web App and Control Library Visible

In examining the solution, note that the "CurrencyConvertControl" control library contains only a single control and that control is called "MoneyChanger". This project also includes a web reference that points to the http://www.webservicex.net site; this public site provides and supports the free web service used to calculate the exchange rates between many different types of currency.

The web application contains only a single web page (default.aspx) and includes a reference to the "CurrencyConvertControl" dynamic link library.

The web application serves as a container used to test the custom control.

The Code:  MoneyChanger

The "MoneyChanger" custom composite control is constructed to retrieve the information from the web service upon initialization and to use that information to display the current exchange rate and to calculate the conversion of money following conversion from one currency type to the next. The control supports about 150 different currency types.

The web service accepts to arguments, the currency type to exchange from and the currency type to exchange to; in response to a request, the service will return a double that contains the exchange rate between the two currencies and that calculate is sensitive to the direction the currency is being converted (e.g., Euros to US dollars will not yield the same result as US dollars to Euros).

In examining the code, note that only the default imports are included in the class. The class itself inherits from the CompositeControl class.

Imports System.Collections.Generic

Imports System.ComponentModel

Imports System.Text

Imports System.Web

Imports System.Web.UI

Imports System.Web.UI.WebControls

 

<ToolboxData("<{0}:MoneyChanger runat=server></{0}:MoneyChanger>")> _

Public Class MoneyChanger

    Inherits CompositeControl

Following the class declaration, a region entitled "Declarations" is created and within that region are the declarations for all of the objects used within the control. The serializable structure is used to maintain control state; the structure contains the member variables used by the control. Aside from that, an event is declared for use in conjunction with the submit button, an instance of the serializable structure (CurrentProperties) is created, each of the control used is declared, and the web service is declared.

#Region "Declarations"

 

    Public Event Change(ByVal Sender As Object, ByVal E As EventArgs)

    Private mCurrentProps As New CurrentProperties

    Public ddlFromCurrency As DropDownList

    Public ddlToCurrency As DropDownList

    Public txtExchangeRate As TextBox

    Public txtAmountToExchange As TextBox

    Public txtExchangedAmount As TextBox

    Public btnSubmit As Button

    Private mXchange As net.webservicex.www.CurrencyConvertor

 

    <Serializable()> _

    Private Structure CurrentProperties

        Dim mFromCurr As Integer

        Dim mToCurr As Integer

        Dim mResult As Double

        Dim mAmountToExchange As Decimal

        Dim mExchangedAmount As Decimal

    End Structure 

#End Region

After the variable declarations, there is another region defined (Methods) and within that region is the code used to drive the control.

The code contained in the Methods region is as follows:

#Region "Methods"

 

    Private Sub MoneyChanger_Init(ByVal sender As Object, ByVal e As

    System.EventArgs) Handles Me.Init

 

        ' required to enable control state

        Page.RegisterRequiresControlState(Me)

 

    End Sub

The first subroutine used in the control is the initialization event handler; this handler is used to set the Page property used to allow the use of ASP.NET 2.0 control state. The next subroutine contained in the methods region is the button click event handler used to handle the submit button click. This subroutine connects to the web service and requests the exchange rate based upon the users supplied currency selections. The handler also performs the calculation needed to convert the currency amount based upon the exchange rate between the two currency types. Once the exchange rate is received and conversion calculated, the handler updates the information displayed to the user.

Private Sub btnSubmit_Click(ByVal Sender As Object, ByVal E As EventArgs)

 

    'update the to and from currency values from the drop down lists

    SetFromCurrency()

    SetToCurrency()

 

    'capture the amount to be exchanged into a property

    AmountToExchange = Convert.ToDecimal(txtAmountToExchange.Text)

 

    ' instance and call the web service to get the conversion rate

    mXchange = New net.webservicex.www.CurrencyConvertor

    Dim dblTemp As Double

    dblTemp = mXchange.ConversionRate(FromCurrency, ToCurrency)

    Result = dblTemp.ToString()

 

    'update the exchange rate textbox to show the returned change rate

    txtExchangeRate.Text = Result

    txtExchangeRate.Enabled = True

 

    'calculate the value of the money once converted to the new currency

    'type and then store it into a property

    ExchangedAmount = AmountToExchange * Result

 

    'convert the ExchangedAmount variable to the proper format

    'and display it in the control

    txtExchangedAmount.Text = ExchangedAmount.ToString("##.00")

    txtExchangedAmount.Enabled = True

 

    OnChange(EventArgs.Empty)

 

End Sub

The next three subroutines are short and simple:

Protected Sub OnChange(ByVal E As EventArgs)

    RaiseEvent Change(Me, E)

End Sub 

 

Protected Overrides Function SaveControlState() As Object

    Return Me.mCurrentProps

End Function 

 

Protected Overrides Sub LoadControlState(ByVal savedState As Object)

    mCurrentProps = New CurrentProperties

    mCurrentProps = CType(savedState, CurrentProperties)

End Sub

OnChange is used to raise an event; this is part of the code related to processing the submit button click event. The other two subroutines are used to save and load control state between postbacks.

Next up is the overridden version of the CreateChildControls subroutine; in this subroutine, all of the controls are instanced, populated, and added to the control. The comments describe each section of the subroutine.

Protected Overrides Sub CreateChildControls()

 

    ' create the dropdown list used to display

    ' the from currency types

    ddlFromCurrency = New DropDownList

    ddlFromCurrency.ID = "ddlFromCurrency"

    LoadDropDownList(ddlFromCurrency)   'populates DDL with currency types

    Me.Controls.Add(ddlFromCurrency)

 

    ' create the dropdown list used to display

    ' the to currency types

    ddlToCurrency = New DropDownList

    ddlToCurrency.ID = "ddlToCurrency"

    LoadDropDownList(ddlToCurrency) 'populates DDL with currency types

    Me.Controls.Add(ddlToCurrency)

 

    ' create the textbox used to display

    ' the exchange rate

    txtExchangeRate = New TextBox

    txtExchangeRate.ID = "txtExchangeRate"

    txtExchangeRate.Enabled = False

    txtExchangeRate.Text = Me.mCurrentProps.mResult 'display result value if any

    Me.Controls.Add(txtExchangeRate)

 

    ' create the textbox used to capture and display

    ' the number of units of one type of currency

    ' to convert into another type of currency.

    ' Defaults to enabled = false since it will

    ' not contain any data and the user won't manually

    ' enter this calculated value

    txtAmountToExchange = New TextBox

    txtAmountToExchange.ID = "txtAmountToExchange"

    txtAmountToExchange.Text = Me.mCurrentProps.mAmountToExchange

    Me.Controls.Add(txtAmountToExchange)

 

    ' create the textbox used to display the exchange

    ' rate calculated and returned by the web service

    txtExchangedAmount = New TextBox

    txtExchangedAmount.ID = "txtExchangedAmount"

    txtExchangedAmount.Enabled = False

    txtExchangedAmount.Text = Me.mCurrentProps.mExchangedAmount

    Me.Controls.Add(txtExchangedAmount)

 

    ' creats the submit button and assigns it a handler

    btnSubmit = New Button

    btnSubmit.Text = "Submit"

    AddHandler btnSubmit.Click, AddressOf btnSubmit_Click

    Me.Controls.Add(btnSubmit)

 

End Sub

Next up is the subroutine used to set the ToCurrency and FromCurrency properties used to the user selected values shown in each drop down list. These are properties used internally to the control and represent the to and from currency arguments passed to the web service. Due to some issues with the enumeration used by the web service to represent the currency types, it was necessary to populate each drop down list item with a value representing the enumeration value as an integer. The To and From Currency properties are actually set to read the value rather than the index or text contained in each drop down list. 

Private Sub SetFromCurrency()

    FromCurrency = ddlFromCurrency.SelectedValue

End Sub

 

Private Sub SetToCurrency()

    ToCurrency = ddlToCurrency.SelectedValue

End Sub

The next subroutine is used to populate the drop down lists used to display the to and from currency types; there are about 150 different types so I will not show the whole subroutine since it is largely repetitive. The subroutine accepts the drop down list control as an argument and clears and populates the drop down list whenever this subroutine is called.

Private Sub LoadDropDownList(ByVal ddl As DropDownList)

 

    ddl.Items.Clear()

 

    ddl.Items.Add("AED-UAE Dirham")

    ddl.Items(0).Value = 139

    ddl.Items.Add("AFA-Afghanistan Afghani")

    ddl.Items(1).Value = 0

    ddl.Items.Add("ALL-Albanian Lek")

    ddl.Items(2).Value = 1...

The next region defined in the code is called "Properties"; this section contains the properties used by the control. In this case, all of the properties are declared as private since all are only used internally by the control; this prevents the properties from being displayed in the IDE at design time. If you wanted these to appear in the property editor, you would need to convert them to public properties and apply the appropriate attributes (category, browsable, descriptions, etc.) to provide adequate design time support. Note that the call to EnsureChildControls and to SaveControlState are included in each property. Both calls are made to keep the controls update to date within the control and to maintain control state in keeping with changes made to the properties.

#Region "Properties"

 

    Private Property Result() As Double

        Get

            EnsureChildControls()

            Return mCurrentProps.mResult

        End Get

        Set(ByVal value As Double)

            EnsureChildControls()

            mCurrentProps.mResult = value

            SaveControlState()

        End Set

    End Property

 

    Private Property FromCurrency() As Integer

        Get

            EnsureChildControls()

            Return mCurrentProps.mFromCurr

        End Get

        Set(ByVal value As Integer)

            EnsureChildControls()

            mCurrentProps.mFromCurr = value

            SaveControlState()

        End Set

    End Property 

 

    Private Property ToCurrency() As Integer

        Get

            EnsureChildControls()

            Return mCurrentProps.mToCurr

        End Get

        Set(ByVal value As Integer)

            EnsureChildControls()

            mCurrentProps.mToCurr = value

            SaveControlState()

        End Set

    End Property 

 

    Private Property AmountToExchange() As Decimal

        Get

            EnsureChildControls()

            Return mCurrentProps.mAmountToExchange

        End Get

        Set(ByVal value As Decimal)

            EnsureChildControls()

            mCurrentProps.mAmountToExchange = value

            SaveControlState()

        End Set

    End Property 

 

    Private Property ExchangedAmount() As Decimal

        Get

            EnsureChildControls()

            Return mCurrentProps.mExchangedAmount

        End Get

        Set(ByVal value As Decimal)

            EnsureChildControls()

            mCurrentProps.mExchangedAmount = value

            SaveControlState()

        End Set

    End Property 

#End Region

The code used to render the control is pretty simple; the HtmlTextWriter is used to define a table and set up its characteristics (cell padding in this example), each row of the table contains two cells, a label and its associated control are placed into each of those two cells. Once all of the data has been written into the table, the ending tag is rendered and the control is complete. Naturally, you can change the configuration of the table or remove some of the data returned from the web service by making changes in the definition of the HTML as defined through the HtmlTextWriter. The RenderContents subroutine is overridden and the HTML is formatted within this subroutine through the use of the HtmlTextWriter. 

#Region "Rendering"

 

    Protected Overrides Sub RenderContents(ByVal output As HtmlTextWriter)

 

        Try

            output.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "3")

            output.RenderBeginTag(HtmlTextWriterTag.Table)

 

            ' Amount to Exchange

            output.RenderBeginTag(HtmlTextWriterTag.Tr)

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddAttribute(HtmlTextWriterAttribute.For, txtAmountToExchange.ClientID)

            output.RenderBeginTag(HtmlTextWriterTag.Label)

            output.Write("Amount to Exchange: ")

            output.RenderEndTag()

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, Me.Font.Name)

            output.AddAttribute(HtmlTextWriterAttribute.Size, Me.Font.Size.ToString())

            txtAmountToExchange.RenderControl(output)

            output.RenderEndTag()

            output.RenderEndTag()

            output.RenderEndTag()

 

            ' from currency

            output.RenderBeginTag(HtmlTextWriterTag.Tr)

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddAttribute(HtmlTextWriterAttribute.For, Me.ddlFromCurrency.ClientID)

            output.RenderBeginTag(HtmlTextWriterTag.Label)

            output.Write("Convert from this currency: ")

            output.RenderEndTag()

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, Me.Font.Name)

            output.AddAttribute(HtmlTextWriterAttribute.Size, Me.Font.Size.ToString())

            ddlFromCurrency.RenderControl(output)

            output.RenderEndTag()

            output.RenderEndTag()

            output.RenderEndTag()

 

            ' to currency

            output.RenderBeginTag(HtmlTextWriterTag.Tr)

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddAttribute(HtmlTextWriterAttribute.For, Me.ddlToCurrency.ClientID)

            output.RenderBeginTag(HtmlTextWriterTag.Label)

            output.Write("Convert to this currency: ")

            output.RenderEndTag()

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, Me.Font.Name)

            output.AddAttribute(HtmlTextWriterAttribute.Size, Me.Font.Size.ToString())

            ddlToCurrency.RenderControl(output)

            output.RenderEndTag()

            output.RenderEndTag()

            output.RenderEndTag()

 

            ' exchange rate

            output.RenderBeginTag(HtmlTextWriterTag.Tr)

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddAttribute(HtmlTextWriterAttribute.For, Me.txtExchangeRate.ClientID)

            output.RenderBeginTag(HtmlTextWriterTag.Label)

            output.Write("Exchange Rate: ")

            output.RenderEndTag()

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            txtExchangeRate.Text = mCurrentProps.mResult

            output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, Me.Font.Name)

            output.AddAttribute(HtmlTextWriterAttribute.Size, Me.Font.Size.ToString())

            txtExchangeRate.RenderControl(output)

            output.RenderEndTag()

            output.RenderEndTag()

            output.RenderEndTag()

 

            ' Exchanged Amount

            output.RenderBeginTag(HtmlTextWriterTag.Tr)

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddAttribute(HtmlTextWriterAttribute.For, txtExchangedAmount.ClientID)

            output.RenderBeginTag(HtmlTextWriterTag.Label)

            output.Write("Amount After Exchange: ")

            output.RenderEndTag()

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, Me.Font.Name)

            output.AddAttribute(HtmlTextWriterAttribute.Size, Me.Font.Size.ToString())

            txtExchangedAmount.RenderControl(output)

            output.RenderEndTag()

            output.RenderEndTag()

            output.RenderEndTag()

 

            ' submit button

            output.RenderBeginTag(HtmlTextWriterTag.Tr)

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddAttribute(HtmlTextWriterAttribute.For, Me.btnSubmit.ClientID)

            output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, Me.Font.Name)

            output.AddAttribute(HtmlTextWriterAttribute.Size, Me.Font.Size.ToString())

            output.RenderBeginTag(HtmlTextWriterTag.Label)

            output.Write("Retrieve Exchange Rate: ")

            output.RenderEndTag()

            output.RenderBeginTag(HtmlTextWriterTag.Td)

            output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, Me.Font.Name)

            output.AddAttribute(HtmlTextWriterAttribute.Size, Me.Font.Size.ToString())

            btnSubmit.RenderControl(output)

            output.RenderEndTag()

            output.RenderEndTag()

            output.RenderEndTag()

 

            output.RenderEndTag()

 

        Catch

 

            output.Write("Money Changer Custom Control")

 

        End Try

 

    End Sub 

#End Region

The Code:  The Demo Site's Default Page

The default.aspx page contained within the demo site serves only a test container for the control. The page contains only a line of text used to describe the page and the control itself. Displaying the default.aspx page in a browser will enable testing of the control.

Summary

This project was intended to describe a useful, easy to build custom composite control. While this demonstration was limited to describing the Money Changer custom composite control, the same approach applied herein would work with a variety of other custom composite controls. It does provide an example of consuming a web service within a custom control and that approach could be applied to displaying information from any web service. The web service consumed in this demonstration is not under my control and I can predict the longevity of the service.

Login to add your contents and source code to this article
share this article :
post comment
 
Become a Sponsor
PREMIUM SPONSORS
  • ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
    The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
Become a Sponsor