Just Sayin’ More Words

RSS Feed Subscribe

Less code is fun: ASP.NET 3.5 SP1 removes need for control adapter when using URL rewriting

If you use URL rewriting in your ASP.NET apps you’re probably familiar with the workarounds required to get your rewritten URL to show up in the action attribute of the form on your pages (see ScottGu’s ‘Handling ASP.NET PostBacks with URL Rewriting’). Well, no more.

Included in the latest ASP.NET Service Pack is this gem (via Scott Hanselman):

HtmlForm.Action is now settable - Again, subtle, but very cool.  I like to use URL rewriting a lot and want my <form action=”"> to be a certain way. Now I can set it manually without fooling around with RegEx’s and messing with the whole response.

Woot! I deleted my FormRewriter.cs control adapter and .browser file then added this little snippet to my common BasePage (you can do this in either Page_Init or Page_Load on individual pages) and now my form action attributes reflect the original URL.

// header is created by Ionic’s ISAPI Rewrite Filter (IIRF)
string u = Request.Headers["X-Rewrite-Url"];
if (!string.IsNullOrEmpty(u))
{
   
Form.Action = u;
}

Be sure to check out the rest of Hanselman’s post for more details on what’s new in SP1.

August 14th, 6:23 PM .NET, Tips Read more Comments

Disabling the AVG 8.0 Free LinkScanner

I use Grisoft’s AVG Free on my home computer for anti-virus. I’ve been using it for a few years and have been pleased with it. It doesn’t have a noticeable performance penalty and it generally stays out of the way. They’ve recently discontinued version 7.5 and have replaced it with 8.0, which is still available for free (although, they’re starting to be more discreet about that).

AVG 8.0 includes a new IE add-on called LinkHelper. When you do a Google search, it checks each link in the results and presents you with some icons indicating whether or not the site listed is safe.

2008-05-24_1820

This is great for my mom, but I don’t like to run any unnecessary browser add-ons. IE doesn’t need any help being more unstable. I figured I’d just disable it, but it’s not that straightforward. I went in and disabled it in the AVG options. This got rid of the icons in IE, but now AVG warns you via the tray icon that there’s an error. If I left it like this and there actually was an error, at a glance I wouldn’t know.

2008-05-24_1824

Disabling LinkScanner also does not unload the IE addon. So here’s my workaround. Enable LinkScanner in AVG, but then unload the browser addon manually:

2008-05-24_1833

AVG still thinks LinkScanner is loaded, but it’s not. You can now search the Googles uninterrupted.

Before anyone responds to this by saying "Switch to Firefox" let me preemptively respond to that. First off, I like Firefox just fine and have nothing against it. The reason I use primarily use IE is because the large majority of the people that use the web sites I build still use IE. If I don’t feel their pain, I find myself ignoring them. Using IE keeps me in touch with my users.

May 24th, 6:39 PM Software, Tips Read more Comments

VS2005 ‘prop’ C# Code Snippet in VS2008

Automatic properties are nice, but sometimes you just want a good ol’ regular property with a backing field. Visual C# 2005 had the ‘prop’ code snippet which generated this:

visual c# 2005 prop code snippet

Visual C# 2008 now generates the following when using the ‘prop’ snippet:

2008-02-26_2330_001

I find myself wanting to use the old snippet more than the new one, so I went into the 2005 code snippets, copied the ‘prop’ snippet file, made a few changes and imported it into 2008 (Tools | Code Snippets Manager | Import).

Now, all is well:

Here’s a .zip file of the snippet that you can download.

February 27th, 1:16 AM .NET, Tips Read more Comments

Stupid Visual Studio Tricks, Part 4

Part 1: Navigate with the back/forward buttons on your mouse
Part 2: Fix annoying jumping toolbars
Part 3: Using the find window to quickly open a file

A couple quick ones:

  • Click with your middle mouse button (or scroll wheel) on a tab to close a document window.
  • Window > Close All Documents (not where I thought it should be)
  • Re-map Control-W to Close Document (like IE/Firefox)
    • Tools | Options | Keyboard
    • In ‘Show commands containing’ type SelectCurrentWord
    • Click Remove
    • In ‘Show commands containing’ type File.Close
    • In ‘Press shortcut keys’ type Control-W
    • Click ‘Assign’ and ‘OK’
  • Use Control-Backspace and Control-Delete to delete entire words. Control-Delete is especially helpful when the cursor is at the end of the line and you want to delete the line break and the leading tabs/spaces of the next line.
  • Use Control-. to bring up the smart tag for adding using statements.
    controldot
  • Use Control-I to quickly search through a document. After you’ve located a match, hit Control-I again to cycle through other matches.
  • Right-drag code to invoke context menu for with options for moving or copying (if you can’t be bothered to hold control while dragging).

