I just added a dynamic Contact Us page to my charity websites:
This is where a signed on administrator can add a new contact person to the page, without having to edit the HTML page and save/overwrite it back.
The secret is to store everything in a database, then output the results of a database query.
Here’s how it’s done (an overview, followed by detailed instructions below):
- Create database table “Contact”
- Import Contact class using an Object Relational Mapper (such as SubSonic).
- Wrap some ComponentModel tags around the ORM class in the business layer.
- Output the results of the SELECT in a GridView. (Code some input fields which are only visible to users with Admin role. )
- Render the image using a Handler.
- Capture the input fields and store them back into the database.
1. Create database table “Contact”
CREATE TABLE [dbo].[Contact](
[ContactID] [int] IDENTITY(1,1) NOT NULL,
[FullName] [nvarchar](100) NOT NULL,
[ImageType] [nvarchar](50) NOT NULL,
[JobTitle] [nvarchar](50) NOT NULL,
[PhoneNumber] [nvarchar](20) NULL,
[UpdatedBy] [nvarchar](20) NOT NULL,
[UpdatedOn] [smalldatetime] NOT NULL,
[Attachment] [image] NULL,
[EmailAddress] [nvarchar](100) NULL,
[FileName] [nvarchar](100) NULL,
CONSTRAINT [PK_Contact] PRIMARY KEY CLUSTERED
(
[ContactID] ASC
)
2. Import Contact class using an ORM
3. Wrap some ComponentModel tags around the ORM class
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Text
Imports DAL = Align.DataAccess
Imports columns = Align.DataAccess.Contact.Columns
Imports SubSonic
<System.ComponentModel.DataObject()>
Public Class Contact
Dim _qry As SqlQuery = New SqlQuery()
Dim _ret As DAL.ContactCollection = New DAL.ContactCollection()
<System.ComponentModel.DataObjectMethodAttribute(
System.ComponentModel.DataObjectMethodType.Select, True)>
Public Function GetData(ByVal ContactID As Integer) As DAL.ContactCollection
_qry.From(DAL.Contact.Schema)
If (ContactID > 0) Then _qry.Where(columns.ContactID).IsEqualTo(ContactID)
_qry.OrderAsc(columns.ContactID)
_ret.LoadAndCloseReader(_qry.ExecuteReader())
Return _ret
End Function
<System.ComponentModel.DataObjectMethodAttribute(
System.ComponentModel.DataObjectMethodType.Insert, True)>
Public Function Insert(
ByVal fullName As String,
ByVal imageType As String,
ByVal jobTitle As String,
ByVal phoneNumber As String,
ByVal emailAddress As String,
ByVal attachment As Stream,
ByVal userName As String,
ByVal fileName As String) As Boolean
Dim dr As DAL.Contact = New DAL.Contact()
dr.FullName = fullName
dr.ImageType = imageType
dr.JobTitle = jobTitle
dr.PhoneNumber = phoneNumber
dr.EmailAddress = emailAddress
dr.UpdatedBy = userName
dr.UpdatedOn = DateTime.Now
If (Not attachment Is Nothing) Then
Dim docLength As Int32 = attachment.Length
Dim docBuffer(docLength) As Byte
attachment.Read(docBuffer, 0, docLength)
dr.Attachment = docBuffer
dr.FileName = fileName
End If
Try
dr.Save(userName)
Return True
Catch ex As Exception
Throw New ApplicationException("Unable to save new Contact", ex)
End Try
End Function
<System.ComponentModel.DataObjectMethod(
System.ComponentModel.DataObjectMethodType.Delete, True)>
Public Function Delete(ByVal contactID As Integer)
Dim delQuery As DeleteQuery = New DeleteQuery(DAL.Contact.Schema)
delQuery.WHERE(columns.ContactID, contactID)
Try
delQuery.Execute()
Return True
Catch ex As Exception
Throw New ApplicationException("Unable to delete Contact", ex)
End Try
End Function
End Class
4. Output the results of the SELECT in a GridView
<%@ Page Title="Contact Us" MasterPageFile="~/site.master" CodeFile="~/Community/contact_us.aspx.vb"
Inherits="Community.contact_us" %>
<asp:Content ContentPlaceHolderID="HeaderContentPlaceHolder" runat="server">
Contact Us
</asp:Content>
<asp:Content ID="Content1" ContentPlaceHolderID="WorkSpaceContentPlaceHolder" runat="server">
<p>
For further information regarding Align Church, please contact us at the following
numbers.</p>
<asp:HiddenField ID="UserName_HiddenField" runat="server" />
<asp:Label ID="Err_Label" runat="server" ForeColor="Red"></asp:Label>
<asp:GridView ID="GridView1" BorderWidth="0px" CellPadding="0" Style="border-collapse: collapse;"
Width="100%" runat="server" AutoGenerateColumns="False" DataSourceID="Contact_Logic"
DataKeyNames="ContactID" ShowHeader="False" EnableModelValidation="True">
<HeaderStyle CssClass="style1" />
<RowStyle CssClass="style2" />
<AlternatingRowStyle CssClass="style3" />
<Columns>
<asp:ImageField DataImageUrlField="ContactID" DataImageUrlFormatString="GetDbImage.ashx?Id={0}" ControlStyle-Width="100px" />
<asp:TemplateField>
<ItemTemplate>
<table>
<tr>
<td class="style1">
Name
</td>
<td>
<asp:Label ID="Label3" runat="server" Text='<%# Eval("FullName") %>' />
</td>
</tr>
<tr>
<td class="style1">
Title
</td>
<td>
<asp:Label ID="Label5" runat="server" Text='<%# Eval("JobTitle") %>' />
</td>
</tr>
<tr>
<td class="style1">
Phone
</td>
<td>
<asp:Label ID="Label7" runat="server" Text='<%# Eval("PhoneNumber") %>' />
</td>
</tr>
<tr>
<td class="style1">
</td>
<td>
<asp:HyperLink ID="Label9" runat="server" Text='<%# Eval("EmailAddress") %>' NavigateUrl='<%#Eval("EmailAddress","mailto:{0}") %>' />
</td>
</tr>
</table>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ShowDeleteButton="true" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="Contact_Logic" runat="server" TypeName="Align.Business.Contact"
SelectMethod="GetData" DeleteMethod="Delete" InsertMethod="Insert">
<DeleteParameters>
<asp:Parameter Name="contactID" Type="Int32" />
</DeleteParameters>
<InsertParameters>
<asp:ControlParameter Name="fullName" Type="String" ControlID="FullName_TextBox"
PropertyName="Text" />
<asp:Parameter Name="attachment" Type="Object" />
<asp:Parameter Name="imageType" Type="String" />
<asp:Parameter Name="fileName" Type="String" />
<asp:ControlParameter Name="jobTitle" Type="String" ControlID="JobTitle_TextBox"
PropertyName="Text" />
<asp:ControlParameter Name="phoneNumber" Type="String" ControlID="PhoneNumber_TextBox"
PropertyName="Text" />
<asp:ControlParameter Name="emailAddress" Type="String" ControlID="EmailAddress_TextBox"
PropertyName="Text" />
<asp:ControlParameter Name="userName" Type="String" ControlID="UserName_HiddenField"
PropertyName="Value" />
</InsertParameters>
<SelectParameters>
<asp:Parameter Name="ContactID" Type="Int32" DefaultValue="0" />
</SelectParameters>
</asp:ObjectDataSource>
<br />
<asp:Table ID="insert_table" runat="server" Width="100%">
<asp:TableHeaderRow CssClass="style1">
<asp:TableHeaderCell>Photo</asp:TableHeaderCell>
<asp:TableHeaderCell>Full Name</asp:TableHeaderCell>
<asp:TableHeaderCell>Job Title</asp:TableHeaderCell>
<asp:TableHeaderCell>Phone Number</asp:TableHeaderCell>
<asp:TableHeaderCell>Email Address</asp:TableHeaderCell>
</asp:TableHeaderRow>
<asp:TableRow CssClass="style2">
<asp:TableCell>
<asp:FileUpload ID="FileUpload1" runat="server" />
</asp:TableCell>
<asp:TableCell>
<asp:TextBox ID="FullName_TextBox" runat="server" /></asp:TableCell><asp:TableCell>
<asp:TextBox ID="JobTitle_TextBox" runat="server" /></asp:TableCell><asp:TableCell>
<asp:TextBox ID="PhoneNumber_TextBox" runat="server" /></asp:TableCell><asp:TableCell>
<asp:TextBox ID="EmailAddress_TextBox" runat="server" /></asp:TableCell></asp:TableRow></asp:Table><asp:LinkButton ID="Insert_Button" Text="Insert" CommandName="Insert" runat="server">
</asp:LinkButton><br />
<table>
<tr>
<td valign="top">
<b>Address</b> </td><td>
<p>
Taita Community Hall<br />
22 Taine Street<br />
Taita<br />
Lower Hutt</p><hr />
</td>
</tr>
<tr>
<td valign="top">
<b>Map</b> </td><td>
<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0"
marginwidth="0" src="http://maps.google.co.nz/maps?q=Taita+Community+Hall&hl=en&cd=1&ei=yZG2S6_iCp2uiwPXyMGYBw&sig2=ii97zdnzh-Ye38TgUgVLiw&ie=UTF8&view=map&cid=10505385825416012616&ved=0CBoQpQY&hq=Taita+Community+Hall&hnear=&ll=-41.179429,174.958979&spn=0.006295,0.006295&iwloc=A&layer=c&cbll=-41.179591,174.958736&panoid=cBJq7GpBqDsMcOoNOA7sfw&cbp=12,31.86,,0,5.53&source=embed&output=svembed">
</iframe>
<br />
<small><a href="http://maps.google.co.nz/maps?q=Taita+Community+Hall&hl=en&cd=1&ei=yZG2S6_iCp2uiwPXyMGYBw&sig2=ii97zdnzh-Ye38TgUgVLiw&ie=UTF8&view=map&cid=10505385825416012616&ved=0CBoQpQY&hq=Taita+Community+Hall&hnear=&ll=-41.179429,174.958979&spn=0.006295,0.006295&iwloc=A&layer=c&cbll=-41.179591,174.958736&panoid=cBJq7GpBqDsMcOoNOA7sfw&cbp=12,31.86,,0,5.53&source=embed"
style="color: #0000FF; text-align: left">View Larger Map</a></small> <hr />
</td>
</tr>
<tr>
<td valign="top">
<b>Bank Account</b> </td><td>
<p>
If you have prayefully considered and decide to make Align Church your spiritual
home, or if you earnestly desire to bless the ministry of Align Church to the Taita
community, then you might want to contribute an offering to this ministry.</p><p>
Align Church is a registered charity with the New Zealand Charities Commission.
Your donations are tax-deductible. </p><p>
Our bank account number (for Internet Banking and/or Direct Debits) is: </p><p>
ALIGN CHURCH TRUST 38-9010-0431534-00 </p><blockquote>
<strong>But just as you excel in everything - in faith, in speech, in knowledge, in
complete earnestness and in your love for us - see that you also excel in the grace
of giving.</strong></blockquote><blockquote>
<em>2 Corinthians 8:7 </em></blockquote><p>
Please clearly identify yourself, so we can send a tax receipt at year end.</p><hr />
</td>
</tr>
</table>
</asp:Content>
<asp:Content ID="Content2" runat="server" ContentPlaceHolderID="head">
</asp:Content>
5. Render the image using a Handler
<%@ WebHandler Language="VB" Class="GetDbImage" %>
Imports System
Imports System.Web
Imports DAL = Align.DataAccess
Public Class GetDbImage : Implements IHttpHandler
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Response.Clear()
If Not context.Request.QueryString("ID") Is Nothing Then
Dim theContact As DAL.Contact = DAL.Contact.FetchByID(context.Request.QueryString("ID"))
context.Response.ContentType = theContact.ImageType
context.Response.BinaryWrite(theContact.Attachment)
Else
context.Response.ContentType = "text/plain"
context.Response.Write("No image")
End If
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
6. Capture the input fields and store them back into the database
Imports Align.Business
Imports System.Security.Principal
Imports System.IO
Imports System.Data.SqlClient
Imports System.Xml.Linq
Namespace Community
Public Class contact_us
Inherits Page
Private p As IPrincipal = HttpContext.Current.User
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Me.IsPostBack Then Exit Sub
If p.Identity.IsAuthenticated Then UserName_HiddenField.Value = p.Identity.Name
If p.IsInRole("Administrator") Then
insert_table.Visible = True
Insert_Button.Visible = True
Else
insert_table.Visible = False
Insert_Button.Visible = False
End If
End Sub
Protected Sub Contact_Logic_Inserted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ObjectDataSourceStatusEventArgs) Handles Contact_Logic.Inserted
If Not e.Exception Is Nothing Then
Err_Label.Text = e.Exception.Message
End If
End Sub
Protected Sub Insert_Button_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Insert_Button.Click
Contact_Logic.Insert()
End Sub
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
Dim theRow As GridViewRow = e.Row
If theRow.RowType = DataControlRowType.Header Then Exit Sub
Dim theCell As DataControlFieldCell = theRow.Cells(2)
For Each ctl As Control In theCell.Controls
If TypeOf ctl Is LinkButton Then
If p.IsInRole("Administrator") Then
ctl.Visible = True
Else
ctl.Visible = False
End If
End If
Next
End Sub
Protected Sub Contact_Logic_Inserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ObjectDataSourceMethodEventArgs) Handles Contact_Logic.Inserting
Dim iod As IOrderedDictionary = e.InputParameters
iod("attachment") = FileUpload1.PostedFile.InputStream
iod("imageType") = FileUpload1.PostedFile.ContentType
iod("fileName") = FileUpload1.FileName
End Sub
End Class
End Namespace