Jon's Blog

.NET Development & More

GridView EmptyDataTemplate: Get Rid of That Annoying Border!

If you are like me then you may have a CSS table style for your GridView with a specific border.  When you use the the EmptyDataTemplate you may then have a border around your message.  I create a CSS class and then use the EmptyDataRowStyle and set its CssClass.  Note, in the GridView I am also setting the default border to 0.  Example:

CSS

table.myGridClass .empty td
{
border-style: none;
border-width: 0px;
background-color: #ffffdd;
}

 

ASPX

<asp:GridView ID="myGridView" runat="server" CssClass="myGridClass" BorderWidth="0">
<HeaderStyle CssClass="myHeaderStyle" />
<RowStyle CssClass="myRowStyle" />
<EmptyDataRowStyle CssClass="empty" />
<EmptyDataTemplate>Your message here.</EmptyDataTemplate>

ASP.NET AJAX Control Toolkit: Bug with Modal Popup Extender

I found a bug in the September 30, 2009 release of the AJAX Control Toolkit.  When you press a button that is inside of a Modal Popup dialog box it will cause a full page postback instead of a partial postback.  When I reverted to the May 13, 2009 release this did not occur.

By the way, I also ran into another weird issue on the September 2009 release where random commas were being inserted into my text box on each postback.  If you are having this issue I also recommend reverting to the May 2009 release.

ASP.NET: Beware of Blank ImageUrl on ImageButton

Earlier today I was debugging a rather tricky issue.  It came down to the fact that an ImageButton control was not getting its ImageUrl property set in certain scenarios.  This would cause ASP.NET to output the following HTML for this control:

<input type="image" name="myName" id="myID" src="" />

 

This was causing the page to request Default.aspx since a src was not explicitly defined*.  So be sure to set the ImageButton control (or its container element) to Visible="false" if you are not setting its ImageURL property.  Otherwise you may have some code-behind logic on Default.aspx executed when you aren't expecting it!

* I assume this is because Default.aspx is set as the default document in IIS.

ASP.NET AJAX: Checking for Partial Postback - IsInAsyncPostBack

My initial thought is always to look for a property on the Page object, but this is actually a property on the ScriptManager.  So if you want to only execute code if it isn't a partial page post back you can do the following:

if (!scriptManagerInstance.IsInAsyncPostBack)
{
    // Do stuff here
}

LINQ Advanced Search

When creating an advanced search you often need to dynamically create the Where statments in your SQL.  Here is an easy way to do this in LINQ.  In the example below orderID, lastName, firstName, shipped are all values retrieved from controls on the page.

var query = from orders in dataContext.MyOrdersTable
select orders;

if (orderID.HasValue)
{
query = query.Where(order => order.OrderID == orderID);
}
if (!string.IsNullOrEmpty(lastName))
{
query = query.Where(order => order.LastName == lastName);
}
if (!string.IsNullOrEmpty(firstName))
{
query = query.Where(order => order.FirstName == firstName);
}
if (shipped.HasValue)
{
query = query.Where(order => order.Shipped == shipped);
}

myGridView.DataSouce = query;
myGridView.DataBind();

Using ASP.NET and GDI+ to Resize Uploaded Image

Below is some sample code I used to resize an uploaded image if the image does not meet the required width and height.  MAX_WIDTH and MAX_HEIGHT below are constants.  Change them as needed.  I am saving the resized image as a JPEG.  It is also a good idea to inform the user that their image was resized.  I removed that code to increase readability.

Note: In this sample the image is being saved to a database, but you could also save it to a file if you wanted to.

