Jeremy Wadsworth
My Contribution to the ASP.NET Community


Welcome   
Welcome to my personal website. Here you will find blog posts related to web development as well as personal related interests. If you're here for the source code to my Personal Web Site Kit, please register and you'll receive an email when your account has been approved.


Latest Blog Entries

 Thursday, August 28, 2008


Compiler Error Message: BC30560: 'Login_ascx' is ambiguous in the namespace 'ASP'    

I've been getting this error intermittently for a while now and finally got tired of seeing it, so I started looking for causes and solutions. The exact error I was getting is shown below. Note that it could appear with the same error 'BC30560', but have a different class name and different namespace.

Compiler Error Message: BC30560: 'Login_ascx' is ambiguous in the namespace 'ASP'

I couldn't really find a clear answer as it seems it can be caused by different scenarios, some of which may be a result of a bug in the framework. In my case it was a simple fix, although I don't know why this fixed it.

I had a page named Login.aspx and a User Control that resided on that page named Login.ascx. Why did I do it this way? Because I used the Login.aspx page as the primary login page, but there were other scenarios where I wanted to show a login without redirecting to the login page. So I created a User Control that I could put anywhere I wanted.

It seems as though there is a bug in the asp.net framework since my page and my control have different file extensions and different class names. Yet as soon as I changed my User Control to be named LoginCtrl.ascx, the error stopped appearing.



jeremy at 3:36 PM | (61) Comments | Add a comment | Permalink



 Thursday, August 21, 2008


Unable to start debugging on the web server. Debugging failed because integrated windows authentication is not enabled.    
I've been developing using Visual Web Developer 2008 and Visual Studio 2008 exclusivily for the last 6 months. I've also been using Windows Vista for the same amount of time. I needed to work with a third party control that apparently could only be designed in Visual Studio 2005. So I loaded the project into VS 2005 and hit run, and received the following error.

"Unable to start debugging on the web server. Debugging failed because integrated Windows authentication is not enabled."

This was my first time to run VS 2005 in Windows Vista. After fittling around with IIS7 settings for a while, I found that this issue is easily fixed with the following Microsoft Hotfix.

http://support.microsoft.com/kb/937523

Once I ran this hotfix, the error was gone and I could debug as expected.


jeremy at 10:00 PM | (18) Comments | Add a comment | Permalink



 Saturday, August 02, 2008


Unable to open the physical file \App_Data\DevResource.mdf. Operating system error 5: 5(Access is denied.).    
Here is the exact error I received.

Unable to open the physical file "C:\Develop\WebSites\Developer Resource\App_Data\DevResource.mdf". Operating system error 5: "5(Access is denied.)". An attempt to attach an auto-named database for file C:\Develop\WebSites\Developer Resource\App_Data\DevResource.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.

After a little Googling something I read pointed me in the right direction. I imagine there are many scenarios that could trigger this error. In my case, I had restored a backup file into the App_Data folder of my website, setup the web.config, and tried to run. The issue was that when I restored the database backup file, the MDF file created in my App_Data folder, didn't have any file permissions on it. So I gave asp.net account rights and everything worked fine.


jeremy at 9:35 PM | (10) Comments | Add a comment | Permalink



 Wednesday, November 14, 2007


Check if an email address is from a valid domain    
Dim strEmail As String = "jimbale@apnzzz.com"
strEmail = strEmail.Substring((strEmail.LastIndexOf("@") + 1), strEmail.Length - (strEmail.LastIndexOf("@") + 1))
Try
Dim strTest As String = System.Net.Dns.GetHostEntry(strEmail).HostName
Catch exNoHostException As System.Net.Sockets.SocketException
 'Handle here when the email has an invalid domain
 Dim stT As String = ""
Catch ex As Exception
 'Handle unexpected errors here
 Dim stT As String = ""
End Try


jeremy at 10:44 AM | (15) Comments | Add a comment | Permalink



 Thursday, October 18, 2007


Automatically unlock a user after a specified time limit    
Using the ASP.NET 2.0 membership service framework, I discovered that when a user's account is locked out as a result of too many invalid login attempts, it stays locked out. I guess I expected it to unlock after 10 or 15 minutes since this is what I've seen on most sites.

I wrote some code to handle this. It's kind of scratchy but it works. You can put this in the Page_PreRender and only run it on postback.

Dim ctrlLogin As System.Web.UI.WebControls.Login
ctrlLogin = CType(LoginArea.FindControl("Login1"), System.Web.UI.WebControls.Login)
txtUserName = CType(ctrlLogin.FindControl("UserName"), TextBox)
Dim theUser As MembershipUser = Membership.GetUser(txtUserName.Text.Trim, False)
If IsNothing(theUser) = False Then
 If theUser.IsLockedOut = True Then
  Dim theUser As MembershipUser = Membership.GetUser(txtUserName.Text.Trim, False)
  Dim ts As TimeSpan = Now.Subtract(theUser.LastLockoutDate)
  If Math.Round(ts.TotalMinutes) > 10 Then
   theUser.UnlockUser()
  Else
   ctrlLogin.Enabled = False
   failureText.Text = "Your account has been locked out for 10 minutes, because of too many invalid login attempts."
  End If
 End If
