Make Sure You're Compressing What You Send to the Browser

This is really a tip for IIS 7 (or later) Web site administrators than it is for developers: Make sure that you've looked at how you're using urlCompression your site. urlCompression ensures that, when the browser supports it, your Web pages and static resources (PDF files, for example) are compressed before being sent to the user. This can reduce the amount of bandwidth used on each user request.

There are three compression options and, since IIS 7.5, the most useful one (dynamic compression, which compresses your Web pages) should be turned on by default. Having said that, I had a client running IIS 10 where even that option was turned off. You probably want to ensure that dynamic compression is turned on and, if your users download a lot of files from your site, that the other choices are turned on also.

However, there are a number of options to manage here and the highest compression settings aren't necessarily the best ones (higher compression settings require more processing time and the savings in bandwidth might not compensate for that processing time). In fact, if you're tight on CPU cycles but have lots of network bandwidth to spare you might actually be better off by not using compression. The best discussion that I've found about the various tradeoffs is here (though the post is rather old).

Posted by Peter Vogel on 08/25/2016 at 12:42 PM0 comments


Visual Studio Toolbox Shortcuts: Expand, Collapse, and Find

With the rise of ASP.NET MVC, the role of the visual designers that were so much a part of creating UIs have diminished and that's too bad. If you're using one of the UI development technologies that give you a Visual Designer with toolbox, here are three tips you might not know to make working with your toolbox easier. After clicking on the toolbox (or otherwise making it active), if you type

  • An asterisk (*), you'll expand all of the sections
  • A forward slash (/), you'll collapse all of the sections
  • Any alphabetic characters, you'll start a search for widgets with matching names (Even if there isn't a search box at the top of the toolbox)

With the search option, once you find a matching widget, pressing the Tab key will move you to the next matching entry. If your toolbox doesn't have a search box at the top, you can see what you've typed in the status bar at the bottom of the toolbox.

Posted by Peter Vogel on 08/12/2016 at 4:36 PM0 comments


Add an Error Handler to Your ASP.NET MVC Controller

There really isn't such a thing as an "unhandled error" -- if your code throws an error outside of a Try...Catch block, then your error bubbles up through various ASP.NET and .NET Framework error handlers. An "unhandled error" is just an error that you aren't handling.

In ASP.NET MVC you can handle more errors by inserting an error handler inside your Controller: Just add an OnException method to your Controller. The code in this method will be invoked each time you have an "unhandled error" in that Controller.

It's easy to add the method: In your Controller, just type Overrides (in Visual Basic) or override (in C#), press the Tab key to get a list of overrideable methods, pick OnException from the list, and press the Tab key again. Visual Studio will write out the skeleton of the method for you.

The Visual Basic version looks like this:

Protected Overrides Sub OnException(filterContext As ExceptionContext)

End Sub

Your method will be passed an ExceptionContext object whose Exception property will give you access to all of the information about what went wrong. Within your OnException method you can do whatever you want about the error that's specific to the Controller (log to some audit file, for example). If you take no further action, the error will continue to bubble up to the ASP.NET error handler.

If, however, you wanted to finish by using the RedirectToRouteResult method built into your Controller to send the user the error page of your choice then you need to stop that bubbling process. You can do with this line:

filterContext.ExceptionHandled = True

which sets the ExceptionContext object's ExceptionHandled property to True.

Posted by Peter Vogel on 08/09/2016 at 2:03 PM0 comments


What Version of ASP.NET MVC Are You Using?

Prior to the pause in releases triggered by the latest structural changes to the .NET Framework, it seemed like the ASP.NET MVC team was releasing a new version in any month whose name ended with a letter. As a result, you could easily find yourself supporting multiple applications, each with its own version of ASP.NET MVC. Alternatively, you might have just taken over support for an ASP.NET MVC application and be wondering what version your application is using.

As an independent contractor, often faced with an application I've never seen before, I figure out the version by opening the Web.config file and doing a search on "System.Web.MVC". This is the element I currently find:

<dependentAssembly>
  <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
  <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
</dependentAssembly>

with the version number in boldface.

Posted by Peter Vogel on 07/29/2016 at 9:46 AM0 comments


Including the Location of Your Error in Your Error Message

A user calls you to complain that your code has thrown an exception. You ask the user to read the message to you … and you realize that you have no idea where that error comes from. You would know if you'd included the Exception object's TargetSite property in your error message because that property reports on the method that had the problem.

