Suppressing Paging Numbers on Short DataGrids

by fwhagen Thu, 21 August 2008

I hate seeing a solitary "1" on the bottom of a paged datagrid because the dataset is too short to have more than one page.  You don't really want to turn off paging but suppress the "1" when it is not needed.

Use this code to do just that when binding the grid:

        if (dgEmployee.Items.Count < dgEmployee.PageSize)
            dgEmployee.PagerStyle.Visible = false;


Filed Under: .NET

Easy Image Tools (and FREE too!)

by fwhagen Thu, 08 May 2008

It amazes me in my travels how many people feel the NEED Photoshop for web development.  And, of course, they only use about 1% of its total capability.  It is true that years ago, it was the only game in town for Image creation and manipulation.  But not for a while now.  There are many free alternatives that suit the web developer much better.

Paint.NET My favorite for most tasks is Paint.NET.  It greatest feature is its price:  absolutely free!  It started life as a college project and was so successful, that it lives on as a great piece of Freeware development.  It is not Open Source, however.  Some of the other features include layering, filters, great image processing tools, alpha transparency, PNG, and many, many more.  All put together in a small, efficient package that is both easy to use and very powerful.  And hundreds of dollars less than Photoshop and lacking the disturbing Adobe trend toward spyware.  And as the name suggests, it is built on C#.NET, so I feel like I am supporting the community I am a part of.

GIMP If you need more, there is the GIMP project.  Much more complicated, far more powerful, still free, but not nearly as user friendly.  It resembles Photoshop in many ways, including the powerful plug-in model that PS uses.  I use GIMP 2.2 for things I cannot do in Paint.NET, which really isn't very often. 

You know, between the two, I don't at all miss the copy of PS I had at my last job.  Not at all.  Of course, I am not a graphic designer or a heavy Photographer either that needs the power of PS, but I haven't worked with many people who really were either.

One last note.  For those that have been heard to say, "[MS] Paint is good enough.":  Do yourself a favor and get Paint.NET.  MSPaint hasn't been good enough since the '90s.

Keywords: , ,

Filed Under: .NET | Programming | Work

Checking for Database NULL Values in C#

by fwhagen Tue, 09 October 2007

This really should have been more obvious to me, so why did I have to look it up?  If you need to check for NULL in a returned field from SQL (or any other datasource), you should the .Equals method on System.DBNull.Value.  I usually prefer the "==" notation for conditionals, but that's just me.  This is more efficient.  The code follows:

if (!dsSpecQuery.Tables[0].Rows[0]["device_type_end"].Equals(System.DBNull.Value)) 
    _EndDate = Convert.ToDateTime(dsSpecQuery.Tables[0].Rows[0]["device_type_end"]);

Of course, dsSpecQuery is a DataSet, and the field in question is DateTime out of SQLServer (not that it matters for the conditional).

Keywords: , ,

Filed Under: .NET | Programming | SQL

Proper ASP.NET Database Calls

by fwhagen Mon, 20 August 2007

Last week, I posted an entry about a simple call to an MS-SQL database with a warning that it should only ever be used in a quick and dirty scenario.  By that I mean when it doesn't make sense to integrate or create a Data Access Layer or class to do the heavy lifting for you.

The advantages of creating classes to do the data calls behind the scenes are many, not the least of which is easier development in the long run.  Take a look at the following code:

    Query qEmplQuery = new Query(); 
    qEmplQuery.ConnectionSettings = ConfigurationManager.ConnectionStrings["EmployeeDB"]; 
    qEmplQuery.StoredProcedure = "DW.PKG_HRPORTAL.PRC_EmployeeInfo"; 
    qEmplQuery.AddParameter("P_EmployeeNumber", szEmplNum); 
    qEmplQuery.MinutesCached = 12 * 60; 
    DataSet dsEmplQuery = qEmplQuery.RetrieveDataSet("P_EmployeeInfo");

Much easier than even the "simple" call I posted earlier, isn't it.  The beauty of this is that it is also an Oracle call (database agnostic:  the same call for Oracle or MS-SQL makes for easier and standardized development) and is cached for 12 hours.  We also have a coding standard that only parameterized Stored Procedures are used for any kind of data access. 