End If


jeremy at 7:59 PM | (10) Comments | Add a comment | Permalink



 Friday, September 14, 2007


DataBinding: 'System.Data.DataRowView' does not contain a property with the name 'PageURL'.    
In my case I am binding to the Telerik r.a.d.Grid using a hierarchal view. So I create a Dataset and stick a parent and child DataTable in it. I then create a DataRelation for the tables and bind it to the grid. The part I missed that throws the System.Data.DataRowView... error, is I didn't assign the parent table name to the datamember property of the grid. If you're using the radGrid, you would assign the parent table name to the DataMember property of the MasterTableView.

If you're not using the Telerik radGrid, but you're trying to bind to a grid or list using a parent/child relationship, something similar to my scenario could be the source of your error.


jeremy at 9:00 PM | (6) Comments | Add a comment | Permalink



 Thursday, September 13, 2007


Error: Failed to generate a user instance of SQL Server due to a failure in starting the process for the user instance. The connection will be closed.    
This error has once again plagued me and consumed way too much of my time. I blogged on this error before when it was occurring in a different scenario; you can read the post here. The solution presented in my previous post did not work in this case.

I have several different websites and web applications using SQL Server Express in which I have the database in the App_Data folder. All of my sites ran fine locally except one. The one site was working fine one day and was giving me this error the next. I tried all the solutions I could find and nothing worked. I didn't reinstall SQL Express cause I wanted to solve the issue.

How did I fix it in this case? I closed Visual Web Developer and then renamed the root folder of the website in Windows Explorer. I then opened VWD and clicked on the old name of my site in the Recent Projects list. When asked to remove the link that was no longer valid, I said yes. I then chose File>Open Web Site and browsed to the renamed folder. When I ran the site this time, it was working again.


jeremy at 11:05 PM | (21) Comments | Add a comment | Permalink



 Wednesday, September 12, 2007


Multiple controls with the same ID were found. FindControl requires that controls have unique IDs.    
This error gets thrown and looks something like Multiple controls with the same ID 'myControl1' were found. FindControl requires that controls have unique IDs.

This error typically occurs when trying to dynamically add or remove controls during the initial load of a page or a postback. You might hit a button and instead of a postback, you get this error. If you're getting this error and you're trying to add or remove controls from the page dynamically, you are most likely adding/removing after something has already been added to viewstate.

The key here is to do your add/remove before things like binding of other controls. Try adding or removing the control in the Page_Init. It might take a little creativity in your code to get the sequence correct.


jeremy at 10:16 PM | (17) Comments | Add a comment | Permalink



 Thursday, September 06, 2007


Resolve an IP Address to a domain name    

While writing a visitor tracking system for site traffic statistics, I came across this useful bit of code for resolving an IP address to a domain name. System.Net.Dns.GetHostEntry("000.000.000.000").HostName will return the domain associated with the IP passed in.



jeremy at 11:06 PM | (2) Comments | Add a comment | Permalink



 Friday, August 17, 2007


Error: Failed to generate a user instance of SQL Server due to a failure in starting the process for the user instance.    

There is plenty of information out there on this error. It could occur for different reasons I suppose. My scenario was this.

I had SQL Server 2005 Express installed. I needed to install SQL Server 2005 Standard Edition. I installed Standard edition, but for some reason none of the tools were showing up. So I uninstalled both SQL Server 2005 editions and then reinstalled both, installing Standard edition first. I then tried to run my Personal Site Kit project, which uses SQL Express. That's when I received the error. Failed to generate a user instance of SQL Server due to a failure in starting the process for the user instance. The connection will be closed.

The first solution I came across seems to be the common solution for this issue. This is what worked for me.

  1. Delete the directory c:\Documents and Settings\username\Local Settings\Application Data\Microsoft\Microsoft SQL Server Data\SQLEXPRESS
  2. Then reboot your computer. That's it.


jeremy at 4:58 PM | (42) Comments | Add a comment | Permalink



 Thursday, May 10, 2007


Setting meta tags for content pages in ASP.NET 2.0    
I replied to a post in the forums regarding how to set meta tags for each content page in an app. If you set the meta tags in the master page, all your pages will have the same meta tags. One way to accomplish setting the meta tags for each content page is to use code like the following.

Dim metaTag As New HtmlMeta
Dim HeadTag As HtmlHead = CType(Page.Header, HtmlHead)
metaTag.Attributes.Add("name", "description")
metaTag.Attributes.Add("content", "your description goes here")
HeadTag.Controls.Add(metaTag)
metaTag = New HtmlMeta
metaTag.Attributes.Add("name", "keywords")
metaTag.Attributes.Add("content", "your keyword go here")
HeadTag.Controls.Add(metaTag)


