{ Code: Impossible } | this = HowI.Roll();

TAG | debugging

Sep/10

2

Spot the bug #2

I came across this issue just at quitting time yesterday and was blown away when I realized what was happening.

The UsersController Index View (pre submit)

The UsersController Code

    public class UsersController : Controller
    {

        List<string> users = new List<string> ()
            {
                "mace.windu",
                "yoda",
                "senator.amidala",
                "anakin.skywalker",
                "obiwan.kenobi"
            };

        public ActionResult Index()
        {
            return View( users );
        }

        [HttpPost]
        public ActionResult Delete ( string[] userstodelete )
        {

            if ( userstodelete == null || userstodelete.Length == 0 )
            {
                throw new ArgumentException (
                    "argument must contain at least one entry",
                    "userstodelete" );
            }

            // code could go here to
            // call out to some service to
            // delete these users

            TempData["deletedUsers"] = userstodelete;

            foreach ( var user in userstodelete )
                users.Remove ( user );

            return View ("Index", users);
        }
    }

Problem
Looks like it should all work perfectly right? That’s what I thought. However, clicking “Delete Users” will only “delete” our pre-darth user “anakin.skywalker”.

Why?

Hint: Everything here is working exactly as it should.

· · · ·

Aug/10

27

Spot the bug

What is wrong with the code below?

Safe Assumptions:

  1. _dictionary is a valid non-null Dictionary<object,object>
  2. _dictionary contains items that will match the passed expression
  3. This code compiles with no warnings or errors
  4. This code will throw an exception at runtime.

public IList<TModel> GetAllByCriteria<TModel> ( Expression<Func<TModel, bool>> criteria )
{
    Func<TModel, bool> action = criteria.Compile();
    return _dictionary.Where( pair =>
        action( (TModel)pair.Value ) ).Cast<TModel>().ToList();
}

If you don’t see it right away then you’re not alone. I spent a while debugging to catch this. If you do see it right away then pat yourself on the back.

· · ·

“Syntax Error, Line: 2, Char: 0″. How many of you out there have seen this error while working on a web project?

Usually it’s because of a forgotten semi-colon or parenthesis in some external javascript file. But sometimes it’s something more sinister… Something darker, dirtier and just a little bit more evil.

After seeing the error message, I opened up Internet Explorer’s options dialog and unchecked the following options:

  • Disable script debugging (Internet Explorer)
  • Disable script debugging (Other)

Internet Explorer Options Dialog

I then closed IE, returned to Visual Studio, stopped and re-started debugging (ctrl+shift+F5), and watched Solution Explorer as my page began to load.

Solution Explorer Debugging Internet Explorer

Oh! That’s not good. See the WebResource.axd request that has the same icon as the Default.aspx file? That means that a bad request was sent for an embedded resource and – most likely recieved a 404 page back instead of the javascript file, which caused our syntax error.

Ok, so how do we figure out which WebResource reference caused the problem? Well, the only way that I have come up with so far, is to manually copy and paste each WebResource.axd url from the html source of the page to the address bar and navigate there. The pages that give return a file download are ok and the ones that don’t will return a 404 page in the browser.

After finishing this long process of elimination, I found the resource request that was causing my headache:

/WebResource.axd?d=MaCiPhUUtdXNj16OOucV5e5lHCBZO...SNIP...

So how do we figure out which resource has embedded this troublesome URL into our html source? I found the solution to that in Irena Kennedy’s blog post on “How to Decrypt an ASP.NET Encrypted Data”:

Please note, that the code below should not be used in production code! It’s only meant for debugging and troubleshooting, and it may break in future versions of the .NET framework if DecryptString private method changes.

  1. Add a web page (e.g. DecryptData.aspx) to your web application. For the code to work, it must run in the same appdomain as the web application that created your encrypted string.
  2. Add a text box where you will type in the encrypted string.
  3. Add a label where you’ll display decrypted results.
  4. Add a button.
  5. In code-behind on button click event, add the following code:

System.Reflection.BindingFlags bf =
    System.Reflection.BindingFlags.NonPublic |
    System.Reflection.BindingFlags.Static;

System.Reflection.MethodInfo DecryptString =
    typeof(System.Web.UI.Page).GetMethod("DecryptString", bf);

DecryptedData.Text = DecryptString.Invoke(
    null,
    new object[] { EncryptedData.Text } ) as string;

After I created this page, I pasted the WebResource.axd URL (everything up to the &t=) into the DecryptedData textbox on my DecryptData.aspx page, clicked the Decrypt button, and saw that one of my custom aspx controls was responsible. I then corrected the resource path and the page loaded as it should.

See the screenshot below for an example of the DecryptData page, or download the DecryptData .ASPX and Codebehind from my box.net folder.

DecryptData page

· · ·

Theme Design by devolux.nh2.me