Creating a Default Error Handler for a Controller

All you have to do to create a default error handler for your ASP.NET MVC controller is put the HandleError attribute on the class. Then, if your code throws an unhandled exception (one not caught in the Try…Catch block), the user will be sent the default Error View in the Views/Shared folder:

<HandleError>	
Public Class HomeController
        Inherits System.Web.Mvc.Controller

At least that's what the attribute will do if you have this tag inside the system.web element in your web.config file:

<customErrors mode="On" defaultRedirect="Error"/>

You can add whatever error information you want to the default Error View by adding code to the View that writes out properties from the Model's Exception property. Alternatively, setting the customErrors element's mode to RemoteOnly will, when you're debugging, let you continue to see ASP.NET's default error page with all of its information while still sending the Error View to your users in production.

Posted by Peter Vogel on 03/07/2014 at 9:37 AM0 comments


Visual Studio Tip: Delete a Line

I've written before about how to comment out code. Sometimes, however, you just want to get rid of a line altogether. The good news is that deleting a line is just a keystroke away, and you don't have to select the whole line to delete the whole line.

Instead, you can leverage the L (for "L"ine) key: <Ctrl>_L cuts the line the cursor is on so that you can paste the line in somewhere else. The more deadly <Shift>_<Ctrl>_L completely deletes the line, but if you need to get the line back, you can still use undo. And if you want to delete (or cut) multiple lines, just select multiple lines before using <Ctrl>_L or <Shift>_<Ctrl>_L, and you still don't have to select whole lines.

Posted by Peter Vogel on 03/05/2014 at 9:17 AM0 comments


Adding Your Own Explicit Type Conversions in C#

In my previous tip, I showed how to add an implicit conversion to C#. But there are two rules you should follow when defining an implicit conversion: 1) An implicit conversion should never throw an error, and 2) It should never lose information. If neither of those conditions is true, you should declare the conversion as explicit, as this code does:

public class PremiumCustomer
{
  public string CustomerId {get; set;}
  public string Name {get; set;}
  public bool CanUseCredit {get; set;}

  public static explicit operator PremiumCustomer(DeadbeatCustomer dbc)
  {
    PremiumCustomer pc = new PremiumCustomer();
    pc.CustomerId = dbc.CustomerId;
    pc.Name = dbc.Name;
    if (pc.CanUseCredit != true)
    {
      pc.CanUseCredit = dbc.CanUseCredit;
    }
    else
    {
      throw new Exception("Can't convert DeadbeatCustomers with bad credit");
    }
    return pc;
  }
}

The code to convert a DeadbeatCustomer to a PremiumCustomer would need an explicit cast and look, like this:

DeadbeatCustomer db = new DeadbeatCustomer();
PremiumCustomer pc = (PremiumCustomer) db;

Posted by Peter Vogel on 02/28/2014 at 9:28 AM0 comments


Adding Your Own Implicit Type Conversions in C#

You may find that you have two classes that you frequently need to convert between. You could repeat the conversion code wherever you need it, or put it in some random class. Or you could add a new implicit conversion to one of the classes.

For instance, if you need to frequently convert a DeadbeatCustomer into a PremiumCustomer, just put the code inside a conversion method in the PremiumCustomer class that accepts a DeadbeatCustomer. To add a conversion method to a class, first define a public static method, followed by the implicit keyword, the operator keyword, and the method's return type. The method must accept a parameter of the type you want to convert. Here's the code for the DeadbeatCustomer to PremiumCustomer conversion:

public class PremiumCustomer
{
  public string CustomerId {get; set;}
  public string Name {get; set;}
  public bool CanUseCredit {get; set;}

  public static implicit operator PremiumCustomer(DeadbeatCustomer dbc)
  {
    PremiumCustomer pc = new PremiumCustomer();
    pc.CustomerId = dbc.CustomerId;
    pc.Name = dbc.Name;
    pc.CanUseCredit = true;
    return pc;
  }
}

This code will automatically invoke your conversion method and handle the conversion:

DeadbeatCustomer db = new DeadbeatCustomer();
PremiumCustomer pc = db;

Be warned, though: I've made some assumptions here that I'll return to in my next tip.

Posted by Peter Vogel on 02/25/2014 at 6:44 AM0 comments


Using LINQ with Collections that Don't Support LINQ, Revisited