This code could also be used to dynamically add meta tags to your pages. The tag values could be stored in a database, and then retrieved and plugged into the code.


jeremy at 4:41 PM | (9) Comments | Add a comment | Permalink



 Thursday, April 26, 2007


Invalid postback or callback argument    
This is a common error that frequently plagues web developers and is often hard to work around. I've come across it several times and fixed it using a variety of solutions that are usually specific to even a particular page being worked on.

Today I watched in horror as this error popped up over and over, on users screens at a training that was being given for a web application that I helped develop. I couldn't understand why since I couldn't produce the error on the live version of the application, which was using the same set of code. When I got home I reviewed the web.config and discovered that I left Debug set to True. I changed it to False, and could no longer get the Invalid Postback error to occur. That's a tough lesson to learn. In addition to the constant error popping up, the performance was very poor as a result of running in debug mode.

It's important to mention that the error was being triggered when a user would click a Menu link and something on the page was still loading.


jeremy at 8:03 PM | (6) Comments | Add a comment | Permalink



 Friday, April 20, 2007


Accessing nested server controls client-side in ASP.NET 2.0    
The other day I was designing a registration process using the ASP.NET 2.0 CreateUserWizard control. There's a lot of different types of information that I need from the user so I divided the process into 6 simple steps to make the registration process clean and easy.

The first step is a <asp:TemplateWizardStep>. Inside of this step is my EULA (End User License Agreement). I designed it so that the user needs to check a checkbox indicating that they agree, before they can proceed to the next step. Normally, I could have just validated on the post back using the CreateUserWizard1_NextButtonClick event, and then displayed a JavaScript alert using the ClientScript.RegisterStartupScript, if the checkbox wasn’t checked. However, I’m using the radAjaxPanel from Telerik so that my whole registration process uses Callbacks instead of postbacks.

I decided I’d go ahead and use JavaScript on the client-side, to evaluate the checkbox when the next button is clicked. In a normal scenario I’d use something like document.getElementById(‘<%= chkEULA.ClientID %>’) to get a reference to the checkbox. The problem I ran into is that my checkbox is nested down inside the CreateUserWizard control and so using chkEULA.ClientID wouldn’t work. With a  little playing around, here is how I was able to get a reference and the ability to evaluate the checkbox on the Next button’s OnClientClick event.

var ctrlEULA = document.getElementById('<%= CType(TemplateWizardStepEULA.ContentTemplateContainer.FindControl("chkEULA"), CheckBox).ClientID %>')

And for those whole need to see a little more code.

<script type="text/javascript"> 
 function IsAgreed()
 {
  var ctrlEULA = document.getElementById('<%= CType(TemplateWizardStepEULA.ContentTemplateContainer.FindControl("chkEULA"), CheckBox).ClientID %>')
  if (!ctrlEULA.checked)
  {
   alert('You must first agree to the End User License Agreement by checking the box.');
   return false;
  }
  else {
   return true;
  }
 }
</script>


And here is the end of my first wizard step.

<asp:TemplatedWizardStep ID="TemplateWizardStep1" runat="server" StepType="Start">
 <ContentTemplate>
  My EULA text goes in here.
  <asp:CheckBox ID="chkEULA" runat="server" Text=" By checking this box you are signifying that you have read, understand, and accept this End User License Agreement." />
</ContentTemplate>           <CustomNavigationTemplate>          <table width="100%" cellpadding="10" cellspacing="0" border="0">
   <tr>
    <td><hr style="padding-top: 0px; margin-top: 0px;" />
     <asp:ImageButton ID="StepCancelButton" runat="server" CommandName="Cancel" SkinID="button_cancel" />&nbsp;&nbsp;
     <asp:ImageButton ID="StepNextButton" runat="server" CommandName="MoveNext" OnClientClick="return IsAgreed();" ValidationGroup="CreateUserWizard1" ImageUrl="~/App_Themes/mytheme/Images/button-iagree.gif" /></td>      </tr>
  </table>
 </CustomNavigationTemplate>
</asp:TemplatedWizardStep>


jeremy at 5:34 PM | (2) Comments | Add a comment | Permalink



 Thursday, March 01, 2007


Be careful when using a Public Module in ASP.NET    
I recently came across a rather disturbing issue while using a Public Module in ASP.NET. I had created a Public Module like:

Public Module MyModule
     ‘Some code here
End Module


I was using the Public Module to build unique connection strings for users based on their login name. The idea here was that each user would have their own database and would be accessing their own data when they logged in. I had put the code in a Public Module for easy reuse, thinking that each user’s session would be using its own instance of the Module. When the user logged in, it would build the connection string for that user and store it in a variable. The next time they accessed the Module, it would see if the connection string had already been built.

