ASP.NET Membership Provider - Validating Duplicate Email Addresses

ASP.NET Membership Provider makes implementing secure authenticating membership forms more straightforward. The ASP.NET Membership Provider contains so many useful methods. But I could not find a method within the Membership class to check whether there was an existing email address in the database even though you can state in the web.config (requiresUniqueEmail) file:

<membership>
  <providers>
    <add
      name="SqlMembershipProvider"
      type="System.Web.Security.SqlMembershipProvider, ..."
      connectionStringName="LocalSqlServer"
      enablePasswordRetrieval="false"
      enablePasswordReset="true"
      requiresQuestionAndAnswer="true"
      applicationName="/"
      requiresUniqueEmail="true"
      passwordFormat="Hashed"
      maxInvalidPasswordAttempts="5"
      minRequiredPasswordLength="7"
      minRequiredNonalphanumericCharacters="1"
      passwordAttemptWindow="10"
      passwordStrengthRegularExpression=""
    />
  </providers>
</membership>

I created the following CustomValidator with a ServerValidate event to carry out the duplicate email check:

protected void DuplicateEmailCheck_ServerValidate(object source, ServerValidateEventArgs args)
    {
        //Create MembershipUserCollection to collate a list of duplicate email addresses
        MembershipUserCollection memCollection = Membership.GetUserNameByEmail(args.Value.ToString());

        //If duplicate email addresses are found then error
        if (memCollection.Count > 0)
        {
            args.IsValid = false;
        }
        else
        {
            args.IsValid = true;
        }
    }

Validation To Check Length Of String Using Regular Expression

I came across a problem today when trying to find an effective way to validate the length of a password field within a registration form I was creating. ASP.NET already has a bunch of useful validation controls. Most of which I have already have in use within my registration form, such as the RequiredFieldValidator, CompareValidator and RangeValidator.

Now you might be thinking. What’s your problem dude? Its not hard to validate the length of a field. Yeah, you are right. But all the validation controls I am using (above) do not create post backs. I could have easily created a CustomValidator control to solve my problem, but this only fires once a post back has occurred.

I guess my only solution is to use a RegularExpressionVaildator which meant I had to do some research into RegEx. To use RegEx to validate the length of a string between 0 and y (some number), use the following expression:

.{0,y}

To validate the exact length, use the following expression:

.{y}

Both example’s above will accept any type of characters entered in the field.

I Feel It's Going Down 10 Feet Below The Ground

microsoft_vista-logo Since the middle of 2008 we have seen that quite a few business have been hard hit by the recession we are currently experiencing. Things are set to get worse in 2009. Who would have thought that out of all the businesses in the world that the Microsoft monopoly would somehow be effected. I was quite surprised to read speculation across the web that for the first time ever in Microsoft's 33 year history,  15,000 of its employees across US and overseas divisions could be laid off and 3,000 UK employees face an uncertain future.

Well I suppose this was bound to happen sooner or later since retail spending has been reduced and consumers are opting for open source operating systems such as Linux. You cannot beat getting something for free! Microsoft operating system, corporate and office licences could also suffer a hit due to businesses scaling down costs. Maybe if Microsoft stopped releasing crap bug filled software (like Windows Vista) they could have reduced their costs.

Many companies are not even touching Windows Vista with a barge pole, due to the performance hungry features and poor reception. Generally, companies normally delay upgrading their operating systems, since they need to justify the impact on the business and of course costing's. There have been reports that Vista is installed on considerably fewer enterprise PCs than originally projected. Oop's, I went off on a bit of a tangent. Window's Vista really annoys me!!!

Anyway, if Microsoft do go ahead with the redundancies, internetnews.com states that under performing areas, such as Entertainment and Devices Division and the Online Business Division will face the most brutal cuts.

Free McAfee Internet Security 2009

McAfee-Internet-Security-2009-Free-3-Months-Trial What a way to start the new year with some free software (and I am talking the legal way). I found that my current PC Internet Security was soon to expire. Instead of renewing my existing Bullguard licence, I decided it was time for a change after being a loyal three year customer mainly because the yearly fee was starting to get a bit too expensive compared to other packages on the market.

As usual I always look at the customer reviews on the Amazon web site, which is always useful. But this time I found one the reviews someone written more useful than others. It contained a coupon code for a free copy of McAfee Internet Security from the US McAfee website.

All you need to do in order to get your free copy of McAfee Internet Security 2009 is to carry out the following:

  1. Go to http://us.mcafee.com/root/campaign.asp?cid=53347.
  2. Enter coupon code: VSPPROMOCF. You will magically see the Grand Total is now $0.00.
  3. Ensure that there is only one copy of Internet Security in your basket for one user.
  4. Click on the "Checkout" button and register your new account. This account will just contain details of when your year subscription will expire.

