Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Tuesday, December 3, 2013

Adding Code Just for Debug Build with C#

It's very easy to add code that will only run for Debug builds for C# projects. The if directive is all you really need to know to do this.

Just add the following two lines to your source file:

#if DEBUG
#endif

You put the code that you want for the Debug build between those two lines. When you compile the project using the 'Debug' build configuration, the compiler will include the code between those two lines. Otherwise, they are ignored.

What if you want to include code for anything other than the Debug build? Just swap 'if DEBUG' for 'if !DEBUG' in the first line of code.

Troubleshooting

The reason why this works is that, by default, the Debug build configuration of a C# project defines the 'DEBUG' constant. If your debug-only code doesn't run when using a debug build, the problem might be in your build settings.

In Visual Studio:
  • Right-click the project that you're working on
  • Click 'Properties'
  • Click on the 'Build' tab
  • Make sure that the build configuration is set to Debug (using the dropdown menu that should be at the top of the build settings pane)
  • Make sure that 'Define DEBUG constant' is checked 
  • Save (Ctrl + S)

Making Your Own Special Build

Because this behavior only relies on C#'s #if directive and a preset DEBUG constant, you can easily use this to add code for any special build of your project. A good example of this is a 'Demo' build configuration. If you setup a Demo configuration for your commercial application, you can sprinkle #if directives statements throughout your code and get demo-specific (or retail-specific) functionality in your program.

The following how-to was written using Visual Studio 2013, but I think that it will work just fine if you're using VS 2008 or later.

1. Add Solution Build Configuration

This can be done through the Build > Configuration Manager... window. Click the 'Active solution configuration' then click '<New...>'. Give it a name like 'Demo'. You should probably copy settings from the Release build. Make sure that 'Create new project configurations' is unchecked unless you want to add one for each project. Click OK, but don't close the 'Configuration Manager' window.

2. Add Project Build Configuration

Look at the 'Project contexts' grid/spreadsheet. Click on the 'Configuration' cell for your project. Click '<New...>'. Give it the same name as your solution config, copy the Release build settings, and uncheck 'Create new solution configurations'. Click OK, but don't close the 'Configuration Manager' window.

3. Use the new project build configuration

Make sure that the 'Active solution configuration' is your new config (Demo).  Click on the 'Configuration' cell for your project and select your new project config. Close Configuration Manager.


4. Add the conditional compilation symbol

  • Right-click the project that you're working on
  • Click 'Properties'
  • Click on the 'Build' tab
  • Make sure that the build configuration is set to your new config (using the dropdown menu that should be at the top of the build settings pane) 
  • Type your new compilation symbol in the 'Conditional compilation symbols' text box
  • Save (Ctrl + S)
 

5. Use your new compilation symbol in code

If you're using 'DEMO' as the compilation symbol, sprinkle these two lines throughout your code to write build-specific code.

#if DEMO
#endif

Friday, November 15, 2013

Getting Started with KSMVVM.WPF Part 2: Messaging

(This is part 2 of 2 in a series about getting started with KSMVVM.WPF)

At the end of Getting Started with KSMVVM.WPF, we successfully converted our SampleApplication to use ViewModels. However, one of our ViewModels still has UI-specific code in it. If we write and run automated ViewModel tests, testing FormViewModel.Submit will show a MessageBox. This is not good!

KSMVVM.WPF has a messaging component, and we'll use its BasicMessager class to move the call to MessageBox.Show out of FormViewModel.

Thursday, November 14, 2013

Getting Started with KSMVVM.WPF

KSMVVM.WPF is a 'kinda small' Model-View-ViewModel framework for Windows Presentation Foundation (WPF) that I released earlier in 2013. It's a little different than other micro-MVVM frameworks because it was specifically designed for migrating existing code-behind WPF applications to MVVM.

Some nice features of KSMVVM.WPF include:
  • Functionality to allow ViewModels to control program navigation (in a manner to allow for automated tests)
  • Lightweight, easy-to-use string-based messaging
  • Two ICommand implementations; a 'hack' one for existing apps, and a 'non-hack' one for new apps
This 'getting started' guide will illustrate use of KSMVVM.WPF in an existing WPF application. This guide assumes that you are using a recent version of Visual Studio (or VS Express) with built-in NuGet functionality. I'm actually using VS Express for Desktop 2013 RC for this tutorial.

The tutorial continues after the page break.

Thursday, September 12, 2013

Skippable - Skip UI-specific Code During .NET VM tests

KSMVVM.WPF, my "kinda small" MVVM framework for WPF, used to have a class named Skippable. Its purpose was simple: to allow the inclusion of UI-specific code inside of a View Model and have it be skippable for unit tests.



How to Use Skippable

Call Skippable.Do(func) in your View Model code and place UI-specific code in func.

Wrap your View Model unit test code in a using(Skippable.Skip) block.

Why Was It Removed?

