Introduction
I have wrote this article to demonstrate custom validation with web controls.
- Web Controls
- Custom Validator
As I only wanted the Custom Validator to fire when a button on the .aspx page had been clicked. All I am going to show in this article is how to create a simple File Upload Control, which:
- Only accepts .gif, .jpg, .png, .bmp
- Provide the user to state whether the image is required or not.
Pages Involved
Here is the page (with Code File) which we will implement the control on:
Default.aspx
Default.aspx.cs
Here is the Web Control page names
CustomControl.ascx
CustomControl.ascx.cs
Tasks for the Web Control ( CustomControl.ascx )
For the web control we need to do the following:
- Add a File Upload
- Add a Custom Validator
- Assign something to the Custom Validator's ServerValidate Event
Here is the Code
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="CustomControl.ascx.cs" Inherits="WebUserControl" %>
<asp:FileUpload ID="FilUpl" runat="server" />
<br />
<asp:CustomValidator ID="ErrorMsg" runat="server" ErrorMessage="CustomValidator" OnServerValidate="ErrorMsg_ServerValidate"></asp:CustomValidator><br />
Tasks For the Web Control Code File (CustomControl.ascx.cs)
For the Code File for the Web Control we need to:
- define all the private variables.
- define all the gets/sets which we will use to set tag parameters and retrieve others.
- define the ServerValidate function which we assigned to the custom validator.
- define a function to get the file extension of the file which is attempting to upload.
Here is the Code
public partial class CustomControl : System.Web.UI.UserControl
{
private bool pGotFile;
private string pFileExt;
private HttpPostedFile pFilePost;
private bool pRequired;
private string pVgroup;
private string[] pFileTypeRange;
private bool Ind = false;
public bool GotFile
{
get { return pGotFile; }
}
public string FileExt
{
get { return pFileExt; }
}
public HttpPostedFile FilePost
{
get { return pFilePost; }
}
public bool Required
{
set { pRequired = value; }
}
public string Vgroup
{
set { pVgroup = value; }
}
public string FileTypeRange
{
set { pFileTypeRange = value.ToString().Split(','); }
}
protected void Page_Load(object sender, EventArgs e)
{
ErrorMsg.ValidationGroup = pVgroup;
}
protected void ErrorMsg_ServerValidate(object source, ServerValidateEventArgs args)
{
if (FilUpl.HasFile)
{
pGotFile = true;
pFileExt = GetExtension(FilUpl.PostedFile.FileName);
pFilePost = FilUpl.PostedFile;
foreach (string str in pFileTypeRange)
{
if (str == pFileExt)
{
Ind = true;
}
}
if (!Ind)
{
args.IsValid = false;
ErrorMsg.Text = "The file format you specified is not supported";
return;
}
}
else
{
pGotFile = false;
if (pRequired)
{
args.IsValid = false;
ErrorMsg.Text = "You must upload something";
}
}
}
private string GetExtension(string FileName)
{
string[] split = FileName.Split('.');
string Extension = split[split.Length - 1];
return Extension;
}
}
Tasks for the Test Page ( Default.aspx )
- Add the tag line at the very top of your page which registers the custom tag which we will use
<%@ Register TagPrefix="CC1" TagName="IUpload" Src="CustomControl.ascx" %>
- Add the tag itself and also a button underneath which we will use to trigger the file upload.
<CC1:IUpload ID="MyUpload1" runat="server" Required="false" Vgroup="Val1" FileTypeRange="jpg,gif,png,bmp" />
<asp:Button ID="Button1" runat="server" Text="Upload Image" CausesValidation="true" ValidationGroup="Val1" OnClick="Button1_Click"/>
Tasks for the Test Page's Code File (Default.aspx.cs)
- Add the event for the buttton.
- Inside this event, check to see if the Page Is valid, Check to see if there is a file, and finally if true, upload it.
Here is the Code
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
if (MyUpload1.GotFile)
{
MyUpload1.FilePost.SaveAs(Server.MapPath("images/MyFile." + MyUpload1.FileExt));
}
}
}
}
Please Note:
I have developed this using ASP.NET Version 2.0, and also using Visual Web Developer Express.
Update With Effect From 11th Aug 2006
I am going to insert something extra to this. Lets say that for the file type range you specify jpg,png,gif,bmp, then you might also want to check that the width of the image meets a certain minimum requirement that you set in the tag. It will check the size without having to save it to disk, by using the InputStream
.
Here is how I achieve the check without saving the file to disk first:
System.Drawing.Image CheckSize = System.Drawing.Image.FromStream(FilUpl.PostedFile.InputStream);
if (CheckSize.PhysicalDimension.Width < minWidth)
{
//Conditional actions here
}
So here is the code again, but this time with the inclusion of the image size check. If it does not meet the required minimum width, it will output this: "Your image does not meet the required minimum size requirements which are" + MinWidth
+"px"etc...
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class CustomControl : System.Web.UI.UserControl
{
//Has the user browsed for a file?
private bool pGotFile;
//The file extension of the Posted File
private string pFileExt;
//The File itself
private HttpPostedFile pFilePost;
//Is the user required to upload an image?
private bool pRequired;
//The validation group that the Custom Validator belongs to on the page
private string pVgroup;
//Extensions you allow to be uploaded
private string[] pFileTypeRange;
//Boolean indicator to check if file extension is allowed
private bool Ind = false;
//The Image Minimum Width
private int minWidth = 0;
/*
* Get and Sets for the above private variables.
* */
public bool GotFile
{
get { return pGotFile; }
}
public string FileExt
{
get { return pFileExt; }
}
public HttpPostedFile FilePost
{
get { return pFilePost; }
}
public bool Required
{
set { pRequired = value; }
}
public string Vgroup
{
set { pVgroup = value; }
}
public string FileTypeRange
{
set { pFileTypeRange = value.ToString().Split( }
public int MinWidth
{
set { minWidth = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
//here we assign the validation group to the Custom Validator, which I have inefficiently named ErrorMsg
ErrorMsg.ValidationGroup = pVgroup;
}
protected void ErrorMsg_ServerValidate(object source, ServerValidateEventArgs args)
{
if (FilUpl.HasFile)
{
pGotFile = true;
pFileExt = GetExtension(FilUpl.PostedFile.FileName);
pFilePost = FilUpl.PostedFile;
foreach (string str in pFileTypeRange)
{
if (str == pFileExt)
{
Ind = true;
}
}
if (!Ind)
{
args.IsValid = false;
ErrorMsg.Text = "The file format you specified is not supported";
//Stop the function
return;
}
if (minWidth > 0)
{
//If you get here then you have set the MinWidth because you are expecting an image,
//and due to validation once at this stage in the code, we know that the user has uploaded
//some sort of image type
System.Drawing.Image CheckSize = System.Drawing.Image.FromStream(FilUpl.PostedFile.InputStream);
if (CheckSize.PhysicalDimension.Width < minWidth)
{
args.IsValid = false;
ErrorMsg.Text = "Your image does not meet the minimum width requirements which are " + minWidth.ToString() +"px";
//Stop the function
return;
}
}
}
else
{
//So if we get here the user has not browsed for a file
pGotFile = false;
//If you have stated that the user has to browse for a file.
//then we must stop now and inform the user of such.
if (pRequired)
{
args.IsValid = false;
ErrorMsg.Text = "You must upload something";
}
}
}
/// <SUMMARY>
/// This returns the file extension. It does not contain the preceding full stop
/// so it would return jpg and NOT .jpg . Please adjust your coding accordingly.
/// </SUMMARY>
/// string
/// <RETURNS>string: the file extension e.g. jpg</RETURNS>
private string GetExtension(string FileName)
{
string[] split = FileName.Split('.');
string Extension = split[split.Length - 1];
return Extension;
}
}
Finally the updated Tag
Inline with my updated code, here is how I would implment it in the Custom Tag.
Register the tag first, I am using a different tag prefix this time:
<%@ Register TagPrefix="ARDesigns" TagName="IUpload" Src="CustomControl.ascx" %>
And then the tag itself:
<ARDesigns:IUpload ID="MyUpload1" runat="server" Vgroup="Val1" FileTypeRange="jpg,gif,png,bmp" MinWidth="400" />
Update With Effect From 3rd September 2006
Basically I need to put this in as I tripped over myself yesterday. Simple, but slipped my mind. People can have files with UPPER CASE file extensions, so we need to put it into lowercase to make the comparison, i.e.
pFileExt = GetExtension(FilUpl.PostedFile.FileName).ToLower();