The TargetSite property returns a MethodBase object (part of .NET's Reflection infrastructure) which has a ton of properties telling you everything you'd ever want to know about the method. However, all you probably want in your error message is the method's full name, including the name of the class. To get that, just call the TargetSite's ToString method:

Try
  ' ... potential exception
Catch ex As Exception
  Throw New Exception("Something has gone horribly wrong at " & ex.TargetSite.ToString)
End Try

One caveat: If you're still embedding class and method names in your ASP.NET MVC routing rules then the class name/method name is information you probably don't want to share with your users (though you still might want to write those names to some log). Fortunately, I discussed how to avoid embedding controller and method names in your UI in my previous tip which makes that problem go away.

Posted by Peter Vogel on 07/22/2016 at 9:49 AM0 comments


Write to Visual Studio's Output Window on Your Breakpoints

I can't tell you the number of times I've put a breakpoint inside a loop so that I could stop each time I go through the loop and check the value of some variable or property. Unfortunately, by the third or fourth trip through the loop I've forgotten what the values were on my first trip through the loop.

If that's your life also, your best choice is to use a tracepoint which will write the information you're interested in to the output window. With a tracepoint, you can review the values you're interested in after the loop finishes. You can even just let your code run, rather than stopping on the line you're interested in.

Setting a tracepoint varies from one version of Visual Studio to another. The easiest way is to set a breakpoint and then right click on the dot in the margin that marks your breakpoint. When the popup menu appears, either select the When Hit choice (in earlier versions of Visual Studio) or the Actions choice (in later versions). Those choices will display the dialog that lets you define your tracepoint.

In that dialog you can enter the message you want written to the output window, enclosing any variables you want displayed in curly braces ({ }). Something like "The counter is {i} and the Customer's age is {cust.age}" will work, for example.

If you'd rather not stop on the breakpoint, make sure the Continue Execution checkbox at the bottom of the dialog is checked. You can do a quick visual check to see if you'll be stopping on the line: If you still have a dot in the margin, it's still a breakpoint and you'll stop every time the line is hit; if you have a diamond in the margin, it's a tracepoint and will just write out your message without pausing.

Now run your application and, after it finishes, look in the output window to see how your data changed over time.

Posted by Peter Vogel on 06/23/2016 at 11:40 AM0 comments


Save Some Time Deleting Entities in Entity Framework: RemoveRange

When it comes to speeding up your application, your best opportunity is to reduce trips to your database. So, when you see a method like RemoveRange on a DbContext collection, you might think that's an opportunity to delete a bunch of objects in less time than deleting those same objects one by one. You'd be right…but not because you're saving trips to your database.

Here's some sample code that will delete all of the SalesOrderHeaders with a DueDate before the current date:

Dim res = From so In db.SalesOrderHeaders 
          Where so.DueDate < DateTime.Now 
          Select so 
db.SalesOrderHeaders.RemoveRange(res)  
db.SaveChanges

This will run faster than, for example, looping through the res collection and passing each object to the SalesOrderHeaders Remove method before calling SaveChanges. However, either way, you'll still be making one trip to the database, submitting one SQL delete statement for every SalesOrderHeader that's being deleted.

Where you'll save time is in the overhead around removing the objects from the SalesOrderHeaders collection (especially around change tracking which will run once with RemoveRange rather than once for each object with Remove).

Posted by Peter Vogel on 06/21/2016 at 12:56 PM0 comments


Save a Trip to the Database with Deletes in Entity Framework

In both deletes and updates there's an assumption that you have to retrieve the corresponding entity object from the database. With an update, you pull back the object so that you can set its properties; with a delete, you retrieve the object so that you can pass it to the corresponding collection's Remove method. That delete code might look like this, for example:

Dim cust As Customer
cust = db.Customers.Find("A123")
db.Customers.Remove(cust)
db.SaveChanges

You don't have to actually need to make that first trip to the database. For a delete, for example, all you have to do is convince Entity Framework's change tracking mechanism that you've deleted the object ... and that just means that you have to remove an object with the right values in the primary key properties. This code, for example:

Dim cust As New Customer
cust.CustId = "A123"
db.Customers.Attach(cust)
db.Customers.Remove(cust)
db.SaveChanges()

will delete Customer A123 from the database without having to retrieve it.

Posted by Peter Vogel on 06/03/2016 at 12:33 PM0 comments


Convert a List from One Type to Another

You have a List of one object but you really want to have a List of some other object. If it was a single object, you could cast from one to the other with a single line of code:

Dim pCust As PremiumCustomer = New PremiumCustomer
Dim cust As Customer 
cust = pCust

But, because you have a collection of objects, you might assume that you have to write a loop and transfer your objects from one List to the other individually. The good news is that you can do that in one line of code using two LINQ functions: Cast and ToList. Here's the one line solution that creates a list of Customers from a list of a derived class, PremiumCustomers:

Dim pCusts As List(Of CustomerPremium) pCusts = GetPremiumCustomers()
Dim custs As List(Of Customer)
custs = pCusts.Cast(Of Customer)().ToList()

Unlike some "clever" LINQ solutions this one is, I think, actually readable. Under the hood, of course, that loop is probably still being created by LINQ and the compiler…but you don't have to write it. Besides, with this single line of code, the compiler might even be able to invoke some clever optimization to speed up the process.

I didn't come up with this myself: If you're interested there are six more useful LINQ tips where this one came from, all thanks to Igor Ostrovsky.

Posted by Peter Vogel on 06/01/2016 at 11:51 AM0 comments


Organize Classes into Folders in Class View

It doesn't show often in the columns I write here, but I'm a big fan of organizing large projects into files. You can, of course, create those folders in Solution Explorer, which adds the folders to your file system.

But, if you use Class View, you know that your Solution Explorer folders don't show up there. As the number of classes in your application starts to increase, the usefulness of Class View starts to diminish. If you want, though, you can also organize Class View into folders … and those folders don't have to match your Solution View folders.

It's not obvious how to do this -- right-clicking in Class View and picking Add from the submenu won't give you a folder option, for example. Instead, you need to click the Add Folder button in the top left-hand corner of Class View. Once you've created your folder, you can drag classes into it (still in Class View, of course). You can also create subfolders (right-clicking on a folder will give you a New Folder option).

These folders only exist in your solution's information file (the .sou file) and aren't added to your file system.

Posted by Peter Vogel on 05/20/2016 at 1:03 PM0 comments


Changing Parameter Values with out and ref

By default, any values that you pass to a method in a parameter are protected from change inside the method. In this code, for example, I know that my variable NotChanged can't be different after I call the method. In this code, the test on the last line is guaranteed to be true:

string NotChanged;
NotChanged = "Fred";
MyOrdinaryMethod(NotChanged);
if (NotChanged == "Fred") ...

That is, unless the parameters to the method are marked with the ref keyword, as in this example:

void MyRefMethod(ref string parm1)
{

Now, if I call this method the value of anything that I pass to that first parameter could be different after calling the method. To make sure that I realize that possibility, the compiler also requires that the calling code use the ref keywords. In this code, the test on the last line is not guaranteed to be true and, thanks to having to provide the ref keyword, I know that:

string PossiblyChanged;
PossiblyChanged = "Fred";
MyRefMethod(ref res);
if (PossiblyChanged == "Fred") ...

While a parameter marked with the ref keyword may or may not be changed, the out keyword is more definite: The out keyword indicates that code inside the method will always change the value in the parameter. If you mark a parameter as out and there is a path through your method that doesn't alter the value of the parameter then the compiler will generate an error.

In addition, with the out parameter, the compiler will refuse to compile your method if, inside your method, you attempt to use the out parameter without first setting its value. In other words, when calling a method with an out parameter, the calling code can set the value of the parameter before passing it to the method -- but it won't do a bit of good because the method has to override that value before it can use the parameter. Again, because I have to use the out parameter when calling the method, I know that:

string DefinitelyChanged;
MyRefMethod(out DefinitelyChanged);
if (DefinitelyChanged == "Fred") ...

That's it for now, I'm out.

Posted by Peter Vogel on 05/05/2016 at 9:37 AM0 comments


Set Culture Information in One Step in .NET Framework 4.5

In the .NET Framework 4.0 or earlier, you have to set the culture for each thread individually. At the very least, this meant setting the CurrentThread object's CurrentCulture and CurrentUICulture properties. In the .NET Framework 4.5, you can do it in just two lines of code for every thread in your application, using the CultureInfo object.

The syntax is a little "un-obvious": You must first instantiate a CultureInfo object, passing a culture code. You then pass that object to a static method called DefaultThreadCurrentCulture, also on the CultureInfo object.

Typical code looks like this:

Dim ci As CultureInfo
ci = New CultureInfo("en-CA")
CultureInfo.DefaultThreadCurrentCulture = ci

which sets the culture code for all threads to English/Canadian.

Posted by Peter Vogel on 05/03/2016 at 10:19 AM0 comments


Upcoming Events

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.