Before I added a messaging class to KSMMVM.WPF, Skippable was the only built-in way of triggering a change in the UI that could not be prompted through binding alone. For example, calls MessageBox.Show() were intended to go inside of a Skippable() block until the program transitioned to a MVVM framework with messaging capability.

I realized that Skippable encouraged poor programming practices. MVVM is all about separation of concerns, and Skippable violates that separation by allowing 'View code' in the View Model. It also requires tests to know if something uses Skippable.

Skippable was meant to help programmers transition WPF code from code-behind to a proper MVVM framework, but it did a grave disservice to developers who 'stick' with KSMVVM.WPF.

Sunday, May 19, 2013

.NET Debugging Tips

In my three years of professional coding experience, I have fixed many problems in .NET programs and unit tests. One example of this is a WPF problem that ultimately involved a faulty GetHashCode() implementation. Most of the problems that I have faced involve NullReferenceExceptions, off-by-one errors, bad regular expressions, and "normal" stuff like that. I've fixed some major concurrency-related issues and even a bug that took 13 steps to re-produce. I don't have a decade of experience, but I know a thing or two about debugging .NET code.

(I) Don't Rely on Breakpoints

Visual Studio has excellent support for breakpoints, but I rarely use them. Removing a breakpoint can be a time-consuming process if you want to leave other breakpoints enabled. They also stop the program entirely, and I've seen cases where breakpoints prevent concurrency issues from being re-produced.

I use breakpoints only when I need to look at local variables in a buggy piece of code. Otherwise, I just sprinkle Debug.WriteLine statements when needed. I can act on Debug info faster than I can a breakpoint, and the program doesn't stop for seconds while printing debug statements.

There is one major disadvantage to using Debug.WriteLine: you have to alter source code to use it. Please do not commit code with Debug statements that you don't plan to keep. Every version control system that I know of has a diff support, and you should check these diffs when you commit code.

(I) Have Plenty of Unit & Integration Tests

I am a big proponent of unit & integration testing. I feel that good tests help developers figure out what isn't causing a problem before they start. Automated testing is not the end-all, be-all of bug prevention. You'll miss edge cases, and there's no way (that I know of) to detect weird GUI-related issues before you stumble upon them. Tests are merely good tools.

If you are able to, I highly recommend writing integration tests. In past endeavors, I had to mock everything out to such an extent that real-world issues (like a missing table, column, or bad parameters) would not be detected until the manual testing phase. My software uses SQLite, and I write tests that write data to real SQLite database. These integration tests helped me write persistence code that didn't easily break.

While debugging, I try to write unit & integration tests that cover the bug. This helps me debug the problem and ensures that the exact same problem does not return in future code revisions.

Rules of Thumb

Common NullReferenceException causes

When my code throws a  NullReferenceException, it's usually one of two things:
  1. I forgot to check a parameter or property for null
  2. Type cast returns null (and I forgot to check for null)

Silently handling exceptions is bad

Silently handling exceptions silence major problems with your code. It also makes your code harder to debug. I highly recommend not writing error-handling code that does nothing.

Of course, I've written error-handling code that basically does nothing. The hack was very well documented to indicate why I was silently handling exceptions, and I didn't catch Exception. That's bad because StackOverflowException and OutOfMemoryException exist.
 
On a related note, catching an exception and throwing a new one can hide the true source of the exception.

 It's probably your regular expression

If a regular expression can be the cause of a problem, it probably is! This isn't a knock against regular expressions, as they can be very useful for validating certain types of input. It's just tough to write one that works all of the time for all cases.

Thursday, May 16, 2013

Identifying WPF BackStack Entries

Frame.BackStack is a useful property in WPF applications: it's an IEnumerable for a frame's navigation history. In my experience, these back entries tend to be JournalEntry instances. JournalEntry.Name can help you find what Page is represented by the JournalEntry, but it is a little tricky to use in practice. Name can be one of four things:
  1. The attached Name attribute.
  2. Title.
  3. WindowTitle and the uniform resource identifier (URI) for the current page
  4. The uniform resource identifier (URI) for the current page.
(Source: JournalEntry.Name documentation on MSDN)

If you set x:Name for a page, the corresponding JournalEntry.Name will be that x:Name. Doing this allows you to (somewhat) reliably identify the JournalEntry's page.

Thursday, March 21, 2013

I Like AngularJS (So Far)

I am building a commercial web app using AngularJS that is currently around 3000 lines of JavaScript code (including comments and spacing). I like AngularJS and I'll tell you why.


Monday, January 14, 2013

How-to Launch a Program with SingleAppLauncher

I recently released SingleAppLauncher. It's a tiny .NET program that runs the latest installed version of a single application. If your program automatically updates, this allows for easier program updates.

Here's a quick guide of how to use SingleAppLauncher in your application.

Directory Layout and Configuration