In an earlier tip, I discussed how the OfType operator lets you run LINQ queries against collections that don't otherwise support LINQ. One reader of that column pointed out that, under the hood, a function named Cast was doing all the work. Another reader pointed out that what's special about OfType and Cast is that, unlike the other LINQ keywords, they work with collections that aren't generic types. Instead, OfType and Cast allow you to specify the type of the objects in the collection.

As an example of how to use Cast and OfType, imagine an ArrayList holding nothing but Customer objects:

Dim customers As New ArrayList
customers.Add(New Customer)
customers.Add(New Customer)

Both Cast and OfType will let you issue LINQ queries against the collection:

Dim custs = From c In customers.Cast(Of Customer)()
            Where c.CreditLimit = 0
            Select c

Dim custs = From c In customers.OfType(Of Customer)()
            Where c.CreditLimit = 0
            Select c

But what if the ArrayList contains a variety of objects? This collection contains both DeadbeatCustomer and PremiumCustomers:

customers.Add(New DeadbeatCustomer)
customers.Add(New PremiumCustomer)

Either Cast or OfType will let you work with this collection of diverse objects, but in very different ways. OfType will extract the objects of a specific type, so this example will process only the DeadbeatCustomer objects in the collection:

Dim custs = From c In customers.OfType(Of DeadbeatCustomer)()
            Where c.CreditLimit = 0
            Select c

Cast, on the other hand, will let you work with all items in the collection, provided they share an interface (i.e., inherit from some common base object or implement a common interface). This example assumes that both DeadbeatCustomer and PremiumCustomer interfaces both implement an interface named IBuyer:

Dim custs = From c In customers.Cast(Of IBuyer)()
            Where c.CreditLimit = 0
            Select c

So thanks, guys: This was your column. I'll send you a bill for writing it up.

Posted by Peter Vogel on 02/04/2014 at 3:23 AM0 comments


Progressive Server-side Validation by Group in ASP.NET

I didn't know this until my fellow instructor at Learning Tree (and author of Learning Tree's ASP.NET Web Forms course), Kevin Rattan, pointed it out to me: when you trigger validation at the server by calling the Validate method, you can pass the name of a Validation Group to the method. When you do, only those Validators you've assigned to that group (through the Validators' ValidationGroup property) will execute.

This allows you to check parts of your page for problems, and if you find a problem, skip validating the rest of the page. If you're using the UpdatePanel, you can trigger validation just for the controls in the panel that was posted back to the server.

Posted by Peter Vogel on 01/31/2014 at 7:45 AM0 comments


Version Control for Small Teams: Team Foundation Services

In an earlier tip, I suggested that in five or 10 minutes, you could set up a source control system for yourself by using Subversion; but what if you're part of a team? Even if every team member has their own source control in place (doubtful), you still want some central repository that represents your "gold" code. There is a simple solution and it's free, provided your project has five or fewer members: Team Foundation Service (Team Foundation Server in the cloud). While the TFS team says TFS will work with any editor, TFS integrates especially well with Visual Studio 2012 and 2013. If you're using Visual Studio 2010, you can still use TFS: just follow these steps, which includes installing a quick patch.

With TFS, you not only get cloud-based source control, you also get a central location to keep track of your team's work items (tasks and features), plus virtual meeting rooms if you're not all within driving distance of each other. Of course, if you get too dependent on TFS and add a sixth member to your team, you might have to buy one of Microsoft's plans or export your code and find a new provider.

Posted by Peter Vogel on 01/27/2014 at 9:16 AM0 comments


Eliminate Import Statements from Your Code in Visual Basic

A surprising number of Visual Basic programmers (i.e., more than one) aren't aware of a feature unique to their language: Project-level Imports. Namespaces added to the list of project-level Imports are, effectively, automatically added to the code files that make up your application --there's no need to add Import statements to the top of the code file for those namespaces.

You can add or remove project-level Imports by opening your Project's properties (right-click on the project in Solution Explorer and select Properties) and selecting the References tab. The list of project-level Imports appears at the bottom of the resulting form. Adding a namespace there means that you don't have to include it in your code file.

There is a wrinkle with using project-level Imports, however: If you remove the libraries whose namespaces are referenced in the Imports, your application will stop compiling. You'll need to track those Imports down and delete them. The good news here is that, instead of those Imports being scattered through your code files, they're all in one place -- though, perhaps, not an obvious place.

Posted by Peter Vogel on 01/23/2014 at 9:04 AM0 comments


Free Tool: WPF Performance Suite