But the most important advantage is that the Query class contains all of the complex coding needed to make this as efficient and "correct" as you know how and never have to think about it again.  This is basic abstraction and Object Oriented Programming fundamentals.  I have used Enterprise Library factories for my calls in Query because of the desire for its good caching and efficient data and network layer calls, but you can use whatever you want. 

In my next series of posts, I will present details of the Query class in order to help build your own.

Keywords: , ,

Filed Under: .NET | DataBase | Programming

Simple ASP.NET Database Query

by fwhagen Wed, 08 August 2007

Below is the most simple database query for C# to populate a GridView object:

int nItemID = 1; try { using (SqlConnection oSQLConn =
new SqlConnection(ConfigurationManager.ConnectionStrings["UserInfo"].ConnectionString)) { oSQLConn.Open(); using (SqlCommand oSQLCmd = new SqlCommand()) { oSQLCmd.Connection = oSQLConn; oSQLCmd.CommandText = "SELECT DisplayName, EMail FROM Users WHERE UserID = @PARAM_ItemID"; oSQLCmd.Parameters.AddWithValue("@PARAM_ItemID", nItemID); SqlDataReader oSQLReader = oSQLCmd.ExecuteReader(); GridView1.DataSource = oSQLReader; GridView1.DataBind(); } } } catch (Exception ex) { Label_ErrorMsg.Text = ex.Message; }

There are actually many reasons to never use this, including performance, caching, safe SQL, code reuse, standards, proper exception handling, etc, etc.  But sometimes you need a quick and dirty, non-production, piece of code for testing and/or development.  This is it.

Keywords: , ,

Filed Under: .NET | Programming | SQL

Oracle.NET connector issues

by fwhagen Wed, 18 July 2007
Interesting problem:  I always use library functions in .NET apps to maximize code reuse, especially for Data Access calls.  So when I ran across the following error from Oracle when connecting to a server running 10.2, I was stymied.  Especially since it worked fine with a 10.1 server:
ORA-12571: TNS:packet writer failure

Looking this one up brings a whole lot of results, none of them helpful in this situation.  To make it worse, VS2005 ran the application just fine. 

The solution?  The server had the 8.1 connector installed, which for some reason connects to 10.1 just fine.  10.2 was different enough to through the error above.  We got IS to push the 10.2 client on the server, and everything is working.

Keywords: ,

Filed Under: .NET | Oracle

VSS Source Code Headers: Automated Comments

by fwhagen Fri, 20 April 2007
One best practice I insist on is codefile headers, especially since VSS makes this stupid easy.  Below is the format I currently use for C#.NET:


#region Version Header
/// <remarks>
/// ----------------------------------------------------------------------------
///   Application: XXXXXXXXXXXXX
///     $Workfile: Default.aspx.cs $
///   Description: Start page for XXXXXXXXXXX.
///        Author: Frank Hagen
///       Created: 11/22/2006
///     Copyright: © 2007 XXXXXXXXXXXXXXX.
/// ----------------------------------------------------------------------------
///      $Modtime:  $
///     $Revision:  $
///   Mod $Author: XXXXXXXXXX $
///  VSS $Archive: /XXXXX/XXXXX/XXXXX/Default.aspx.cs $
/// ----------------------------------------------------------------------------
/// </remarks>

Keywords: ,

Filed Under: .NET | Programming

Lazy Coding or Careful Coding?

by fwhagen Fri, 09 March 2007

Some background:  A few months ago, I decided to put a little AJAX in an app I inherited.  The problem was a huge form that used post-back to fill some dropdown boxes based on values in other elements.  I coded the AJAX all from scratch, or near scratch anyway, mainly because ATLAS was still in early beta and this is a 1.1 app.  Anyway, everything worked well enough, or so I thought. 