What I discovered is that any Public Modules are actually application level not session level. This meant that if User A logged in and the connection string was build for User A’s database, and then User B logged in after words, it would change the stored connection string in the Public Module, and the next time User A executed an action that needed data from the database, it would try to use the database for User B. Go ahead and read it again if you need to.

Fortunately the way the code was written; this scenario just caused an error. However, it took me a bit to figure out what was going on. I can’t believe I didn’t know that a Public Module was application level after all my experience and all my studying for my MCP Cert. I’m still kicking myself.

I fixed the issue by using a session variable to cart around the connection string for each user and did away with using the Public Module. I can see there could be some good uses for the Public Module now that I know it works that way.


jeremy at 3:30 PM | (3) Comments | Add a comment | Permalink



 Saturday, February 24, 2007


Can’t sign out of website in ASP.NET 2.0 / Single Sign On    
This stupid issue has plagued me for a while now. I eventually figured out what the issue was related to, I just didn’t know how to fix it until recently. The issue I was running into was this:

A user types in “mydomain.com” into the address bar and then logs in, checking the “Remember Me” checkbox. The user comes back to the website on at a later date and is automatically logged in as they should be. Then they decide to logout but when they click the logout link at the top of the page, the page refreshes and they aren’t logged out.

I wasn’t sure what the issue was so I wrote a custom logout page that my Logout link directs the user to. The logout page just executes the following code.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 If User.Identity.IsAuthenticated = True Then
  Session.Abandon()
  FormsAuthentication.SignOut()
 End If
 Response.Redirect("~/Login.aspx")
End Sub


However, this created another issue. Sometimes the user would be directed to the Login page after the code was executed but would just see a blank login page. If they navigated back to the home page, they would still be logged in.

I discovered that if the user logged in when the address read http://mydomain.com/login.aspx, and then later tried to click logout when the address read http://www.mydomain.com/somepage.aspx, they are not logged out. So it appears that the forms authentication cookie is specific to whether www is present in the URL.

I was able to fix this issue by writing code to change the cookie that was being used to authenticate the user. However, I just found the correct way to fix this issue. If you do a lot of web development and frequently have to program around the forms security model, I highly recommend the following book. ASP.NET 2.0 Security, Membership, and Role Management (WROX) by Stefan Schackow.

After reading chapter 5 and the section “Passing Tickets across Applications”, the answer was clear. It’s really a Single Sign On or SSO issue. In the Forms section of the web.config I needed to specify the domain. Otherwise, when the cookie is issued it will use the domain that is showing in the address bar which may or may not contain the www depending on how the user typed it in. Here is the code.

<forms loginUrl="Login.aspx" protection="Validation" timeout="5000000" path="/" domain="mydomain.com" />

Adding the domain property to the Forms tag, causes the forms authentication ticket to be issued using the exact domain you specify. It will also use that domain setting when signing out and expiring the ticket. Using this setting will allow users to log in at http://mydomain.com and still be authenticated when transferring them to http://subdomain.mydomain.com.


jeremy at 11:16 AM | (7) Comments | Add a comment | Permalink



 Thursday, February 08, 2007


A potentially dangerous Request.Form value was detected from the client    

You might receive this error if your allowing users to enter text into a textbox, then saving the text to the database, and trying to display it on a page. This error might occur if characters or text deemed unsafe by the asp.net request validation feature, are entered by the user. You can easily solve this issue by html encoding input from the user.

So in your code, you would do something like this before saving the text to the database.

Dim strText As String = Server.HtmlEncode(MyTextBox.Text.Trim)
SaveToDB(strText)


When you want to display the saved text on a web page you would use something like the following.

Dim strText as String = Some code to retrieve the text from the database
MyLabel.Text = Server.HtmlDecode(strText)


This short blog post is meant to be a quick read for this issue. You can read a great article on this subject at http://www.asp.net/faq/requestvalidation.aspx



jeremy at 4:52 PM | (15) Comments | Add a comment | Permalink



 Sunday, January 21, 2007


Download content as Word Document or XML File    
I recently responded to a question in the ASP.NET Forums regarding how to allow users to click a download button that would then prompt the user to save a particular page as a MS Word document. I have worked on various projects where I’ve had to stream various types of content to be downloaded as files.

I have created a sample project that demonstrates one way of downloading a web page as a Word document or downloading XML output as an XML file. You can download the sample project here. In addition, you can run the live sample here.


jeremy at 3:41 PM | (0) Comments | Add a comment | Permalink



 Friday, December 29, 2006


The user account has been locked out    
I came across this error today in the user management page of one of my web applications. I have a grid that I’m filling with all the users in the system along with their information. In this grid I am also showing the passwords for each user. I know, not the best security. However, I am using SSL.