September 12th, 6:18 PM Software, Tips Read more Comments

Stupid Visual Studio Trick, Part 3

Part 1: Navigate with the back/forward buttons on your mouse
Part 2: Fix annoying jumping toolbars

This tip comes courtesy of Rob Prouse who posted this recently in a comment on this very site. Here’s a quick way to open up a file without taking your hands off the keyboard:

"In the toolbar, type >of in the find window, then start typing the filename you are looking for. An autocomplete list of all files in your project will come up that you can select from. Select, hit enter and up pops the file in the editor!"

Great tip! Thanks Rob!

UPDATE: Here’s another post outlining even more tricks with the Find box.

September 11th, 9:13 PM Software, Tips Read more Comments

Stupid Visual Studio Trick, Part 2

Continuing my series of ‘Stupid Visual Studio Tricks’ (see Part 1), today’s tip fixes one of the more annoying things about Visual Studio: bouncing/flashing/crazy context-sensitive toolbars. This is particularly annoying when working with SQL Server Management Studio over RDP because it frequently causes a full-window redraw which can be soooo sloooowww. The jumping toolbars also drove me crazy when I used the Copy Web Site feature, but I don’t use that anymore.

To work around this annoyance, I create an empty toolbar as such:

  1. Right click in an empty section of the toolbar area, select ‘Customize…’
  2. Select the ‘Toolbars’ tab and click ‘New…’
  3. Give the toolbar a name (I use "Blank"; clever, huh?) and hit ‘OK’
  4. Drag the newly created toolbar (which can be tough to spot but it should be just to the right of the Customize dialog) up to the far right of the toolbar area.
    vsblanktoolbar

The next time you open a window you might see three toolbar rows instead of two with the middle one just being the blank toolbar you created. Just drag the bottom row up to the middle row and it will be there next time you open a file. Now go ahead and switch between a .aspx and code-behind file. No more jumping toolbars!

September 11th, 6:55 PM Software, Tips Read more Comments

Stupid Visual Studio Trick, Part 1

Right click on a method, select Go To Definition, click fancy back button on mouse. Neat huh? Forward works too. If you don’t have a mouse with  back and forward buttons, you’re missing out.

September 10th, 7:36 PM Software, Tips Read more Comments

Slightly more dynamic ORDER BY in SQL Server 2005

Dynamically ordering SELECT statements in T-SQL has been an issue I’ve run into a lot. The options have traditionally been use dynamic SQL (eww) or a CASE statement in the ORDER BY. CASE kind of works, but its limited (only one column, no sort directions, datatype issues, etc).

I needed a way to dynamically sort the results of a stored procedure by multiple columns with different combinations of sort directions (e.g. Customer.LastName DESC, Customer.FirstName). I’m fortunate that in my situation there’s only six possible sort combinations based on CustomerTypeID. If you’re looking for a way to pass a string parameter to your stored procedure and sort by that; as far as I can tell you’re still stuck with the existing workarounds. Alright, let’s get into the example.

Create the following tables and test data. Remember, this example only works with SQL Server 2005.

CREATE TABLE Customer
(
    CustomerID int identity(1,1),
    FirstName nvarchar(50),
    LastName nvarchar(50),
    CustomerTypeID int
)

CREATE TABLE CustomerType
(
    CustomerTypeID int identity(1,1),
    CustomerType nvarchar(50)
)

--Insert test data

INSERT INTO CustomerType (CustomerType) VALUES('Type1') -- ID=1
INSERT INTO CustomerType (CustomerType) VALUES('Type2') -- ID=2
INSERT INTO CustomerType (CustomerType) VALUES('Type3') -- ID=3

