Wednesday 30 April 2008

Validation of viewstate MAC failed error - Fixed

There is a problem with ASP.NET encrypted viewstate which means it will generate an error if your page is slow to load and the user tries to post back to the page (e.g. by clicking a button). Encrypted viewstate typically exists on the page because any controls (like GridViews) that use "DataKeyNames" require it. The big problem is that it is put at the bottom of the page just before the end form tag - which may not have been loaded by the time a user post backs on a slow-loading page. This often happens on the first hit to a page as the client is downloading images or the JIT compiler is doing its work.

One of the best articles I've seen on some of the solutions to this problem is here:

http://blogs.msdn.com/tom/archive/2008/03/14/validation-of-viewstate-mac-failed-error.aspx

There are 3 workarounds suggested:
  1. Set enableEventValidation to false and viewStateEncryptionMode to Never.
  2. Disable the form until the page has finished loading
    function enableForm() {
    document.getElementById("form").disabled = false;
    }
    window.onLoad = enableForm();


  3. Or override the Render of your page so that the Encrypted section of the viewstate is put at the top of the form rather than at the bottom as it is by default. I've tested this version in our application which uses Virtual Earth maps and it fixes the issues with have with slow page loads (RECOMMENDED as it does not rely on javascript to work):




public abstract class BasePage : Framework.Web.UI.Pages.BasePage
{
/// <summary>
/// Fix for viewstate issue when the user clicks on a button before the encrypted section
/// of the viewstate is finished.
/// As per fix in
/// http://blogs.msdn.com/tom/archive/2008/03/14/validation-of-viewstate-mac-failed-error.aspx
/// </summary>
/// <param name="writer"></param>
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
System.IO.StringWriter stringWriter = new System.IO.StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
base.Render(htmlWriter);
string html = stringWriter.ToString();
string[] aspnet_formelems = new string[5];
aspnet_formelems[0] = "__EVENTTARGET";
aspnet_formelems[1] = "__EVENTARGUMENT";
aspnet_formelems[2] = "__VIEWSTATE";
aspnet_formelems[3] = "__EVENTVALIDATION"; aspnet_formelems[4] = "__VIEWSTATEENCRYPTED";
foreach (string elem in aspnet_formelems)
{
//Response.Write("input type=""hidden"" name=""" & abc.ToString & """")
int StartPoint = html.IndexOf("<input type=\"hidden\" name=\"" +
elem.ToString() + "\"");
if (StartPoint >= 0)
{
//does __VIEWSTATE exist?
int EndPoint = html.IndexOf("/>", StartPoint) + 2;
string ViewStateInput = html.Substring(StartPoint, EndPoint - StartPoint);
html = html.Remove(StartPoint, EndPoint - StartPoint);
int FormStart = html.IndexOf("<form");
int EndForm = html.IndexOf(">", FormStart) + 1;
if (EndForm >= 0)
html = html.Insert(EndForm, ViewStateInput);
}
}

writer.Write(html);
}

Microsoft Live Mesh - Device Sharing On Steroids & How to get an Invite

Live Mesh is a new SAAS (Software as a Service) platform from Microsoft that allows you to effectively have a shared drive on the web. This is similar to Amazon's Simple Storage Service (S3) or the GMail Drive Shell Extension. But it is much more than just a file share for the web that can be shared between different machines and different users... you can also connect to your PCs in the mesh via remote desktop - and you can connect different types of devices to it. The official site is www.mesh.com.