The error occurred when a user got locked out and then the administrator tried to go in and view the grid of users. When the code tried to retrieve the password for the locked out user, a MembershipPasswordException error was thrown. You can’t retrieve certain information for a user in ASP.NET 2.0 when that user has been locked. In the ASPNET_Membership table the column is IsLockedOut. When this column is set to 1 for a user in the table, you will not be able to retrieve the password.

A user gets locked out when they have too many failed login attempts and usually only get locked out for 10 minutes unless you’ve changed it to be a longer period.

In order to get around this error, I have to check if the user is locked out before trying to retrieve their password. If they are locked out I just call the UnlockUser method off of the membershipuser object. The following code illustrates this.

For Each user As MembershipUser In memberList
   If user.IsLockedOut = True Then user.UnlockUser()


jeremy at 3:57 PM | (10) Comments | Add a comment | Permalink



 Sunday, December 03, 2006


Handle Session Timeouts and Forms Authentication Timeouts in ASP.NET 2.0    

Recently I wrote about session timeout and forms authentication timeout issues. They’re really pretty straight forward when it comes to configuring them. However, problems arise when we attempt to set the forms authentication timeout to a long period of time so that users don’t have to log in every time they return to our site. In this case we tend to run into issues with users being logged in even after their session has expired.

It would be much simpler if we just set the forms authentication timeout to a time that was less than the session timeout. In this case, if the user was inactive for too long, they would be redirected to the log in page. Upon redirection to the login page you could clean up and end their session. However, if we want to allow the user to be automatically logged in on return visits, this isn’t a very good solution. In addition there are other unpleasant scenarios that can occur in this model. Take for instance the following example.

You have a user that logs into your web application and goes into edit mode on one of your webforms. When the user enters edit mode, you store a business class object in a session variable for use while they’re working with that form. The user then gets a phone call and begins a lengthy conversation about selling their house or something. While they are on the phone, the forms authentication ticket expires. The user gets off the phone and enters data into more of the fields on form and then hits save. Boom, the user gets redirected to the login page because their authentication ticket expired. They loose the data they had finished entering and aren’t very happy about it.

The solution I implemented to handle these scenarios more gracefully, is to automatically end the users session, log them out and send them to the login page when their session is about to expire.

This solution is specific to the use of a master page throughout your application. If you’re not using a master page, it would be possible to create a user control that you drop on every page to implement the same functionality. However, why not just use a master page.

In my Default.master.vb I have the following two variables declared at a module level.

Protected mintTimeout As Integer
Protected mstrLoginURL As String

Then in the Page_Init of the Default.master.vb I set the two variables.

Dim intRedirectTime As Integer = 2
mintTimeout = (Session.Timeout - intRedirectTime) * 60000
mstrLoginURL = ResolveUrl("~/endsession.aspx")

The variable intRedirectTime represents how many minutes prior to the session timeout that I want to force the redirect to the login page.

60000 represents 1minute in milliseconds. I’ll be using the window.setTimeout method so I need time in milliseconds. Every time there is a postback in the application the above code is run and sets the timeout variable to 2 minutes less than the session timeout setting. I also set the mstrLoginURL with a resolved URL for my endsession.aspx page.

Then on the Default.master just before the end body tag </body>, I put the following JavaScript section.

<script language="javascript">
 window.setTimeout("endSession();",<%=mintTimeout%>);
 function endSession()
 {
  alert("Your session has expired. You will be redirected to the login page.");
  url = '<%=mstrLoginURL %>';
  document.location=url;
 }
</script>

In the above javascript section the setTimeout method fires 2 minutes before the session is about to end. The endSession function is called which pops up an alert to notify the user that their session has ended. At this point the session is still active, but will be ended regardless once the Ok button is clicked on the alert dialog. In addition the user will be logged out using the FormsAuthentication.SignOut() method.

The page that the user is actually sent to is a blank page with the following code in the Page_Load. I have named the page endsession.aspx.

If User.Identity.IsAuthenticated = True Then
 FormsAuthentication.SignOut()
End If
Session.Abandon()
Response.Redirect("~/Login.aspx")

In the above code I check to see if the user is authenticated before trying to sign them out. I then call the Session.Abandon method and redirect them to the login page.

The solution shows what is possible with a little creativity for handling timeout issues in ASP.NET 2.0 web applications. Every application is different and may require unique solutions for handling issues that arise from the new security model in ASP.NET 2.0. I hope this article inspires ideas for others to solve the session issues they may face.

If you have any thoughts, ideas, or input on this subject, please tell me about it by leaving a comment.



jeremy at 10:42 PM | (57) Comments | Add a comment | Permalink



 Saturday, November 18, 2006


Dynamically add Validation Controls to a page in ASP.NET 2.0    

When developing web applications there are often times when I need to dynamically set or change properties of controls in a page. This is a concept that is probably not implemented as much as it should be. In fact, you can create procedures that will dynamically handle controls on any page.

