Three Ways to Catch Exceptions in ASP .NET

Before we get on with the article, a couple of quick announcements. Regular readers of this site know well my tendency to put this site through an obnoxious number of redesigns. Sometimes I feel like I'm in a never-ending design cycle, because I'm always tweaking something here or adding something there. Anyway, I once again found myself twitching to do a redesign. I hesitate to say that I got tired of the old ( well, current, as of this entry ) theme, because I still like it; however, it most definitely grew old. So: look for the new design soon — like over the weekend; definitely over next week. :-)

Moving on.

Catching Exceptions in a Method

public void DownloadPdf(string path)
{
 try
 {
  System.IO.StreamReader reader = System.IO.File.OpenText(path);
 }

catch (System.UnauthorizedAccessException ex) { // Hey, you don't have access to the file! }

catch (System.IO.FileNotFoundException ex) { // Hey, the file doesn't exist }

catch (Exception ex) { // Something bad happened } }

Catching Exceptions at the Page Level

protected override void OnError(EventArgs e)
{
 Exception exception = HttpContext.Current.Server.GetLastError();

// Inform the user about the exception, log it, and do whatever // else you want to do here. }

Catching Exceptions at the Application Level

// In global.asax
protected void Application_Error(object sender, EventArgs e)
{
 Exception ex = HttpContext.Current.Server.GetLastError();

// Do whatever with the exception here. }

You might notice that catching exceptions at the application level is remarkably similar to catching them at the page level. This is good — one less thing for us to have to remember. :-)

Clearing Errors

What if you want to have your application continue on its merry way, not stop dead in its tracks because of the exception? For example, suppose the user is trying to upload a file and your application throws an exception because the file is too big. It would be nice if your application lets the user to continue working instead of taking him to the jarringly-ugly yellow page of death error page?

This is what happens when you catch an exception (aka, method 1), so you don't need to do anything special. However, it's a pain to have to wrap every single method in a try...catch block. The way to clear exceptions/errors with the other two methods is with the Server class' handy ClearError method:

 // In global.asax
protected void Application_Error(object sender, EventArgs e)
{
 Exception ex = HttpContext.Current.Server.GetLastError();

// Do whatever with the exception here.

HttpContext.Current.Server.ClearError(); }

Conclusion

You should, at some point, trap all exceptions that occur in your application. At the very least, you should redirect the user to a custom error page. Not only are the default error pages produced by ASP .NET horrendously ugly, they're usually unhelpful to the end-user. Also, they reveal information about your code, which is bad from a security-viewpoint. ASP .NET provides 3 very easy ways to trap errors in an application.

My favorite method — well, my second favorite method — of catching exceptions is using the Global.asax's Application_Error method. ( My favorite way is to use HttpModules, which I'm going to talk about in a future article. )

How To List All Stored Procedures in a Database

exec sp_stored_procedures

That's it. That single line/word will list all the stored procedures in the currently-active database.

DatabaseName.dbo.sp_stored_procedures

This line lists all the stored procedures in the specified database.

Another useful stored procedure is sp_helptext, which shows you the actual (SQL) stored procedure:

DatabaseName.dbo.sp_helptext StoredProcedureName

Using these stored procedures with a linked server is straight-forward, too:

NameOfTheLinkedServer.NameOfTheDatabase.DatabaseOwner.sp_stored_procedures

Commenting Out Server Controls in ASP .NET

This is something I seem to be doing an awful as of late. I start out with some control (say a GridView), then switch to some other control (say a Repeater), but I don't want to delete the GridView control until I get the Repeater control working.

You might have tried commenting out the control the HTML way — i.e., <!--...--> — and you probably found out that ASP .NET engine still parses it. Until recently, I was dealing with this the hard way: cutting & pasting the control into Notepad.

No longer.

Enter Server Comments

Namely:

<%--

<asp:GridView ID="ProductsGridView" runat="server" DataSource="ProductsDataSource"> </asp:GridView>

--%>

ASP .NET will ignore everything within a server comment block.

How To Show Some Rows Differently in a GridView

Suppose you're showing a list of customers, and you want to highlight any customer who'd been with you since before 1920. Maybe you also want the JoinedOn field to show the number of months for customers who've been with you for less than a year. It's fairly easy.######Add OnRowDataBound Handler to GridView

The easiest place to change the data is just after the data gets bound to the row. So:


<asp:GridView runat="server" ID="CustomerGrid" OnRowDataBound="CustomerGrid_OnRowDataBound">
</asp:GridView>

Make the changes in CustomerGrid_OnRowDataBound


protected void CustomerGrid_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
 GridViewRow row = e.Row;

// Make sure we aren't in header/footer rows if (row.DataItem == null) { return; }

Customer customer = row.DataItem as Customer;

if (/* Do your conditionals here*/) { // Change Row formatting here OR // Add new cells // Or create an entirely different cells } }

How do you format a date variable in a GridView?

<asp:BoundField DataField="CreatedOn" DataFormatString="{0:M/dd/yyyy}" HtmlEncode="false" />
######Other Resources:

Registering Server Controls in Web.Config

A useful addition to ASP .NET 2.0 is the ability to register web controls in web.config. In ASP .NET 1.1, if you wanted to use a custom server control on twenty different pages, you had to register it on all twenty of those pages:

  1. <%@ Register tagprefix="tagprefix" Namespace="Namespace" Assembly="Assembly" %>

In ASP .NET 2.0, you can register the server control in the controls section of web.config once and use it in whatever page you want of the web application.

  1. <pages>
  2. <controls>
  3. <add
  4. tagPrefix="MyTagPrefix"
  5. namespace="My.Namespace"
  6. assembly="MyAssembly"/>
  7. </controls>
  8.  
  9. <!-- Other elements go here -->
  10.  
  11. </pages>

Read more on MSDN

Two Cents On Access Modifiers in C#

Access Modifiers

Access modifiers, as their name suggests, control who sees what in an application. C# has 4 basic access modifiers (there’s also a 5th one, but more on that later). Here they are, listed from least restrictive to most restrictve.

  1. public: accessible anywhere.
  2. protected: accessible to current class and all derived classes.
  3. internal: accessible to any class in the current assembly.
  4. private: accessible to current class only.

Easy enough to understand.

Some Things to Keep In With Access Modifiers

  1. Namespaces can’t have access modifiers. They’re always public. So: public namespace AwesomeNewNamespace { … } will produce a compile-time error.
  2. Classes can be either public or internal but not protected or private. So: private class AwesomeNewClass { … } will produce a compile-time error. This makes sense if you think about it — how exactly would you use a private or a protected class??
  3. Interfaces, like classes, can be either public or internal but not protected or private.
  4. Methods defined in interfaces can’t have access modifiers.
  5. Enums are always public. They can’t have access modifiers either.
  6. By default, classes are internal. So: class NotSoCool { … } is equivalent to internal class NotSoCool { … }.
  7. By default, methods in class are private. So void SomeAwesomeMethod() { … } is equivalent to private void SomeAwesomeMethod() { … }.
  8. Same goes for variables (fields): private unless specified otherwise.
  9. Needless to say, you can’t use access modifiers on variables inside a method: public voidMethod() { protected string someString; will produce a compile-time error.
  10. Derived classes can either have the same restriction level or can be more restrictive than the base class but not less restrictive. So: internal class Base { … } public class Child : Base { } will produce a compile-time error.

Now that we got that out of the way, let’s take a look at that 5th modifier that I mentioned at the beginning. This would be the compound modifier protected internal. After looking at it for a minute, you would think that it does what other compound modifiers in .NET do. For example, protected virtual void AwesomeMethod() makes AwesomeMethod both virtual and protected, so you’d think that protected internal AwesomeClass { … } would make the class both protected and internal (i.e., it is only accessible to derived classes in the assembly) but you would be wrong. For some bizarre reason that I have yet to fathom, the powers-to-be have decided that protected internal means protected or internal (so that the method is available to all derived classes as well as all classes in the current assembly).

Granting EXECUTE Permissions on All Stored Procedures

Something I’ve had to do often. Until now, I’ve gone through the “laborous” (hehe) process of remembering what stored procedures I’ve added and granting EXECUTE permissions to whatever user for each procedure. I was sure that there was an easier way to grant the permission on all stored procedures, and there is!

GRANT EXECUTE TO [Insert the name of the user here]

If you’re using SQL Server 2000, you don’t have it so easy. However, here’s an article on how to create a stored procedure to do the same.

5 of 7 pages « First  <  3 4 5 6 7 >

On the Side