if (fileUpload.HasFile)
{
// Get uploaded image from upload control
System.Drawing.Image uploadedImage = System.Drawing.Image.FromStream(fileUpload.PostedFile.InputStream);

// Check width and height of image and resize if necessary
if (uploadedImage.Width > MAX_WIDTH || uploadedImage.Height > MAX_HEIGHT)
{
// Get the factor we must resize by
decimal heightFactor = Decimal.Divide(uploadedImage.Height, MAX_HEIGHT);
decimal widthFactor = Decimal.Divide(uploadedImage.Width, MAX_WIDTH);
decimal resizeFactor = Math.Max(heightFactor, widthFactor);

// Calculate the new height and width using the resize factor
int newHeight = Convert.ToInt32(uploadedImage.Height / resizeFactor);
int newWidth = Convert.ToInt32(uploadedImage.Width / resizeFactor);

Bitmap sourceBitmap = new Bitmap(uploadedImage);
Bitmap newBitmap = new Bitmap(newWidth, newHeight);
Graphics graphics = Graphics.FromImage(newBitmap);
MemoryStream memoryStream = new MemoryStream();

try
{
// Set quality settings and save to MemoryStream object as Jpeg
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage(sourceBitmap, new Rectangle(0, 0, newWidth, newHeight));
newBitmap.Save(memoryStream, ImageFormat.Jpeg);

// Save to Business Object
bizObject.FileData = new Binary(memoryStream.ToArray());
bizObject.FileType = "image/jpeg";
bizObject.FileName = Path.GetFileNameWithoutExtension(fileUpload.FileName) + ".jpg";
}
catch (Exception)
{
throw;
}
finally
{
// Dispose of graphics objects
memoryStream.Dispose();
sourceBitmap.Dispose();
newBitmap.Dispose();
graphics.Dispose();
}
}
else
{
// Image size is correct, so save what was uploaded
bizObject.FileType = fileUpload.PostedFile.ContentType;
bizObject.FileName = fileUpload.FileName;
bizObject.FileData = new Binary(fileUpload.FileBytes);
}

// Other code removed for clarity
}

File Upload: File Extension Validation

This is an easy way to validate the file extension on a FileUpload control.  This way you won't have to postback to the server to validate.  Unless, of course, the user has JavaScript turned off.  The example below is for images (JPEG, GIF, or PNG).

<asp:RegularExpressionValidator ID="regxImage" runat="server" Text="*" 
ErrorMessage
="Image must be a JPEG, GIF, or PNG."
ValidationExpression="(.*?)\.(jpg|JPG|jpeg|JPEG|jpe|JPE|png|PNG|gif|GIF)$"
ControlToValidate="myFileUpload" />

IE8: Image max-width bug

I found a strange IE8 bug dealing with images and the CSS max-width property.  I had an image inside of a table cell.  The image had a max-width set using CSS.  In IE8, if the actual image width was larger than the max-width value then the image was resized properly, but the table cell was not.  It was strange because it worked fine in IE7 and Firefox.  The way I fixed this issue was to wrap the image inside of a div and then set the width of the div to the same value as the max-width of the image.  Oh well, easy enough.

HTML:

<table class="myTable">
    <tr>
        <td class="col1">
            <div class="imageWrapper">
                <img src="images/blah.jpg" class="myImage" />
            </div>
        </td>
        <td class="col2">
            <p>Content here</p>
        </td>
    </tr>
</table>

 

CSS:

table.myTable .col1 { vertical-align: top; width: 122px; }
table.myTable .col2 { vertical-align: top; width: 353px; padding-left: 5px; }

img.myImage { max-width: 122px; max-height: 172px; }
div.imageWrapper { width: 122px;  }

DropDownList: Customized DataTextField

If you try to bind a DropDownList to a DataSouce you will find that you can only use one column as the DataTextField.  The easiest way I have found to overcome this is to manually add the items to the DropDownList like this:

foreach (var item in items)
{
ListItem li = new ListItem(item.FirstName + " " + item.LastName, item.ID);
ddlMyDDL.Items.Add(li);
}

You could also change your query/stored procedure to pull back what you needed displayed in a single column.  But I prefer the above method.

SQL Server Trigger for Row Archive

This trigger will write to an archive table when a row is updated or deleted.  Very useful when you want to know who did what and when.

USE [DatabaseName]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[trigTableName_Archive] 
   ON  [dbo].[TableName]
   FOR UPDATE, DELETE
AS 
BEGIN
    SET NOCOUNT ON;
    
    INSERT INTO TableName_ARCHIVE
        (Column1,
        Column2,
        Column3)
    SELECT
        Column1,
        Column2,
        Column3
    FROM deleted

END