You can download a working sample project here.

The example I’m going to use involves dynamically adding RequiredFieldValidator controls to the page for textbox fields that are required. In this scenario I need the textbox controls inside table cell <asp:TableCell ID="formCell" runat="server">. I also need the ValidationGroup property set on each textbox to ValidationGroup="Required". I’ll use this later so I know which textbox fields are required. There are of course better ways to do this using custom business objects, but I’ll do it this way to keep it simple.

I have the following html inside the form tag on a simple default.aspx page. Below my fields I have placed a ValidationSummary.

<asp:Table ID="Table1" runat="server">
 <asp:TableRow>
  <asp:TableCell ID="formCell" runat="server">
   <table cellpadding="3" cellspacing="0" border="0">
    <tr>
     <td align="right">Name: </td>
     <td>
      <asp:TextBox ID="Name" runat="server"
       ValidationGroup="Required"/></td>
    </tr>
    <tr>
     <td align="right">Company: </td>
     <td valign="top">
      <asp:TextBox ID="Company" runat="server"/></td>
    </tr>
    <tr>
     <td colspan="2">
      <asp:Button ID="btnSubmit"
       runat="server" Text="Submit" /></td>
    </tr>
   </table>
  </asp:TableCell>
 </asp:TableRow>
</asp:Table>
<asp:ValidationSummary id="ValidationSummary1"
 DisplayMode="BulletList"
 ShowSummary="true"
 HeaderText="Please check the following fields:"
 runat="server" />


Now I want to be able to dynamically add RequiredFieldValidators for controls that are in the Required ValidationGroup. In order to do this I’m going to create a public sub named SetValidators and pass in to it the table cell that all my controls reside in as well as the Form on the page.

I’ll use a reference to the table cell to loop through all the controls and I’ll use a reference to the form to add the validation controls. When I identify my required fields I’ll also change the backcolor to something other than white to identify that they are required.

Public Module PageControls
 Public Sub SetValidators(ByRef objCell As TableCell, ByRef objForm As HtmlForm)
  'loop through the controls and set validators based on the ValidationGroup
  For Each ctrl As Control In objCell.Controls
   Select Case True
    Case TypeOf ctrl Is TextBox
     Dim txtBox As TextBox = CType(ctrl, TextBox)
     With txtBox
      'Required Field Validator
      If .ValidationGroup.ToUpper = "REQUIRED" Then
       .BackColor = Drawing.Color.LightSalmon
       Dim reqValidator As New RequiredFieldValidator
       With reqValidator
        .ID = txtBox.ID & "ReqFieldValidator"
        .ControlToValidate = txtBox.UniqueID
        .ErrorMessage = "Missing required field!"
        .Text = ""
        .Display = ValidatorDisplay.None
       End With
       objForm.Controls.Add(reqValidator)
      Else
       .BackColor = Drawing.Color.Transparent
      End If
     End With
   End Select
  Next
 End Sub
End Module

Then in the code file for the default.aspx page, I’ll pass the table cell and the form object in the Page_PreRender.

Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
 SetValidators(formCell, form1)
End Sub


Using this technique and some creativity you can easily dynamically add all the validation for all the pages in your application. In complex scenarios you can expand the SetValidators procedure to handle adding all types of validation controls.


jeremy at 9:21 PM | (11) Comments | Add a comment | Permalink



 Friday, November 17, 2006


Using a SortedList with a DropDownList in ASP.NET 2.0    

I ran into a scenario the other day where I had a Hashtable that I filled with records from a Datatable that had sorted data. Then later in my page code I would fill an asp.net DropDownList using the Hashtable. However, I discovered that the sorted data that I stuck in the Hashtable was not filling the DropDownList in the same sorted order. In fact the order didn’t seem to make sense.

I started looking around for a different way to accomplish what I was doing. I came across the SortedList which is similar to the Hashtable. The SortedList stores items as key value pairs and automatically sorts the list by key. Well, that was almost what I needed. I needed it to sort by value.

Fortunately this was easily remedied by changing how I filled the SortedList. When I fill the list I swap the key and the value. Notice the example below:

The default use of the SortedList is like so: myList.Add(Key as Object, Value as Object)

Instead I add the value as the key and the key as the value.

Dim myList as SortedList
Dim strKey as String = “a key”
Dim strValue as String = “a value”
myList.Add(strValue, strKey)

Then I can just bind the SortedList to my DropDownList and specify that the Key column of the SortedList item is assigned to the DataTextField, and the Value column of the item is assigned to the DataValueField.

myDropDown.DataSource = objList
myDropDown.DataTextField = "Key"
myDropDown.DataValueField = "Value"
myDropDown.DataBind()

This gives me a sorted DropDownList. This of course is not ideal for every scenario. I mostly bind datatables to dropdownlists. However, in this one case, my application was set up differently where this type of implementation was ideal.