INSERT INTO Customer (FirstName, LastName, CustomerTypeID) VALUES ('John', 'Doe', 1)
INSERT INTO Customer (FirstName, LastName, CustomerTypeID) VALUES ('Jane', 'Doe', 1)
INSERT INTO Customer (FirstName, LastName, CustomerTypeID) VALUES ('Steve', 'Jobs', 2)
INSERT INTO Customer (FirstName, LastName, CustomerTypeID) VALUES ('Steve', 'Wozniak', 2)
INSERT INTO Customer (FirstName, LastName, CustomerTypeID) VALUES ('Linus', 'Torvalds', 2)
INSERT INTO Customer (FirstName, LastName, CustomerTypeID) VALUES ('Bill', 'Gates', 3)
INSERT INTO Customer (FirstName, LastName, CustomerTypeID) VALUES ('Michael', 'Dell', 3)
INSERT INTO Customer (FirstName, LastName, CustomerTypeID) VALUES ('Steve', 'Ballmer', 3)
INSERT INTO Customer (FirstName, LastName, CustomerTypeID) VALUES ('Ray', 'Ozzie', 3)

Let’s say we need a procedure to return customers of a certain type. The proceedure needs to sort result sets with Customers of TypeID=1 by FirstName then LastName. Customers of TypeID=2 by LastName then FirstName and lastly Customers of TypeID=3 as LastName DESC then FirstName.

This is where SQL Server 2005 comes into play. SQL 2005 has introduced some new ranking functions like RANK(), ROW_NUMBER(), etc. We’re going to use RANK() here. Because RANK() accepts multiple ORDER BY statements, we can use the return value to order our result set.

First, let’s see the results of using the RANK() function in our stored procedure.

CREATE PROCEDURE CustomerGetWithRanks
AS
BEGIN
    SELECT
        CustomerID,
        FirstName,
        LastName,
        CustomerTypeID,
        RANK() OVER (ORDER BY FirstName, LastName) AS Type1SortRank,
        RANK() OVER (ORDER BY LastName, FirstName) AS Type2SortRank,
        RANK() OVER (ORDER BY LastName DESC, FirstName DESC) AS Type3SortRank
    FROM
        Customer
END

Results:

CustomerID FirstName LastName  CustomerTypeID Type1SortRank Type2SortRank Type3SortRank
---------- --------- --------- -------------- ------------- ------------- -------------
7          Steve     Wozniak   2              9             9             1
8          Linus     Torvalds  2              4             8             2
12         Ray       Ozzie     3              6             7             3
6          Steve     Jobs      2              8             6             4
9          Bill      Gates     3              1             5             5
4          John      Doe       1              3             4             6
5          Jane      Doe       1              2             3             7
10         Michael   Dell      3              5             2             8
11         Steve     Ballmer   3              7             1             9

You can see how each set of sort criteria would sort all of our test records. I only need to retrieve one type at a time however, so I’m going to combine this method with the previously limited CASE method.

The last piece of the puzzle is adding the logic to determine which sort order to use based on CustomerTypeID. We’re also going to narrow down our result set to only return a specific type of Customer and hide the RANK() output.

CREATE PROCEDURE CustomerGetFinal
    @CustomerTypeID int
AS
BEGIN
    SELECT
        CustomerID,
        FirstName,
        LastName,
        CustomerTypeID
    FROM
        Customer
    WHERE
        CustomerTypeID = @CustomerTypeID
    ORDER BY
        CASE
            WHEN @CustomerTypeID = 1 THEN (RANK() OVER (ORDER BY FirstName, LastName))
            WHEN @CustomerTypeID = 2 THEN (RANK() OVER (ORDER BY LastName, FirstName))
            WHEN @CustomerTypeID = 3 THEN (RANK() OVER (ORDER BY LastName DESC, FirstName DESC))
        END
END

(NOTE: If you want to output the RANK() result and order by the same value, you have to specify the whole line twice as SQL server doesn’t appear to be accepting dynamically created columns as ORDER BY parameters). Here are the results:

EXEC CustomerGetFinal 1

CustomerID FirstName LastName CustomerTypeID
---------- --------- -------- --------------
5          Jane      Doe      1
4          John      Doe      1

EXEC CustomerGetFinal 2

CustomerID FirstName LastName CustomerTypeID
---------- --------- -------- --------------
6          Steve     Jobs     2
8          Linus     Torvalds 2
7          Steve     Wozniak  2

EXEC CustomerGetFinal 3

CustomerID FirstName LastName CustomerTypeID
---------- --------- -------- --------------
12         Ray       Ozzie    3
9          Bill      Gates    3
10         Michael   Dell     3
11         Steve     Ballmer  3

kick it on DotNetKicks.com

April 23rd, 7:20 PM SQL Server, Tips Read more Comments