To be involved in the tech preview, you can register via MS Connect (http://connect.microsoft.com/) OR you can just go to this site to find some one who can give you an invite to this new service - http://www.sharemesh.com/. For a brief rundown on what this tech preview of Live Mesh provides, see this review: http://www.networkworld.com/community/node/27230


Tuesday 29 April 2008

The best settings for Crysis on Dell XPS 1730 with 8800M GTX in SLI

After experimenting with different SLI and graphics settings for 2 hours, I found the absolute best performance optimization for Crysis under Vista is to dump DirectX 10.0 altogether.

This occurs by default in XP as you can't get DirectX 10.0 for XP at all. However, if you are in Vista you have to force a DirectX 9.0 override via the commandline.

To do this, just create a shortcut on your desktop like so (you file path may vary):
"%Program Files%\Electronic Arts\Crytek\Crysis\Bin32\Crysis.exe" -dx9

You can have the best of both worlds (for the best performance and image quality) with the help of this config file hack which allows Windows XP to run on the "Very high settings" mode found at http://www.ngohq.com/news/12492-crysis-demo-very-high-settings-hack.html. The very high setting is not normally available in the Game->System menu in DirectX 9/Windows XP.

With these settings, I can run Crysis on the max setting normally available in DX 10 (Very High) on a Dell XPS 1730 at 1024x768 with 2x AA very smoothly. I've found these settings to be the best to play with... you can tackle a crowd of North Koreans at close range without a stutter, and then stop to admire the view. What's more, you get all the volumetric light effects normally reserved for the DirectX 10 only crowd.

Monday 28 April 2008

LINQ Group By Syntax for Grouping on Multiple Columns (another peculiarity of syntax in LINQ)


It is an oversight by the folks at Microsoft that LINQ does not have a built-in group by operator that supports multiple group by columns. For example, I found it unusual that LINQ does not support multiple grouping statements like so:



from f in FundUserRoles
group f by f.RoleId, f.UserName into myGroup
where myGroup.Count() > 0
select new {myGroup.Key, ProductCount = myGroup.Count()}




If you try to run this query, you will get a syntax error on the second line. You cannot just add items to the group by clause like this. Instead, to get this group by working, you must use anonymous types and do the following:

from f in FundUserRoles
group f by new {f.RoleId, f.UserName}
into myGroup
where myGroup.Count() > 0
select new { myGroup.Key.RoleId, myGroup.Key.UserName, FundCount = myGroup.Count()}


This query now works in LINQPad.


Using Regular Expressions for Simple Code Generation in UltraEdit

I love getting tools to do repetitive 'monkey work' for me. To this end, there is an alternative to my post on code generation via sysobjects at http://ddkonline.blogspot.com/2008/02/rehash-daves-simple-sql-workbenchquery.html. Difference in this post that is code/SQL generation is done through… you guessed it… UltraEdit Regular Expressions!

My task – I wanted to do a multiple column join to determine if any updates had been made to a table (compared to a table which contained the original Excel import). Now instead of doing the hard work and going through all 70 columns and manually typing each table name in e.g. Table1.ColumnName = Table2.Column name for every column, I used the following shortcut:




  1. Drag the columns folder from the treeview to the working area in SQL 2005 WorkBench so you have a list of comma-separated columns (e.g. RecordNumber, Information, RecordType, DocAuthor)




  2. Copy this into my the text editor, UltraEdit (make sure you have Advanced -> Configuration -> Search -> Regular Expression Engine set to “Unix Style” as used in .NET rather than “Ultra Edit Style”)



  3. Ctrl+R to open the replace dialog and put in “\W*(\w*),” to the Find box and “Table1.\1 = Table2.\1 AND\n” in the Replace Box.




  4. Do the replace and you will now have a properly formatted join expression for use in your queries. i.e.

    Table1.RecordNumber = Table2.RecordNumber AND
    Table1.Information = Table2.Information AND
    Table1.RecordType = Table2.RecordType,


You can now put the joins back into your query:


SELECT

*

FROM

dbo.OpportunityRawImport_Stage1Load as Stage1

INNER JOIN

dbo.OpportunityRawImport_Stage2Load as Stage2

ON

Stage1.RecordNumber = Stage2.RecordNumber AND

Stage1.Information = Stage2.Information AND

Stage1.RecordType = Stage2.RecordType AND




Handy Tools for Building Regular Expressions:

A free regular expression editor with English interpretations of your regular expressions (The Regular Expression Workbench) can be found at:
http://blogs.msdn.com/ericgu/archive/2003/07/07/52362.aspx. For example, a regular expression for Australian Postcodes ("^[\d]{4,4}$". Is interpreted as:



^ (anchor to start of string)
Any character in "\d"
At least 4, but not more than 4 times
$ (anchor to end of string)




Sunday 27 April 2008

Fix - IE 7 and 8 Freezing and Generating Javascript Errors on Windows Vista

Since the new XPS 1730 arrived, I've been having horrible response times on some (not all) https pages and getting almost random javascript errors on a handful of websites. This was not happening on my other Vista Basic edition laptop - and didn't happen with Firefox at all on either machine. The problem was occurring all of the admin pages on the iinet toolbox (https://toolbox.iinet.net.au/). I couldn't even log into the iinet billing system without IE timing out and giving javascript errors.

I am always determined to get to the root of the problem if something is not working quite right on my home machines - so I applied my usual "Divide and Konquer" (DK for short) approach to solving bewildering issues....

This is the process I worked through to find the problem - so you don't have to go through the same 13 step process if you encounter this issue:


  1. Googled some of the javascript errors I was getting. Logically, I believed that if something is working on one machine, but not on the other - it had to be some kind of IE Javacript engine corruption or different configuration setting. Indeed, someone else in the world MUST have had the same issue with the same javascript errors. I read through many articles but none solved my issues. It wasn't the javascript itself - as that was working on my other laptop.
  2. Started in IE in safe mode (Start->All Programs->Accessories-> System Tools -> Internet Explorer (No Add-ons). No difference - pages still slow and freezing in IE 7, javascript errors
  3. Rebooted my machine (Another of my mottos - "If in doubt, restart it"). Problem still there.
  4. Did a reset of all settings and Advanced Settings in IE 7 (Tools->Options->Advanced->Reset Button)
  5. Flushed out IE temp files and cache in case I had corrupted javascript files that weren't getting updated on page refesh (Tools->Options-> Delete). Still no result.
  6. Removed all startup services via sysinternals autoruns (http://technet.microsoft.com/en-us/sysinternals/bb963902.aspx). No difference.
  7. Started up in safe mode. No difference (contrary to some articles I have seen - wireless does work in Safe Mode with Networking, not just hard ports).
  8. Rolled back to my first system restore point. No difference.
  9. Backed up my system and installed the factory default image that comes from Dell. No change.
  10. Did a completely fresh install of Windows Vista from the Dell Media provided by Dell. No difference.
  11. At this stage, I thought it must be external in some horrible combination of issues with IE 7 and my router - but my other laptop (on which I had not changed settings) ran fine. Just in case, I rebooted the router (a Belkin 54g wireless with VOIP I got 2 years ago from iinet)- still no benefit.
  12. A bit more investigation and I found (another list) that runs through some of the troubleshooting steps when fixing IE 7 on Vista. I didn't think much of it as it was similar to all the other lists I found in step 1 - but there was one report of an issue with Vista and certain routers not cooperating: http://www.howtogeek.com/howto/windows-vista/troubleshooting-internet-explorer-on-vista-locking-up-or-running-slowly/. This is under the heading "Disable Receive Window Auto-Tuning".

    "If none of those fixes the problem, and you are just having a really slow browsing experience only on your Vista computer, the problem could very well be due to the network auto-tuning feature in Windows Vista which is incompatible with some routers.
    Open up an administrator mode command prompt (right click on command prompt and choose Run as Administrator), and then type in the following command.
    netsh int tcp set global autotuninglevel=disabled
    You can also try running a cut down version of auto tuning via this commandline. But your mileage may vary:
    netsh interface tcp set global autotuninglevel=restricted
    You can set it back to normal by (you guessed it):
    netsh interface tcp set global autotuninglevel=normal
    Just remember to reboot for these to take effect.
  13. So I ran the netsh commandline fix and magically all the sites that were having problems ran at full speed without errors. Unfortunately, this was not as simple as a firmware fix as I have the latest version of the firmware on my machine (April 2007 - http://www.belkin.com/au/support/article/?lid=ena&pid=F1PI241EGau&aid=6242&scid=846). Why this netsh fix works is explained right here:
    http://blogs.msdn.com/wndp/archive/2007/07/05/receive-window-auto-tuning-on-vista.aspx.

    As per http://support.microsoft.com/kb/934430, the connectivity diagnostic suite can tell you if you suffer from the same problem - you can get this from here: http://www.microsoft.com/windows/using/tools/igd/default.mspx
  14. Problem solved.


Sunday 13 April 2008

My monster Dell 1730 with 8800M GTX SLI arrives



At the start of this month (April), after deliberating over whether I should get a laptop or a desktop, I took the plunge and went for the Dell XPS 1730. I need to move the laptop around the house (depending on where my daughter Heidi is), so I decided on the slightly more mobile option.

The real question was about what model I should get. Should I import from the US or buy locally? Some guys on newsgroups (e.g. at http://forums.whirlpool.net.au/) had recommended importing some of the quad-core capable laptops made by Clevo like the Metabox M57RU http://www.p4laptops.com.au/order-m57ru-8800.htm (aka Rock in the US and UK). However, I took the plunge when Dell Asia Pacific offered a generous 15% discount on all Dell XPS machines. My last 4 laptops have been Dells and I have no major complaints about Dell thus far.



I had a very pleasant surprise on Friday evening - I received a message from Mai at the Oakton office in North Sydney that my new "baby" Dell 1730 (or "behemoth", take your pick) had arrived safe and sound - about 10 days early.




I was very keen to get my grubby little hands on it so I rushed out at 17:45 to grab (or lug) the beast home (with 2x200GB 7200rpm drives, 4GB RAM, running a Core 2 Duo T9300 @ 2.5GHz) I'm about 2kms from the office so it was a bit of a stretch to carry the overly large box back home.






All safe and sound, I unwrapped the package. Even my daughter Heidi was excited. As I would expect, a few of the golden oldie games that I've been playing in my fairly limited spare time with a Dell Inspiron 640m (a 15 incher) ran as smooth as silk - at twice the resolution. Crysis at Very High Settings with Blood (VSYNC off of course) and at 1280x1024 ran at a reasonable rate with minor slowdowns when in combat. It is truly a gorgeous game; from all the horror stories I've heard about the steep system requirements for Crysis - I can't say I've got any complaints with my new SLI setup. The only issue is with heat dissipation or lack thereof - the fans at the back of the laptop are like a blast furnace after playing Crysis for an hour. Just don't try to use this baby when your sitting at the service station. You have been warned.
Assassins Creed was just released for the PC 3 days ago. This machine can handle it for sure... so bring it on...



Some piccies of the Dell XPS 1730 inline. Just mind you don't drool on your keyboard!



Wednesday 9 April 2008

Virtual Earth is not the only kid on the Intranet Block anymore - Google Maps API Premier Announced

Until now, the Google License has prohibited developers from using Google maps for intranet web sites - http://code.google.com/support/bin/answer.py?answer=55141&topic=10945
"The Maps API is not available for use within enterprise or intranet applications. "

Virtual Earth was the only available alternative for intranet apps. Until now.

Google recently released the new Google Maps API Premier , which allows companies to add Google Maps to their own website.

See the following:
http://www.google.com/enterprise/maps/

"When Google Maps plays an important role on your public website, or is incorporated in an internal application for your employees, organizations need an enterprise-class application that handles high volumes and provides necessary support."

In terms of price, the Google Maps API Premier starts from $10K USD a year (based on the number of users). Virtual Earth has starts with Basic Platform Access (Incl. 200K transactions, 50 Users, 2 support incidents) for $4K USD per annum (I am unable to disclose their full pricing structure pending approval from Clint McCarthy at Microsoft).