jeremy at 3:02 PM | (2) Comments | Add a comment | Permalink



 Monday, November 06, 2006


ASP.NET 2.0, sessionState timeout, forms timeout, and process recycling    
I recently encountered an issue in one of my ASP.NET 2.0 web applications where a user is logged in and authenticated, but their session times out and causes an exception. I started searching around and found a few different articles on this subject.

What is happening is that in ASP.NET 2.0 the sessionState timeout and the Forms Authentication timeout are separate. Previously I had set my session timeout to 30 minutes and my Forms Timeout set to a very large number. So the user’s session would end, yet they were still logged in. This would cause application errors due to business objects being stored as session variables. So I increased the sessionState timeout to 60 and lowered the Forms timeout to 50.

However, my trouble didn’t end here. My session was still ending at 30 minutes. What was happening is the process that my web application was running in would get recycled after being idle for 30 minutes. This is a performance feature in IIS 6.

If you go into IIS and right click on the Application Pool that your web application is using, and choose properties. Then click on the Performance tab. There is a check box for the Idle Timeout. If your application is getting enough use, this might not be an issue. Otherwise the Idle Timeout may need to be set to greater than or equal to the session timeout that you have chosen.

You can read a little more discussion on this subject at Scott Guthrie’s blog here.


jeremy at 8:24 PM | (19) Comments | Add a comment | Permalink



 Monday, October 23, 2006


Ultimate CAPTCHA Custom Server Control for ASP.NET 2.0 in C#    
After implementing the guestbook in my site about 3 months ago, I started getting spam entries in my guestbook every couple days or so. Then it increased to at least once a day and finally about a week ago, 2 or 3 every hour.

So over the weekend I spent some time looking for a CAPTCHA control or code that I could use to eliminate automated spam posting to my guestbook. I found only a few different solutions that were intended for developers using ASP.NET 2.0. I ended up using Peter Kellner's "Ultimate CAPTCHA Custom Server Control". I don't know if that is an official title or just what he called it. Either way, I call it golden. I haven't had a single spam entry since I implemented his control.

If you're having issues with spam posts to your blog comments or guestbook, or if you are getting automated registrations, I would recommend you take a look at Peter Kellner's CAPTCHA control at PeterKellner.net.


jeremy at 8:49 AM | (20) Comments | Add a comment | Permalink



 Saturday, October 21, 2006


Internet Explorer issue    
You know, it's a real pet peeve of mine when I have several Internet Explorer windows open and one of them stops responding. I then have to end task on the browser window that is not responding and guess what, all my browser windows close. That irritates me so much. I have encountered this problem many times when using the Ctrl+F to find text on a page. I think I'll download Internet Explorer 7 and check it out. I noticed it has been released.


jeremy at 11:00 AM | (3) Comments | Add a comment | Permalink



 Saturday, October 21, 2006


ASP.NET 2.0 Web Parts    
I was searching around for some information about ASP.NET 2.0 and came across an article about ASP.NET 2.0 Web Parts. Until now, I had somehow not heard of Web Parts. Web Parts is a set of controls and functionality to personalize the experience of users on your website. Here are a few good links to learn more about it.

http://msdn2.microsoft.com/en-us/library/hhy9ewf1.aspx
http://asp.net/getstarted/default.aspx?tabid=61
http://quickstarts.asp.net/QuickStartv20/aspnet/doc/webparts/default.aspx


jeremy at 12:35 AM | (3) Comments | Add a comment | Permalink



 Tuesday, October 03, 2006


Type ProfileCommon is not defined    
After writing in my blog about adding custom properties for an ASP.NET 2.0 membership user, I have received several hits on my site regarding the error “Type ProfileCommon is not defined” or “ProfileCommon not found”. The type of error means that the Profile or custom properties you’re intending to add for membership users, is not defined in your web.config. If you’re trying to add Company and PhoneNumber as custom properties of membership user, you will need to define them in the <profile> section in your web.config like the following:
  <profile>
     <properties>
        <add name="Company"/>
        <add name="PhoneNumber"/>
      </properties>
  </profile>

This declaration in the web.config should be nested in the <system.web> section.


jeremy at 7:30 PM | (9) Comments | Add a comment | Permalink



 Monday, October 02, 2006


Custom Error Handling in ASP.NET 2.0    
ASP.NET 2.0 provides the ability to define custom error pages to be used, by specifying the error pages in the web.config. This can be quite useful if you want to prevent your users from seeing detailed errors output to the page. However, this is not always ideal in the world of web application development. In some of my applications, I use a different model to notify the user that an error occurred and to also notify me that an error occurred.

The general idea is as follows: Create a Public Procedure that accepts an object of type Exception. In the procedure you would write code to email you the message of the exception object and set a session variable to True.

In the Page_PreRender of your master page, you would place and if statement to check the session variable. The statement would be similar to the following.