This is where good end-user testing is so important.  You see, since I inherited this beast, I don't know how everything is supposed to work.  Some of the nuances are not always apparent to me and I might miss them.  For example, when creating a new form, a set a parameters will autofill the main form.  When I inserted my AJAX streamlining and tested, everything worked great from my perspective, a new form was created with some of the values prepopulated.   What I didn't realize was that the dropdown list was not being read correctly by the codebehind, because from it's perspective, it was empty the last time it saw it and was not reading the form post value.  I don't know yet whether this is my fault or the friendly designer who wrote this screaming... thing, but the end result is that not all of the values were filled that were supposed to.

So here's where my post title comes in:  When I put the AJAX calls in, I did not change the code-behind.  I simply added my JavaScript and disabled the elements' autopostback attributes.  When developing systems I don't understand, I make as little impact as possible and comment like hell, so someone can come in behind me and fix what I broke.  I also CYA in comments for who requested what changes and why.  Fixing broken code reminds me constantly about the importance of good commenting, despite that I don't do very good job of that in my original code.  Anyway, the implementation of some business logic features and these got rolled up, tested of course, and deployed late yesterday.

Well, this morning I get a frantic call and a HD Ticket:  Yep, the form is not populating all of the values.  It needs to be fixed immediately!  And behold!  It only took 15 minutes to find the cause and simply turn on the autopostback and disable the JavaScript.  All in the aspx file!  If I had removed or commented the methods in the code-behind, I would have had to recompile everything and risk version conflict; I had started on the next set of changes, of course.

So there's a lesson here, I think.  Although it is not the most efficient coding technique in the world, there is ample reason to not remove a method that you think is unused, especially if you do not understand the total impact of a change.  Let it sit there, all it is hurting is a tiny amount of overhead and some compile time.  This time it really saved my bacon!  Next time it will probably bite me.

Disagree?  Send me your exeriences in comments!

Keywords: , , ,

Filed Under: .NET | AJAX | Programming | Work

I Believe - ADO.NET Edition

by fwhagen Fri, 02 March 2007
I Believe...  that all database connections should be opened immediately before using them and closed immediately afterwards.
I Believe...  that if you are going to create a data layer, and you should, and you also create a data access layer, and you should, that the method be put in the lowest level and handled as abstractly as possible.  Yes the connection.close should be called before returning results.
I Believe...  that if you open the connection to the database in a method and pass that connection as a variable to another object, you should be shot.
I Believe...  that if you open the connection to the database in a method and pass it as a variable to another object, and forget to close said connection, you should be stabbed.
I Believe...  that if you open the connection to the database in a method and pass it as a variable to another object, and store the open connection in an ASP.NET session variable, you should be stabbed in the eye.  Twice.  With a spoon.
I Believe...  that if you store the results of a large query in ASP.NET session so you can page it back to the user, they haven't devised a painful enough punishment for you yet.
With special thanks to Blue Collar TV for the "I Believe..." concept.

Keywords: , ,

Filed Under: .NET | Programming | Rant

AJAX and NTLM Authentication Issues

by fwhagen Tue, 06 February 2007

Because the AJAX.NET hadn't been finalized yet, and because the app I was trying to "AJAX up" was a 1.1 app, I chose to roll my own AJAX backend.  It's extremely simple and lightweight, and really wasn't difficult to do.  The only problem that I had was in an Intranet setting with Windows Authentication security throughout.  The first time the client would initiate an AJAX call, the browser would throw a login credential request up.  I tried many different security settings to defeat that but was not successful.  Until I came across an article that mentioned it in passing.  Here's my altered code block:

        req.onreadystatechange = processReqChange;'POST', szURL, true);
        req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.setRequestHeader("Content-length", data.length);
        //req.setRequestHeader("Connection", "close");  /// Fixes AJAX Authentication Issue!!!

Note, line 5 is commentted out.  I don't know why this works, but it does and seemingly without any impact on either the client or the server.  All sessions are closed successfully and there is no data leakage that I can see.  So until I upgrade the app to 2.0 and use the official framework, I'm going with it.

If you'd like my AJAX backend .js file, it is only 60 lines and meets simple AJAX needs.  Just drop me a comment or email here with your address and I will get back to you.

Keywords: ,

Filed Under: .NET | AJAX