What developers like to do best is to write code (and design the applications that will let them right code). Administrative overhead just gets in the way of writing code—even something as simple as a To Do list. Yet developers are constantly getting part way through a problem and having to go and work on something else, or to address another part of the application before returning to finish what they were working on.
The Visual Studio Task List actually helps with this. Just type a comment that begins with ToDo (e.g. 'ToDo or //ToDo) and is followed by some text, and a line with your text appears in the Task List. To see the Task List, from the View menu, and select Task List. When the Task List window displays, switch the drop down list at its top to Comments. Once you see the list of notes that you (or someone else) has left on the Task List, double-clicking on an item in the list takes you to that section of your application.
In addition to ToDo, there are two other tokens: HACK (for…) and UNDONE (for…). However, if you (or your team) wants to mark additional types of material, you can create your own custom tokens. Select Options From the Tools menu, and in the Options dialog, expand the Environment node to find the Task List entry. Enter a name for your token in the Name text box and click the Add button to define your token (if your token will be used in a case-sensitive language, make life easy for the token's users by making the name either all uppercase or all lowercase).
Unfortunately, there's no easy way to share custom tokens among a team. You can export your settings (which include custom tokens) into a file so that other developers can import your custom tokens…but it's probably just as easy for each developer to set up any new tokens you invent in their copy of Visual Studio (besides, then the developer will know what tokens are available).
Visual Studio 2010 displays all your tokens when you open a project -- earlier versions wouldn't populate the Task List until you opened the file containing the token. However, in earlier versions of Visual Studio, if you do a Find and Replace replacing "ToDo" with "ToDo" and click the Replace All button, Visual Studio would find all of the files containing a ToDo token and open them for you, updating the Task List as it goes.
Posted by Peter Vogel on 01/30/2012 at 1:01 PM0 comments
In a previous free tool
column, I recommended WoVS Default Browser Switcher, which provides an easy way to change your default browser when testing ASP.NET pages. However, browsers are only one kind of user agent that can access your page (I do some search engine optimization work -- primarily for professional companies like law firms -- so working with search agents is important to me).
In a Practical .NET column, I discussed Microsoft's recent updating of the file that ASP.NET uses to determine the capabilities of the browser requesting your site and how you could mock that component to test against how your site behaves with different user agents.
My friend Kevin Rattan (who writes on Learning Tree's Perspectives on Programming in .NET) pointed out a cool tool: Chris Pederick's User Agent Switcher. User Agent Switcher is a Firefox add-in that basically causes Firefox to lie about itself and represent itself as a different browser…or even as a search 'bot or an iPhone. It adds a new menu and toolbar button to Firefox to let you change how Firefox represents itself to your server. You can either switch Visual Studio over to using Firefox for testing, or just keep Firefox open and aimed at your site to see your site as a search 'bot sees it.
Posted by Peter Vogel on 01/30/2012 at 8:59 PM0 comments
By default, ASP.NET pages post their data back to themselves. However, there are cases that, when the user clicks on a button, you want the data in the browser sent to some other page. For instance, if you have an option that lets users search the site, you've probably implemented this with a Search button with a text box on every page on your site. When the user enters some text and clicks on the button, you want to send the user to your site's Search page, not back to the current page—and you also want to send to that page whatever search term the user entered in the text box beside the button. The same is true of a Help button with a text box: When the user clicks the button, you want to send the user to a page that displays help about the topic the user entered into the text box.
In ASP.NET, sending the data on a page to another page is called cross-page posting. It's controlled through a property on the ASP.NET Button. To turn on cross-page posting, set the button's PostBackUrl property to the URL of the page you want the data sent to (e.g., your search or help page).
However, when you arrive at the other page, you'll need to retrieve the value that the user entered in the search or help text box. Since you're now on a different page, the user's data won't be nicely slotted into a control on the form—you'll have to hunt for the text box. And, since the user can come to a page through many ways (the user may have bookmarked your search page, for instance, and used the bookmark to get to the page) you don't want to hunt for the text box unless you know it's there.
The Page Load event is a good place to put that code. You should begin by determining if the user has arrived at your page through cross-page posting. The first step is to check to see if the page's PreviousPage property is set: If the user came to your page through cross-page posting, PreviousPage will be set to something.
However, PreviousPage will be set in at least two scenarios: if the user arrived at the page using cross-page posting, or if the user arrived through using Server.Transfer. So, once you know that the PreviousPage property has something in it, you should check its IsCrossPagePostBack property to see if user got there through a click on a postback button. The code looks like this in Visual Basic:
If Me.PreviousPage IsNot Nothing AndAlso _
Me.PreviousPage.IsCrossPagePostBack = True Then
The next step is to find your textbox. For that you can use the PreviousPage's FindControl method, passing the Id of the TextBox you're looking for. You'll need to cast the result to the correct object type (and you should also deal with not finding the text box in case some other developer builds a page that posts to your search or help page):
Dim txt As TextBox
txt = CType(Me.PreviousPage.FindControl _
("SearchTextBox"), TextBox)
If txt IsNot Nothing Then
RetrievedString = txt.Text
End If
Finding the text box is a little more difficult if your control is inside a naming container like a Content control or a FormView.
It wouldn't be surprising if your cross-page posting button is part of your site's Master Page (a Help or Search button would, typically, be something that you'd want on every page on the site). Fortunately, you can search a PreviousPage's Master page through its Master property, like this:
Dim txt As TextBox
txt = Me.PreviousPage.Master.FindControl( _
"HelpTopicTextBox"), TextBox)
Posted by Peter Vogel on 01/13/2012 at 11:56 AM3 comments
When I tell people what I like about productivity tools like ReSharper and CodeRush (among others), I always mention their support for automatically adding references and adding imports for namespaces when I type in a class name. The Clarius team, through World of Visual Studio (WoVS), has a free add-in that does that also. But sadly, I was only able to get it to work for C#.
Here's what happens: You type in a class name that Visual Studio doesn't recognize because you don't have the right imports/using statement at the top of your file; or worse yet, you haven't added a reference to the library to your project. You get the red wavy line and the error tooltip says that the type or namespace can't be found.
Here's what you do: Click at the front of the class name to get the error correction dropdown list. Provided you've spelled and capitalized the class name correctly, you'll have a new choice at the bottom of the dropdown list. That new choice automatically adds a reference to the library you need (there may be multiple entries if the class name appears in several libraries) and then goes on to insert the necessary using statement at the top of your file. To put it another way: One click and your code will compile.
The tool is even easy to install -- you can get it from Visual Studio's Extension Manager. The only downsides? As I said, it only works for C# and, I'm told by some international friends, only if Visual Studio is running in English. Plus, of course, I'll no longer know the namespace or library for any class that I'm using. It turns out that I'm OK with that last one.
Posted by Peter Vogel on 12/14/2011 at 9:24 AM1 comments
You have a method that returns multiple values. So you have to define a class, instantiate it, set the properties to the values, and return the resulting object, right? Well, no you don't -- at least in .NET Framework 4, which gives you a simpler way: Tuples.
A Tuple can hold up to eight values (including classes) and can be created on the fly. To declare and instantiate a Tuple that could hold two values (one string and one integer), you'd use code like this:
Dim tup As New Tuple(Of Integer, String)
When you instantiate a new tuple, you also pass the values that will be put in the Tuple. So instantiating the Tuple and putting the number 2 and the string "fred" in it would require this code:
Dim tup As New Tuple(Of Integer, String)
(2, "fred")
There's no need to define a special purpose class to return some arbitrary collection of values.
Here's a more useful example: A method that returns a List of Customer objects. However, the method also returns an error code and a human-readable error message. Rather than defining a class, the code just declares a Tuple with an integer, a string, and List of Customers:
Function ReturnData(Region As String) _
As Tuple(Of Integer, String, List(Of Customer))
Dim cust As Customer
Dim lst As New List(Of Customer)
Dim errorCode As Integer
Dim errorMessage As String
'code to add customers to lst and catch errors
Dim tup As New Tuple(Of Integer, String, List(Of Customer))
(errorCode, errorMessage, lst)
Return tup
End Function
The code that calls this method would use Item* properties on the Tuple to access the values. A Tuple, like this one, with three items stored in it will have properties called Item1, Item2, and Item3 (and all the properties will have the right data type).
To call the method, check for an error, and either display the error message or process the Customers in the list if everything works right, you'd write code like this:
Dim retData As Tuple(Of Integer, String, List(Of Customer))
retData = ReturnData("NA")
If retData.Item2 < 0 Then
MessageBox.Show(retData.Item2)
Else
For Each cust In retData.Item3
'process Customers
Next
End If
Editor's Note: This article has been updated to reflect that Tuples can hold up to eight values, not four.
Posted by Peter Vogel on 12/08/2011 at 5:46 PM14 comments
Sometimes, in debug mode, you find yourself sitting on a line in a method that you have no interest in. What you actually want to do is to get back out of the method and stop in some method you've already passed through. Of course, if you just want to get back to the method that called the code you've stopped in, you can use Step Out (Ctrl+Shift+F8). But if you're more than one level deep, getting back to someplace useful can be painful.
In a recent article on the debugging tools available in Visual Studio, I described the benefits of the Breakpoint window. What I didn't talk about was the Call Stack window which lets you stop in any method that you passed through on your way to the current line of code.
To use the Call Stack window, after you've stopped on a line, first bring up the window: either use the menu choice Debug | Windows | Call stack or use the distinctly un-intuitive Ctrl + L (in Visual Studio 2010). That will give you a window with a list of methods executed on the way to the line you've stopped at.
The method you're stopped at appears right at the top of the window. Listed below that line are the methods you passed through on the way to this line of code. Now just right-click on one of those methods and select Run to Cursor (or select the method and then press Ctrl+F8). Your code will execute until control returns to the method you've selected in the Call Stack. Once you've stopped there, you can treat it like any other breakpoint.
If you want to set something more permanent, after selecting a method in the Call Stack, use F9 (or Debug | Toggle Breakpoint) to set a breakpoint on the method.
Posted by Peter Vogel on 11/29/2011 at 8:16 AM2 comments
Time was, I only worked on intranet projects because my clients could control the browser that users accessed the site with. This meant that the testing cycle for any project was relatively short: We only had to test the site with the "approved" browser. However, as browsers have become more compliant to standards—and as the economy has retracted—testing cycles for Internet applications have gotten shorter and I've started working on Internet projects. That change means that I need to be able to test my client's sites in multiple browsers.
Just released on October 1st 2011, the WoVS Default Browser Switcher add-in (available from Visual Studio's Extension Manager) gives you the Default Browser Switcher toolbar. The toolbar hosts an icon for each of the major browsers (any browsers not installed on your computer have their icons disabled). Clicking on the icon for a browser makes that browser the default for Visual Studio and, as a result, the one used next time you test your application.
If you don't want to add another toolbar to your Visual Studio interface or just want to test a page in a particular browser without changing your default settings, the add-in also adds a new "View in browser" submenu on the context menu for an ASPX page. That submenu lets you select the browser you want to view the page in without whacking your default settings.
Posted by Peter Vogel on 11/16/2011 at 12:28 PM3 comments
This week's tip comes from Bobby Orndorff of GrapeCity software. He's the Chief Architect for Spread.NET, and implemented the Spread Calculation Engine and the Chart component.
Floating point numbers have limited precision. This can lead to small approximation errors in calculations which, in turn, can cause unexpected results when comparing calculation results. For example, consider the following C# code, which multiples a number by its multiplicative inverse and then compares the calculated result with the expected result of one.
double x = 49.0;
double y = 1 / x;
double calculatedResult = x * y;
double expectedResult = 1.0;
bool areSame = calculatedResult == expectedResult;
We would expect areSame to be true, because the product of a number and its multiplicative inverse should always equal one. However, areSame will be false in the above code. The problem is that 1/49 cannot be represented exactly using the double data type. This introduces a small approximation error in y which in turn introduces a small approximation error in calculatedResult. This example demonstrates why it's unwise to perform an "exactly equals" comparison of floating point numbers.
To allow for small approximation errors in calculations, it's better to perform an "almost equals" comparison of floating point numbers which checks whether the numbers are close to each other. This involves checking whether the difference between the numbers is less than some epsilon.
The problem then becomes choosing an epsilon. Any fixed epsilon would likely be too small when comparing large numbers, or too large when comparing small numbers. Thus, it's desirable to choose a relative epsilon that is relative in magnitude to the numbers being compared. Note that the double data type uses 64 bits, with 1 bit for sign, 11 bits for exponent, and 52 bits for mantissa. If we choose epsilon by dividing one of the numbers by 2^n, a difference of less than epsilon will indicate that the numbers being compared agree about the first n bits of the mantissa. For example, consider an AlmostEqual method that compares the difference of the two numbers to the first number divided by 2^48.
public static bool AlmostEqual(double a, double b)
{
if (a == b)
{
return true;
}
return Math.Abs(a - b) < Math.Abs(a) / 281474976710656.0;
}
This method will return true when the two numbers match to about the first 48 bits of the mantissa (i.e., only disagree in about the last 4 bits of the mantissa). Note that the method has code to handle the special case when the two numbers are exactly equal. We can then rewrite our original code example using the AlmostEqual method in place of the == operator.
bool areSame = AlmostEqual(calculatedResult, expectedResult);
Now areSame will be true, indicating that caluclatedResult is close enough to expectedResult that any difference could easily be an approximation error due to limitations of the double data type.
Note that the above AlmostEqual method is not perfect. Zero will only compare almost equal to zero. Thus, the above AlmostEqual method doesn't account for approximation errors when one of the numbers being compared is zero.
Posted by Peter Vogel on 11/08/2011 at 6:41 AM5 comments
Sometimes you really, really, really want to see the SQL that LINQ generates when working with the Entity Framework. For instance, in a comment to a
recent tip, a reader mentioned that a LINQ to Entities query generated a SQL statement that joined more than 40 tables. The application's performance was, to say the least, disappointing. If you're not getting what you expect from your LINQ queries, being able to see the SQL statement can give you real clues in tracking down the problem, as it did with that column's reader.
There are a couple of free Visual Studio Add-ins that, among their other features, allow you to see the SQL statement for a LINQ query (The LINQ to Entity Query Visualizer, Entity Visualizer). However, developers have had trouble getting those add-ins up and running in some versions of Visual Studio (especially Visual Studio 2010). Fortunately, if all you want to do is see your SQL statement, you can do it in Visual Studio's debug mode using a little code in the Immediate Window.
The first step, of course, is have a program with a LINQ query as in this example:
Dim en As New northwndEntities
Dim res = From cust In en.Customers
Select cust
If you cast the variable holding the output from the query (res, in this case) to Objects.ObjectQuery then you get access to the ObjectQuery's ToTraceString property. That property returns the SQL statement that will be issued by your Entity Framework Model. In Visual Basic, you'd type this in the Immediate window:
CType(res, Objects.ObjectQuery).ToTraceString()
In C#, you'd type this:
((System.Data.Objects.ObjectQuery) res).ToTraceString()
For my sample query, the result looked like this in Visual Basic (the C# version includes escape characters for newline and carriage returns):
SELECT [Extent1].[CustomerID] AS [CustomerID],
[Extent1].[CompanyName] AS [CompanyName],
[Extent1].[ContactName] AS [ContactName],
[Extent1].[ContactTitle] AS [ContactTitle],
[Extent1].[Address] AS [Address],
[Extent1].[City] AS [City],
[Extent1].[Region] AS [Region],
[Extent1].[PostalCode] AS [PostalCode],
[Extent1].[Country] AS [Country],
[Extent1].[Phone] AS [Phone],
[Extent1].[Fax] AS [Fax],
[Extent1].[Timestamp] AS [Timestamp]
FROM [dbo].[Customers] AS [Extent1]
Posted by Peter Vogel on 11/03/2011 at 9:20 AM3 comments
In a recent
article on using LINQ with Entity Framework, I recommended using Entity Framework's navigation properties in your LINQ statements instead of joins. The code is easier to write and the SQL generated for you will automatically include the necessary joins.
However, the following won't generate an SQL statement that joins the Orders table to the Employees table because the LINQ query doesn't reference the Employees objects:
Dim res = From o In nw.Orders
Where o.Freight > 0
Select o
For Each ord In res
EmpName = ord.Employee.FirstName
'…code using the employee name
Next
In this case, the navigation properties aren't being used until the For…Each loop that follows the LINQ statement. The compiler isn't smart enough to spot that, so the SQL statement that's generated from the LINQ query won't include a join to the Employee table. Instead, Employee rows will probably be fetched one by one from the database as the code loops through the collection of Order objects retrieved through the LINQ query. This would be terrifically inefficient if, as this code does, every Order is going to have its related Employee object processed.
The solution is to give LINQ some advice about what you intend to do. In the same way that ADO.NET will process requests faster if you tell it more (for instance, if you know that only a single row will be retrieved, using ADO.NET's SingleResult option will give you better performance), LINQ will work faster for you if you tell it what you need. In this case, using the Include keyword tells LINQ that it should add a join to the SQL statement to fetch the related Employee rows:
Dim res = From o In nw.Orders.Include("Employees")
Where o.Freight > 0
Select o
As a developer, you'll have to make some decisions here. If, for instance, the loop in the previous example had an If statement that ensured that only some of the Employee records were going to be processed, it might make sense to omit the Include keyword. With the Include keyword gone, only the Employee rows that were actually needed in the loop would be fetched. You may need to run some tests to see if using Include makes your application run faster or slower. Fortunately, as with SQL, switching between the two versions of the LINQ statement is easy to do (delete or add the Includes), so it's relatively easy to do some time trials and see what gives you the best performance.
Posted on 10/26/2011 at 7:52 AM5 comments
The ASP.NET DataViews, when connected to a DataSource, generate all the buttons a user needs to edit, update and delete the data that the DataView displays (assuming that you enable edits, updates and deletes).
But what if you want to add some additional functionality to the form? If, for instance, you want the user to be able to click a button to run a credit check on the currently displayed customer? Or, for some change that requires coordinating changes to several values, you want to give the user the ability to implement the update with a single button click? Or, by clicking a button, delete not the currently displayed record but some other, related set of records (i.e. "Delete all orders for this customer")? You can put that code where it belongs -- associated with the DataView -- rather than scattered through several Click events by using the FormView's ItemCommand method.
All you have to do is drop a Button of your own onto the form and set the Button's CommandName property to some string. When the user clicks on any Button on the DataView, the DataView fires its ItemCommand event. The e parameter to that event has a property called CommandName that's automatically set to whatever was in the CommandName property of the button that triggered the event. You can use that value to check to see which Button was clicked and execute your code. Typical ItemCommand code will look like this:
Select Case e.CommandArgument
Case "CreditCheck"
'....
Case "DeleteAllOrders"
'....
'CommandArguments for other buttons
End Select
This event has two other properties useful in this scenario. The CommandArgument property contains the value of the CommandArgument property on the Button the user clicked. You can store data in the CommandArgument that will be passed to the ItemCommand event when the Button is clicked. Less useful is the CommandSource, which points at the Button that fired the event (the sender parameter passed to the event points to the DataView).
And, because the ItemCommand event fires for every Button on the page and fires before any of the events triggered by that button, the ItemCommand event lets you preview all other Button clicks on the page. This allows you to use the ItemCommand event as a central point-of-control for every Button on the DataView.
Posted by Peter Vogel on 10/24/2011 at 1:48 PM2 comments
In my recent
review of Document! X 2011, a tool for generating MSDN-style documentation for your projects by scanning your assemblies, a reader pointed out that you can achieve many of the same results by using Ghost Doc and Sandcastle. I've discussed
Ghost Doc (a free tool for generating XML comments in your source code) before. Both Document! X and Sandcastle will incorporate your XML comments into the documentation they generate through scanning your assemblies.
Sandcastle is a set of command-line utilities that's free from Microsoft. Sandcastle generates the inputs to Microsoft's various Help compilers, which you'll also need to install. In addition, using Sandcastle would be painful were it not for a free GUI, the Sandcastle Help File Builder. But don't panic -- you can download a Sandcastle package from CodePlex that includes a great "guided installation" wizard. The wizard will help ensure that you get everything you need: Sandcastle, the GUI, and the necessary Help compilers. Just make sure that you download from the CodePlex site -- a simple Google search can lead you to a Sandcastle site with outdated links.
Using Sandcastle with the GUI is easy: Select Sandcastle from the Windows Start menu, create a new project, and add to the Sandcastle project the assemblies you want to document (you can also add "reference" assemblies, which are not documented but which your documentation refers to). Once you've added all your assemblies, it's just a matter of clicking the Build button and waiting for your Help files to be generated. After the files are generated, you can view the resulting output from the GUI's view menu.
There are several plug-ins for Sandcastle. For instance, the Wildcard References plug-in allows you to add as references to your project whatever assemblies in a folder (and optionally, its subfolders) meet a filespec. Sandcastle also includes a tool for gathering up the XML comments from ASP.NET Web Applications and Websites (since ASP.NET projects may have multiple DLLs) so that they can be incorporated into your documentation.
Sandcastle doesn't integrate with Visual Studio 2010 or your project's file structure, though there's an alpha release of a package that has begun adding that feature. The package also has the odd limitation. For instance, you can't add a reference to a COM DLL through the GUI.
Does Sandcastle do everything Document! X does? No. Currently, Sandcastle lacks Document! X's integration with Visual Studio, doesn't support documenting databases or Ajax components, and lacks Document! X's source control features, among other options. However, if what you want to do is generate MSDN-style documentation for your assemblies, Sandcastle will do that -- and the price is right. It's entirely possible that Sandcastle will meet your current needs for documenting your applications and should you, eventually, need to do something that Sandcastle doesn't support, you can purchase a more comprehensive package.
Posted by Peter Vogel on 10/19/2011 at 7:48 AM0 comments