Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Convert Currency Values with a Custom Control

4.57/5 (6 votes)
8 Nov 20067 min read 1   534  
This article describes the details for constructing a custom ASP.NET 2.0 composite control used to convert one form of currency into another.

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).

Image 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:

Image 2

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.

VB
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.

VB
#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:

VB
#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.

VB
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:

VB
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.

VB
Protected Overrides Sub CreateChildControls()

    ' create the dropdown list used to display
    ' the from currency types
    ddlFromCurrency = New DropDownList
    ddlFromCurrency.ID = "ddlFromCurrency"
    'populates DDL with currency types
    LoadDropDownList(ddlFromCurrency)
    Me.Controls.Add(ddlFromCurrency)

    ' create the dropdown list used to display
    ' the to currency types
    ddlToCurrency = New DropDownList
    ddlToCurrency.ID = "ddlToCurrency"
    'populates DDL with currency types
    LoadDropDownList(ddlToCurrency)
    Me.Controls.Add(ddlToCurrency)

    ' create the textbox used to display
    ' the exchange rate
    txtExchangeRate = New TextBox
    txtExchangeRate.ID = "txtExchangeRate"
    txtExchangeRate.Enabled = False
    'display result value if any
    txtExchangeRate.Text = Me.mCurrentProps.mResult
    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 FromCurrency properties are actually set to read the value rather than the index or text contained in each drop down list.

VB
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.

VB
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.

VB
#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.

VB
#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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here