SingleAppLauncher requires a specific directory layout in order to work properly. It must be placed in the root directory of an application, and each program directory (with the .exe to launch) must be a version number. Here's an example adapted from SingleAppLauncher's readme:

C:\App\
  • app.exe (SingleAppLauncher)
  • app.exe.config (SingleAppLauncher's configuration file)
  • 0.91\
    • program.exe
  • 0.92\
    • program.exe
    SingleAppLauncher can be configured in two different ways: configuration file and command-line arguments. For the sake of simplicity, this guide will only cover the configuration file. Here's an example (as a Github Gist):



    In this example, launching 'app.exe' (in C:\App\) will launch C:\App\0.92\program.exe. As of this writing, the version folder names must be exact version numbers according to the .NET Framework's Version class. For example, if the 0.92 version folder was named 'v0.92', SingleAppLauncher will launch '0.91\program.exe'. If both folder names have 'v' at the beginning, SingleAppLauncher will crash.

    Launching Your Program From a Shortcut

    Just have your program's shortcut point to SingleAppLauncher: it will take care of the rest. You should change the shortcut to use your program's icon.

    Including SingleAppLauncher With Your Program

    SingleAppLauncher is released under a permissive license, allowing you to bundle it with commercial and non-commercial software.

    I currently do not distribute SingleAppLauncher in binary form, and (for right now) you should clone the repository from GitHub and build SingleAppLauncher when you build your program.

    SingleAppLauncher currently requires .NET 4.0 to be installed on the build system as well as the client system.

    Wednesday, December 26, 2012

    ServiceStack and jQuery Problems

    I'm currently working on a website that uses ServiceStack, and I ran into a problem where complex request objects were not properly created when making requests in-browser using jQuery. Simple (flat) requests worked as expected, but complex requests (with nested objects) led to various null-related errors coming from the service implementation. My unit tests worked fine, but I could not access the 'complex' service within a web browser.

    My problem seemed to be with my client-side JavaScript code. I was writing code similar to the following:
    
    // Bad example - DO NOT FOLLOW
    $.ajax({
        url: '/url/',
        data: { 'Data': properties },
        type: 'PUT'
    }).fail(function() { alert('Oh no'); });
    
    
    I changed a few lines of code, and everything began working as expected.

    
    // Better example - could probably do better
    $.ajax({
        url: '/url/',
        data: JSON.stringify({ 'Data': properties }),
        contentType: 'application/json',
        type: 'PUT'
    }).fail(function() { alert('Oh no'); });
    

    This version of the AJAX call specifies content type and uses a JSON string for the data.

    According to the jQuery documentation for the ajax function, the default content type is ''application/x-www-form-urlencoded; charset=UTF-8". This default is inappropriate for this particular use case.

    The call to JSON.stringify is also important because jQuery's .ajax() function does not convert the data for you.

    Sunday, August 26, 2012

    WPF DataGrid and 'Random' ArgumentException

    WPF's DataGrid class seems to have an odd problem. If you put a DataGrid in a ScrollViewer, and if you bind a collection of a type with a specific kind of GetHashCode() implementation, and if you edit data in the grid twice, an ArgumentException will likely be thrown by clicking the data grid a third time. I say "likely" because it sometimes didn't occur on the third attempt. Here's an example stack trace:



    I could not find source code for InternalSelectedItemsStorage's constructor, but it probably calls GetHashCode() to generate a dictionary key. The DataGrid problem is resolved by changing the GetHashCode() implementation so that it gives the same return value even if the name or price of an object changes.

    Here are two examples (one bad, one better) of GetHashCode() implementations.



    Friday, November 18, 2011

    SharpDevelop – Code Coverage Issue Involving VerificationException

    I recently encountered a hard-to-debug issue with SharpDevelop that caused one of my unit tests to fail only when code coverage is enabled. The test failed with the following exception:

    System.Security.VerificationException : Operation could destabilize the runtime.

    The method being tested uses Microsoft.VisualBasic.TextFieldParser to parse CSV. I dug around and determined that the exception seems to be thrown within TextFieldParser’s constructor.

    The Solution


    The fix is easy: just add a PartCover exclusion. In SharpDevelop (4.1), this can be done by going to the Test project’s properties, clicking on ‘Code Coverage’, and adding the following to the Exclusion text box:

    [Microsoft*]*

    A Bit of Explanation


    SharpDevelop’s preinstalled code coverage tool uses PartCover. It seems that VerificationException is thrown when PartCover attempts to track code coverage in an assembly decorated with System.Security.AllowPartiallyTrustedCallersAttribute. Apparently, the assembly where TextFieldParser is defined (Microsoft.VisualBasic.dll) is decorated with this attribute.

    Resources


    I learned about PartCover exceptions and default exceptions from this introduction to PartCover.

    PartCover’s maintainer asked a question on StackOverflow that pointed me in the right direction when I was doing some research on why this problem occurs.