Thursday, March 29, 2007
Ajax extensions services always report “There was an error processing the request.”
I use Microsoft Ajax extensions 1.0 to query web services which may raise exceptions. In my development environment, I would always get a nice localized error message but on the production server, the same code would produce a generic “There was an error processing the request”.
After having spent enough time stepping through my code with a debugger, I have decided to look at the Ajax extensions code and I have found the following piece of code in WriteExceptionJsonString of RestHandler.cs.
if (context.IsCustomErrorEnabled)
{
writer.Write(JavaScriptSerializer.SerializeInternal(new WebServiceError(
AtlasWeb.WebService_Error, String.Empty, String.Empty)));
}
else
{
writer.Write(JavaScriptSerializer.SerializeInternal(new WebServiceError(
ex.Message, ex.StackTrace, ex.GetType().FullName)));
}
Where WebService_Error is a resource which is valued “There was an error processing the request.”
This means that if you have enabled custom errors in your web.config on your production environment like I did, your Ajax calls will always report a generic error.
Why have the Microsoft people introduced such a restriction is a mystery to me.
Friday, March 16, 2007
Extender controls may not be registered before PreRender
All our pages derive from our own WebPage class which derive from the standard Page class. WebPage provides features like custom error handling and QueryString parsing into page properties.
The page where we had the new extender control had the following method:
protected override void OnPreRender(EventArgs e)
{
//The following line is required, otherwise you get "Extender controls
//may not be registered before PreRender."
base.OnPreRender(e);
//Some code that displays errors on postbacks
...
}
The solution to the problem above is to add base.OnPreRender(e); at the beginning of the method.
Wednesday, January 31, 2007
Functional and load testing of ASP.NET Ajax applications – part I
Introduction
Velodoc is developed in ASP.NET C# 2.0 with Visual Studio .NET 2005.
VSTS comes with unit testing, web testing and load testing, considering load testing is actually an execution environment for unit tests and web tests.
Unfortunately Visual Studio web tests work at the protocol level, recording HTTP traffic in order to replay it. The same applies to Redgate’s ANTSLoad and many other load testing tools. Velodoc is an Ajax application and this does not work.
We have started our search for a solution from the following lists of testing tools:
- http://www.aptest.com/webresources.html
- http://www.softwareqatest.com/qatweb1.html
- http://www.testdriven.com/modules/mylinks/viewcat.php?cid=21&orderby=titleA&PHPSESSID=9f0501e81e532817372ad86a3dec5395
Obviously there are tools like Mercury Winrunner/Loadrunner and the IBM Rational equivalents which certainly cope but they are too expensive.
Our requirements are the following:
- Test ASP.NET applications
- Works on Windows XP with IE
- Compatible with NetAdvantage controls, iFrames, file uploads and Ajax
- Scripts IE including IE dialogs to drive functional UI tests
- Several instances can be executed concurrently to create load/stress tests
- Uses a familiar technology (low learning curve)
- Open source is a plus and a requirement if the supplier has not been around for a long time.
There are three types of solutions which cope more or less with these requirements:
- Macro recorders/players
- Test environments
- Web application scripting frameworks
Macro recorders/players and test environments
Searching on Tucows, Download.com and other shareware web sites reveals loads of macro recorders. Most of them hook the message pump and replay the windows messages. Obviously, the result is not good. We have tried a dozen of them but only iOpus iMacros 5.2 could do a decent job at automating a file upload from https://www.velodoc.net/. The code is reproduced below:
TAB T=1
TAB CLOSEALLOTHERS
URL GOTO=https://www.velodoc.net
SIZE X=876 Y=627
TAG POS=1 TYPE=INPUT:TEXT FORM=NAME:aspnetForm ATTR=ID: SenderTextBox CONTENT=test1@acme.com
TAG POS=1 TYPE=INPUT:TEXT FORM=NAME:aspnetForm ATTR=ID: RecipientTextBox CONTENT=test2@acme.com
TAG POS=1 TYPE=TEXTAREA FORM=NAME:aspnetForm ATTR=ID: MessageTextBox CONTENT= Test<SP>with<SP>iMacro
FRAME F=1
WINCLICK X=100 Y=429 CONTENT=
WINCLICK X=100 Y=429 CONTENT=C:\test.bin
FRAME F=0
TAG POS=1 TYPE=INPUT:CHECKBOX FORM=NAME:aspnetForm ATTR=ID: SendTermsCheckBox&&VALUE:on CONTENT=YES
WINCLICK X=490 Y=513 CONTENT=
I see at least three drawbacks to using iOpus iMacros as a functional test tool:
- The lack of assertions and reporting capabilities makes it insufficient for functional testing;
- The lack of infrastructure makes it insufficient for load testing;
- The proprietary language reduces the possibilities despite the fact that it can call external scripts or be called via a COM component.
I have also tried several test environments mentioned in the above lists. Generally, recording the file upload test on https://www.velodoc.net/ has always proved difficult but I cannot tell whether it was feasible or not for some of them. I have limited myself to 2 hours per evaluation and the inherent complexity and learning curve was not worth digging passed first impression.
Web application scripting frameworks
I have looked at two open-source frameworks, which both script IE to execute functional tests on the web application:
Both frameworks are very easy to start with due to a familiar language and an intuitive API. Additionally both frameworks provide the necessary assertions to report on the success or failure of a test fixture.
Scripting a file upload on the Velodoc home page with IEUnit entails the following JavaScript code:
_.openWindow(https://www.velodoc.net);
_.setField("SenderTextBox", test1@acme.com);
_.setField("RecipientTextBox", test2@acme.com);
_.setTextArea("MessageTextBox", "Test with IEUnit");
var fname = "C:\\test.bin";
var cmdShell = new ActiveXObject("WScript.Shell");
cmdShell.Run("C:\\EnterFileName.sbk " + fname, 0, false);
_.setFrame(0);
_.clickObjById("FileInput");
_.setFrame(-1);
_.setCheckBox("SendTermsCheckBox",true);
_.clickObjById("SendWebImageButton");
Where EnterFileName.sbk contains:
var fpath = " " + WScript.Arguments(1);
var popupWin = _.waitForWindow("Choose file", 30000);
_.setFrame(0);
_.findWindow(popupWin, "Edit").sendText(fpath);
_.findWinButton(popupWin, "&Open").click();
Scripting a file upload on the Velodoc home page with WatiN entails the following C# code:
using (IE ie = new IE(https://www.velodoc.net/))
{
ie.ShowWindow(NativeMethods.WindowShowStyle.Maximize);
ie.TextField(Find.ById("SenderTextBox")).TypeText("test1@acme.com");
ie.TextField(Find.ById("RecipientTextBox")).TypeText("test2@acme.com");
ie.TextField(Find.ById("MessageTextBox")).TypeText("Test with WatiN");
Frame f = ie.Frame(Find.ById("FileUploadFrame"));
FileUpload fUp = f.FileUpload(Find.ById("FileInput"));
fUp.Set("C:\\test.bin");
ie.CheckBox(Find.ById("SendTermsCheckBox")).Checked = true;
//ie.TextField(Find.ById("SenderTextBox")).FireEvent("onKeyUp");
ie.Button(Find.ById("SendWebImageButton")).ClickNoWait();
SimpleTimer t = new SimpleTimer(60 * 60);
Span s;
do
{
s = ie.Span(Find.ById("DownloadLinkLabel"));
if (!String.IsNullOrEmpty(s.Text))
goto EXIT;
System.Threading.Thread.Sleep(1000);
} while (!t.Elapsed);
throw new WatiN.Core.Exceptions.TimeoutException("...", 60 * 60));
EXIT:
Assert.AreEqual(true, s.Text.Contains(https://www.velodoc.net/));
}
Conclusion
The beauty of WatiN is that it builds on top of C# and .NET framework. Accordingly you get not only a rich language but also a rich environment. Test code built with WatiN can be executed within NUnit and Visual Studio unit testing projects which means that they can also be executed for load tests which I am going to try next although we know already that launching several instances of IE has its own limitation.
Tuesday, December 19, 2006
New incompatibility between ASP.NET Ajax 1.0 RC and Google AdSense
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager" runat="server" >
<Scripts>
<asp:ScriptReference Name="PreviewScript.js" Assembly="Microsoft.Web.Preview" />
</Scripts>
</asp:ScriptManager>
<div>
<script type="text/javascript"><!--
google_ad_client = "pub-6623312146541354";
google_ad_width = 250;
google_ad_height = 250;
google_ad_format = "250x250_as";
google_ad_type = "text";
google_ad_channel = "";
google_color_border = "000000";
google_color_bg = "F0F0F0";
google_color_link = "0000FF";
google_color_text = "000000";
google_color_url = "008000";
//--></script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
</form>
</body>
</html>
ASP.NET Ajax page method on login page requires setting location in web.config
If you have an ASP.NET web site with forms authentication and your login page has an ASP.NET Ajax extensions page method, this method will not work unless you set:
<location path="login.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
Otherwise, the call to ~/login.aspx/yourScriptMethod fails because it is not authenticated.
Monday, November 27, 2006
Migration from Atlas July CTP to ASP.NET Ajax Beta 2
I am developing an application which does not really make use of Atlas controls but has a significant amount of Atlas scripting code to migrate.
I am not found of declarative scripting but maybe I am old-fashioned: I like to step through my code to debug it. My opinion is that declarative scripting is only good as the output of code-generation tools. It is not something that developers should write in a text editor.
So, I have got script to migrate and I have read the documentation available at:
- http://weblogs.asp.net/scottgu/archive/2006/11/08/ASP.NET-AJAX-1.0-Beta-2-Release.aspx
- http://ajax.asp.net/files/AspNet_AJAX_CTP_to_Beta_Whitepaper.doc
- http://ajax.asp.net/files/Migration%20Guide.doc
- http://ajax.asp.net/docs/default.aspx
Downloading and installing ASP.NET Ajax Beta 2 is well explained in the documentation but I had to do a bit of guessing as well as exploring Microsoft’s code to migrate my own code. I deliver my findings below:
Migrating client script
- To use client scripting of html components, you need to add a reference to PreviewScript.js in your ScriptManager as shown below:
<asp:ScriptManager ID="ScriptManager" runat="server">
<Scripts>
<asp:ScriptReference Assembly="Microsoft.Web.Preview"
Name="Microsoft.Web.Resources.ScriptLibrary.PreviewScript.js"/>
</Scripts>
</asp:ScriptManager>
- $(id) is now $get(id)
- The Sys.UI namespace is now Sys.Preview.UI
- Sys.UI.Select is now Sys.Preview.UI.Selector
- Sys.UI.CheckBox.click.add(handler) is now Sys.UI.Preview.CheckBox.add_click(handler)
- Sys.UI.Select.selectionChanged.add(handler) is now Sys.Preview.UI.Selector.add_selectionChanged(handler)
- $addHandler/$removeHandler is the new way to add event handlers
- Sys.UI.Control.get_enabled() and set_enabled() no more work
Migrating web service calls
- You need to decorate your web services and page methods with new attributes as explained in http://blogs.msdn.com/sburke/archive/2006/10/21/hint-components-that-use-web-services-with-asp-net-ajax-v1-0-beta.aspx.
- The prototype of asynchronous calls to web services and page methods has been simplified, but this is well explained in the documentation listed above.