Awesome!

I am not too sure how long it is valid for. But give it a try. It worked for me!

Left Navigation Site Links Not Appearing In MOSS 2003

If any of you have come across a problem in SharePoint 2003 whereby some users are not able to see a link to an area within the main portal page, the solution couldn't be even easier. Ensure all users required to access the area are setup with access rights for that area. I always thought that even if a user does not have access to an area the link will always be shown in the navigation within the main portal site. Obviously I was wrong. Silly me!

What's The Difference Between NULL and DBNull

I always used NULL and DBNULL interchangeably in my coding around my database results without ever considering what were the differences. Fortunately, I stumbled upon a great blog written by Bilal Haidar, "Difference between NULL and DBNull"

If I understand correctly, you use DBNULL to check if a certain field in a database is null and you would use NULL to check if a whole record is not found in the database.

The Google Chrome Comic Strip

I have to say that I am quite impressed with the way Google markets its own applications and services. Who would ever had thought of using a comic string to introduce the key workings of a specific application? Its a lengthy comic to say the least, consisting of 38 “fun filled” pages, which actually makes learning about the Chrome browser an interesting read.

Google Chrome Comic 1

Google Chrome Comic 2

But this does ask the question on why Google is releasing their own browser? I thought they had extended their search deal with Mozilla Firefox in return for setting Google as the default search engine. I guess this may cause an awkward relationship between the two in the future. But I suppose any attack against the dreaded Microsoft Internet Explorer browser can only be a benefit!

I have to say that the guy wearing the glasses on the left bares a striking (less cool) resemblance to me. :-)

You can view the full comic strip here.

Outputting Custom Made Charts To An ASP.NET Page

A few weeks ago I was trying to implement a Bar and Pie Chart for a report in a web application. I found that most of the charting solutions on the web cost an arm and a leg. So I decided to have a bash at creating my own one.

I have been reading through the MCTS Application Development Foundation book and found a couple of chapters on using System.Drawing namespace to output graphics and create Pie Charts in a C# application. Great stuff! However, I encountered a problem when my Chart was rendered within a web page that contains other HTML content. For some reason there was no HTML in my page and all that was displayed was my Chart.

This is how I wanted my chart to be inserted into my page:

ChartScreenshot1

However, when my charting code was added, my page looked like this:

ChartScreenshot2

After investigating this problem further it seems that when you output the chart image to a stream the whole page is rendered as an image which removes all the HTML. For example:

Response.ContentTye = "image/gif"; //MIME type
Bitmap.Save(Response.OutputStream, ImageFormat.Gif);

In order to get around this problem required quite a strange work around:

  1. In the page where you need to the chart to be displayed (we will call Report.aspx) add an ASP Image control that will link to an .aspx page that will contain your chart. Things will become more clearer in the next step.
<asp:Image ID="imgSelfAverageBarChart" ImageUrl="/Charts/BarChart.aspx" runat="server" />
  1. Create a new ASP.NET page that will contain all the code for your chart (we will call BarChart.aspx). Now you might be thinking how can I send the figures to the chart? Well this can be done be using Session variables or parameters within the web page link that you used in your ImageUrl in the Report.aspx page.
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
public partial class BarChart : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            List<string> Questions = new List<string>();
            List<float> Values = new List<float>();
    
            //Check the session values have values
            if (Session["Sections"] != null && Session["SelfAverageValue"] != null)
            {
                Questions = (List<string>)Session["Sections"];
                Values = (List<float>)Session["SelfAverageValue"];
            }
    
            Bitmap imageBitmap = new Bitmap(600, 285);
            Graphics g = Graphics.FromImage(imageBitmap);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.Clear(Color.White);
    
            Brush[] brushes = new Brush[5];
            brushes[0] = new SolidBrush(Color.FromArgb(255, 216, 0));
            brushes[1] = new SolidBrush(Color.FromArgb(210, 219, 252));
            brushes[2] = new SolidBrush(Color.FromArgb(0, 127, 70));
            brushes[3] = new SolidBrush(Color.FromArgb(0, 148, 255));
            brushes[4] = new SolidBrush(Color.FromArgb(190, 99, 255));
    
            int xInterval = 70;
            int width = 60;
            float height = 0;
    
            //Draw the Pie Chart
            for (int i = 0; i < Values.Count; i++)
            {
                height = (Values[i] * 40);        // adjust barchart to height of Bitmap
                //Draws the bar chart using specific colours
                g.FillRectangle(brushes[i], xInterval * i + 50, 260 - height, width, height);
                //Draw legend
                g.FillRectangle(brushes[i], 420, 25 + (i * 50), 25, 25);
                g.DrawString(Questions[i], new Font("Arial", 8, FontStyle.Bold), Brushes.Black, 450, 31 + (i * 50));
                // Draw the scale
                g.DrawString(Convert.ToString(Math.Round(Convert.ToDecimal(Values[i]), 2)), 
                new Font("Arial", 10, FontStyle.Bold), Brushes.Black, xInterval * i + 45 + (width / 3), 300 - height);
                // Draw the axes
                g.DrawLine(Pens.Black, 40, 10, 40, 260);        //   y-axis
                g.DrawLine(Pens.Black, 20, 260, 400, 260);       //  x-axis
            }
    
            Response.ContentType = "image/gif";
            imageBitmap.Save(Response.OutputStream, ImageFormat.Gif);
            imageBitmap.Dispose();
            g.Dispose();
        }
        catch
        {
        }
    }
}
  1. Go back to Report.aspx page and add the code to parse your values in a Session.