I like Windows Presentation Foundation (WPF) very much, especially its implementation of the Model-View-Controller (MVC) design pattern. I've also grown to appreciate XAML as a declarative (if quirky) way of building complex user interfaces that integrate with a testable code file. However, every once in a while, I end up with a WPF Window that takes a long time to render, or renders in a bizarre series of jumps. If that's happened to you, it's worthwhile to download Microsoft's WPF Performance Suite.

The suite includes two tools: Perforator and Visual Profiler. Neither will tell you what to do to fix your problem, but both will help you locate the problem.

Perforator concentrates on the low-level routines that render your XAML. The download page for the package includes some useful information about the kind of values you should see with Perforator to help you figure out where your problem is. You can also experiment with various settings to see which (if any) will help with your problem.

While Perforator looks at how WPF is rendering your XAML, Visual Profiler shows how individual controls you've included in your XAML (Buttons, Lines and so on) are being rendered. In many ways, this is more useful to the developer: once you know what your problem controls are, you can focus on what's causing them to behave badly. The best solution may be to just do without them.

Posted by Peter Vogel on 01/13/2014 at 12:42 PM0 comments


Use Nested Classes to Organize Complex Classes

The ability to nest one class inside provides a powerful way to encapsulate code inside a class to organize complex functionality used within a single class. A nested class looks like this:

Public Class MyClass
  …code for the class…  

  Class MyNestedClass

  End Class
  
  Public Sub SomeMethod()
     Dim mnc As MyNestedClass
     mnc = New MyNestedClass()
     …using the nested class…
  End Sub

End Class

As the example shows, in the surrounding host class you can instantiate the nested class and use it. No other class, however, can access the nested class. Nested classes give you a way of organizing the functionality of the host class without exposing that functionality to other classes (or cluttering up your IntelliSense lists with new classes that are only useful in one place -- the host class).

For instance, in a recent application, I needed to manage the permissions and privileges for three levels of users in a form. I created a class for each type of user, with each class holding all (and only) the code for managing what that type of user was allowed to do. Any permissions-related code that was shared by all the users I put in a base class that the three user classes inherited from, giving me four classes altogether. This design cleaned up and organized my permissions code while simplifying the code in the host that set permissions in the form's user interface: the host class just instantiated the right nested class and called its permissions-related members.

Since these classes were only relevant to that single form, I nested all four classes within the controller for that form. With that design, code in the form could instantiate the nested classes and use their members, but the classes didn't appear in any IntelliSense lists outside of the host class.

If you do need to make a nested class available to the outside world, you can add a property to your host class that returns the nested class (as I did in a recent column on creating a fluent interface).

And, of course, you can argue that any class that needs nested classes is too big and too complicated, and is probably violating the Single Responsibility Principle. But that's a different discussion.

Posted by Peter Vogel on 01/09/2014 at 2:32 PM0 comments


Free Tool: ILSpy

If you miss the free version of Reflector now that Red Gate's taken it over, and if you don't appreciate the functionality that Red Gate has added to it, then ILSpy is for you.

ILSpy will decompile any .NET DLL back to either Visual Basic or C# (your choice), and provide a viewer that lets you browse the results. If you want to find out how the code behind the framework DLLs works (or if you've just lost your source code), ILSpy will let you see it. There are even a few plugins for ILSpy that enhance the basic package (and they're also free).

ILSpy doesn't provide the tight integration with Visual Studio (and Visual Studio debugging) that Red Gate's Reflector does, but -- did I mention this? -- it won't cost you a dime.

Posted by Peter Vogel on 01/08/2014 at 1:17 PM0 comments


Document Your Code with IntelliSense

Over a series of articles about commenting, I discussed why the key issue is to write ROC (Really Obvious Code). If you do, then the only comments you need to provide for your methods should be what parameters the method expects, what your method will do with those parameters, what the method will return, and any side effects of executing the method (e.g., database updates). If you bought into that plan (and some readers did not), then the best place to put that documentation is where Visual Studio will make the best use of it: in IntelliSense, by using XML comments.

To create the structure for your XML comments, click your mouse before your method declaration; then, in Visual Basic, type three apostrophes ('''); in C#, type three forward slashes (///). In either case, Visual Studio will add a framework to hold the comments for your method, for each of the parameters the method accepts, and for your method's return value (if any). All you have to do is type in your content.

Not only will the programmers who work on your code find all the information they need when changing your code, the developers who use your methods will find that IntelliSense delivers your documentation to them when they use your methods.

Posted by Peter Vogel on 01/07/2014 at 9:23 AM0 comments


Upcoming Events

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.