If IsNothing(Session.Item("errorOccured")) = False Then
 If CBool(Session.Item("errorOccured")) = True Then
  Page.ClientScript.RegisterStartupScript(GetType(String), "error", "alert('An error has occured. Your data was not saved.'); ", True)
  Session.Item("errorOccured") = Nothing
 End If
End If

Then in the Catch of all your Try Catches, you would call the error handling procedure you created, passing in the exception object. Using this design your user gets a simple notification that an error occurred and you get an instant email with the details of the error. In more complex applications you could pop up a form asking the user to type in details of what they were doing when the error occurred, and then email the users comments along with the exception information.


jeremy at 11:39 PM | (0) Comments | Add a comment | Permalink



 Wednesday, September 20, 2006


Set the visibility of controls based on roles in ASP.NET 2.0    

In small ASP.NET 2.0 web sites, when membership services is being used, developers may sometimes want to set the visibility of a button or other control based on the role of the logged in user. One simple way to do this is by using code similar to the following.

<asp:ImageButton ID="ibtnSubmit" runat="server" PostBackUrl="~/Feedback.aspx" Visible='<%# CBool(HttpContext.Current.User.IsInRole ("Administrators")) %>' />

This technique works well if you are using a DataList or GridView and you want to be able to set the visibility of specific controls in each row based on roles. Of course, this only works well when the visibility pertains to one role. If you wanted to set the visibility of a control based on more than one role, you could use a Protected function in place of the IsInRole function above. It would look something like the following.

In codebehind:
 Protected Function IsVisible() As Boolean
  Dim aryRoles As String() = Roles.GetRolesForUser()
  If aryRoles.Length = 0 Then Return False
  For i As Integer = 0 To aryRoles.Length
   Select Case aryRoles(i).ToUpper
    Case "ADMINISTRATORS"
     Return True
    Case "FRIENDS"
     Return True
   End Select
  Next
 End Function

On the page:
<asp:ImageButton ID="ibtnSubmit" runat="server" PostBackUrl="~/Feedback.aspx" Visible='<%# IsVisible() %>' />

It's important to note, that it would be better to define a group of roles in the web.config in the appsettings, rather than hard code them as shown in the function above. However, the purpose here, is just to give you an idea of solutions related to this topic.


jeremy at 9:40 AM | (6) Comments | Add a comment | Permalink



 Monday, September 18, 2006


Adding custom properties for membership users in ASP.NET 2.0    

This instruction is for the programmer that doesn’t really care to hear about the nuts and bolts of adding profile properties to membership users, but just wants the quick read on what to do. I’m assuming that you’re already using the ASP.NET 2.0 membership services.

Adding custom properties for users is really quite simple. In the web.config you define your properties in the <system.web> section like the following code.
   <profile>
      <properties>
         <add name="FirstName"/>
         <add name="LastName"/>
         <add name="Address1"/>
         <add name="Address2"/>
         <add name="City"/>
         <add name="State"/>
         <add name="Zip" />
         <add name="PhoneNumber"/>
      </properties>
   </profile>

Once you have defined your properties in the web.config, the properties magically become accessible through the ProfileCommon class. The ProfileCommon class is only available after adding the Profile section to the web.config.

Now that you have defined the additional properties for users, you can now set and retrieve these properties.

You would probably want to set the properties when creating the user or editing a user’s information. For this purpose you could use code similar to the following. Notice you need to call the Save after you set the properties.

Dim userProfile As ProfileCommon = ProfileCommon.Create(CreateUserWizard1.UserName, True)

With userProfile
   .FirstName = txtFirstName.Text.Trim
   .LastName = txtLastName.Text.Trim
   .Address1 = txtAddress1.Text.Trim
   .Address2 = txtAddress2.Text.Trim
   .City = txtCity.Text.Trim
   .State = drpState.SelectedItem.Value
   .Zip = txtZip.Text.Trim
   .PhoneNumber = txtPhoneNumber.Text.Trim
   .Save()
End With

You can then retrieve information for a user using code similar to the following.

Dim userProfile As ProfileCommon = ProfileCommon.Create(HttpContext.Current.User.Identity.Name, True)

            Dim strFirstName As String = userProfile.FirstName
            Dim strLastName As String = userProfile.LastName
            Dim strCompany As String = userProfile.Company
            Dim strAddress1 As String = userProfile.Address1
            Dim strAddress2 As String = userProfile.Address2
            Dim strCity As String = userProfile.City
            Dim strState As String = userProfile.State
            Dim strZip As String = userProfile.Zip
            Dim strPhoneNumber As String = userProfile.PhoneNumber

You could then display this information on an administration page.

That’s all there is to it. For a working example including a page to manage user information, you can register and download my User Management example project.



jeremy at 9:29 AM | (13) Comments | Add a comment | Permalink







Join WebHost4Life.com






If you would like to help support this project, please click the button below to make a small donation.