//Some code that carried out calculations
//Calculated the averages
float selfAverageTotal = selfAssessValue / numberOfSections;
float otherAverageTotal = otherAssessValue / numberOfSections;
//Add generic list
List<string> questions = new List<string>(); //To store the names of x and y axis
List<float> averages = new List<float>();    //To store the values
questions.Add("Self Average Total");
averages.Add(selfAverageTotal);
questions.Add("Other Average Total");
averages.Add(otherAverageTotal);
//Parse lists to session variables
Session["Questions"] = questions;
Session["AverageValue"] = averages;

So the idea of this is that the Chart.aspx will just the render our chart and we don't care if the HTML gets wiped in this web page since we only want the image.

You might be thinking: Why didn't you use a User Control? Well this is one of the first things I tried when trying to resolve this issue which I believe would have been a nicer implementation. Unfortunately, my report page HTML still got rendered as an image.

If anyone knows a better way to output a chart to a webpage, then please leave a comment! Thanks!

Oh yeah, and here is what my Bar Chart looked liked by using the above code: Sample Chart Output

Creating A Comma Delimited String

A little while back I needed to create a comma-delimited string to parse into my SQL Query. My first attempt in creating my comma-delimited string involved using a StringBuilder class and appending a comma at the end of each of my values via a loop. However, I found that my application would error when parsing my comma-delimited string into my SQL query due to the fact a comma was added to the end of my string.

After some research on the MSDN website to solve my problem I found a solution and it was simpler than I thought. The .NET Framework already has a class called CommaDelimitedStringCollection and it is pretty simple to use as the following example shows:

using System.Configuration;
public partial class CommaPage : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //Create a collection to parse to CommaDelimitedStringCollection class
        List<string> cars = new List<string>();
        cars.Add("Volvo");
        cars.Add("VW");
        cars.Add("BMW");
        cars.Add("Ford");
        
        //Create instance of CommaDelimitedStringCollection
        CommaDelimitedStringCollection commaCollection 
        = new CommaDelimitedStringCollection() ;
        
        //Iterate through cars collection and add to commaCollection
        foreach (string item in cars)
        {
            commaCollection.Add(item);
        }
        
        //Read out list of values
        Response.Write(commaCollection.ToString());     
    }
}

The output of the example above would be: "Volvo, VW, BMW, Ford".

So pretty much the .NET Framework's CommaDelimitedStringCollection class did all the work for me.

Nice one!

Adding An XML Sitemap to a Website

In 2005, the search engine Google launched the Sitemap 0.84 Protocol, which would be using the XML format. A sitemap is a way of organizing a website, identifying the URLs and the data under each section. Previously, the sitemaps were primarily geared for the users of the website. However, Google's XML format was designed for the search engines, allowing them to find the data faster and more efficiently.

Even the most simple sitemap to a website is quite important in order to allow search engines such as Google and Microsoft Live Search to crawl your website for any changes. The following example shows what a basic XML sitemap contains:

<?xml version="1.0" encoding="UTF-8" ?> 
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>/blog/</loc> 
<priority>0.5</priority> 
<changefreq>weekly</changefreq> 
</url>
</urlset>


As you can see the sitemap contain the following:

  • <loc> = Location of the page
  • <priority> = The priority of a particular URL relative to other pages on the same site. The value for this tag is a number between 0.0 and 1.0, where 0.0 identifies the lowest priority page(s) on your site and 1.0 identifies the highest priority page(s) on your site. The default priority of a page is 0.5.
  • <changefreq> = This value indicates how frequently the content at a particular URL is likely to change.

Thankfully, there is a site that will automatically generate an XML sitemap for you: http://www.sitemapspal.com/

I have written a blog post a little while back on how to manually submit your sitemap to search engines which proves to be quite useful if you find that your site has not been crawled for a long time. You can find that blog post here.