A JavaScript Stack Trace in ASP.NET AJAX

Something came up in that work recently that I’ve found to be quite useful in my day to day coding sessions and that’s how to create a stack trace in ASP.NET AJAX.
For starters, JavaScript doesn’t provide an easy way of pulling the stack trace of the call so we’re going to have to roll our own.

I’ve seen a couple of different methods of creating the stack trace and the one I’m going to use comes from Helephant.com. I really like this implementation and I’m glad that I was able to poach somebody else’s code to create the stack trace (thx Helen!) rather than have to create mine from scratch.

From Helen’s post on Helephant.com we can see that there are three main functions to generate the stack trace: getFunctionName, getSignature, and stackTrace. Since we’re deep in the ASP.NET AJAX world I’ve updated the code to rely upon it and look more like code written for it. The code is below.

/// <reference name=”MicrosoftAjax.js />

/// Adopted from: http://www.helephant.com/Article.aspx?ID=675

_StackTrace = function() {

_StackTrace.initializeBase(this);
};
_StackTrace.prototype = {
_getFunctionName: function(theFunction) {
if(theFunction.name) {
return theFunction.name;
}
var definition = theFunction.toString();
var name = definition.substring(definition.indexOf(‘function’) + 8,definition.indexOf(‘(’));
if(name) {
return name;
}
return“anonymous”;
},
_getSignature: function(theFunction) {
var signature = newSys.StringBuilder(this._getFunctionName(theFunction));
signature.append(“(”);
for(var x=0; x < theFunction.arguments.length; x++) {
var nextArgument = theFunction.arguments[x];
if(nextArgument.length > 30) {
nextArgument = nextArgument.substring(0, 30) + “…”;
}
signature.append(String.format(“‘{0}’”, nextArgument));

// comma separator

if(x < theFunction.arguments.length – 1) {
signature.append(“, “);
}
}
signature.append(“)”);
return signature.toString();
},
createStackTrace: function(startingPoint) {
var stackTraceMessage = newSys.StringBuilder(“Stack trace: \n”);
var nextCaller = startingPoint;
while(nextCaller) {
stackTraceMessage.appendLine(this._getSignature(nextCaller));
nextCaller = nextCaller.caller;
}
stackTraceMessage.appendLine();
stackTraceMessage.appendLine();
return stackTraceMessage;
}
};
_StackTrace.registerClass(“_StackTrace”);
Sys.Application.add_init(
function() {
StackTrace = new_StackTrace();
}
);
Sys.Application.notifyScriptLoaded();

Looking at the code, its basic job is to walk the caller pointer attached to the implicit arguments variable available in every function and derive a stack trace. Pretty straigh-forward.

So you might be thinking, if somebody else wrote the stack trace code, why is this guy writing a blog entry and not providing anything new except for a few minor tweaks to the stack trace code? Well, turns out that the stack trace is only 1/2 the battle. If you use this stack trace code or any other stack trace code that you might have written or come across, you’re going to run into a seriously annoying problem if your JavaScript uses the prototyping feature to construct objects. If you use the prototype feature to create your object and then attempt to pull the stack trace, all of your method names are going to be anonymous, which is really unhelpful. To illustrate this problem, we’ll use another object defined below and then execute the sayHello method from a test page.

/// <reference name=”MicrosoftAjax.js” />

Type.registerNamespace(“Animal”);Animal.Dog = function() {this._speech = “Arf!”;};
Animal.Dog.prototype = {
_speak: function() {
var trace = StackTrace.createStackTrace(arguments.callee);
alert (trace);
},
sayHello: function() {
this._speak();
}
};
Sys.Application.notifyScriptLoaded();

In this object we expose a public method, sayHello off of our Animal.Dog object. Nothing important at here except that in our _speak method we make a call to our StackTrace class and execute the createStackTrace method.

Finally, we create a small test page that executes the sayHello method when it loads. The important section is listed below.

<asp:ScriptManagerID=”SM1″runat=”server”>
<Scripts>
<asp:ScriptReferencePath=”~/StackTrace.js” />
<asp:ScriptReferencePath=”~/StackTraceTester.js” />
</Scripts>
</asp:ScriptManager>
<script type=”text/javascript”>

functiontester () {
var test = newAnimal.Dog();
test.sayHello();
}
Sys.Application.add_init(tester);
</script>

Executing the following code gives us the following output.


Stack Trace

Reading the stack trace from top to bottom states that we executed an anonymous method, followed by another anonymous method, followed by our tester method, and so on. What’s striking about this stack trace is how useless it is! The anonymous method name does not help us at all for figuring out where our stack trace originated from. Can you imagine how much of a pain this would be if our stack was deeper and we had a large library of code?

Anyways, we can fix this problem, and it requires us using a technique seen in the MicrosoftAjax.debug.js file; the main ASP.NET AJAX file. In that file, Microsoft provides what can best be described as debug method names for its methods so that “anonymous” doesn’t appear in the call stack. For this example, we’ll update our Animal.Dog classes well as our StackTrace class using this method. Below is the code from the updated Animal.Dog class and the StackTrace class is updated similarly.

/// <reference name=”MicrosoftAjax.js />

Type.registerNamespace(“Animal”);

Animal.Dog = functionAnimal$Dog() {

this._speech = “Arf!”;

};

Animal.Dog.prototype = {

_speak: functionAnimal$Dog$_speak() {

var trace = StackTrace.createStackTrace(arguments.callee);

alert (trace);

},

sayHello: functionAnimal$Dog$sayHello() {

this._speak();

}

};

Sys.Application.notifyScriptLoaded();

We’ve made changes to both the constructor and the methods. In the constructor we named our constructor function Animal$Dog. We named it using the dollar sign instead of the period (.) because in JavaScript a period is not valid in a function name. For the functions, we named them using the object type followed by the name of the function.

Now when we execute our test page we get the following output.


Stack Trace2

As you can see, our anonymous methods that were present in the first stack trace have turned into named methods. This is quite useful for tracing our execution. Not only does this provide us with a way to build a stack using our StackTrace object, but it gives us the method names in the Call Stack window in Visual Studio.

Call Stack Window

If you have better solution, just tell me

ASP.NET AJAX and SharePoint

One of the questions I was recently asked at a user group meeting in Europe was whether it was possible to use ASP.NET AJAX within SharePoint 2007 solutions. This was a common enough question that the SharePoint team recently blogged about their plans with ASP.NET AJAX to help answer it. You can read their post here.

At a highlevel, official support for ASP.NET AJAX within SharePoint will be coming with the first service pack of SharePoint 2007. This is because SharePoint 2007 shipped before ASP.NET AJAX 1.0 did, and so there is some work the SharePoint team needs to-do to make it integrate nicely.

In the meantime, though, you can read the SharePoint team's blog post here on how to install ASP.NET AJAX 1.0 on a SharePoint 2007 site and start using its functionality today. There are some caveats to using it until the first service pack ships - but the steps in their blog post will help you start using it immediately. Also make sure to check out Eric Schoonover's blog post on a custom AjaxBasePart web part that his team has created to help with using ASP.NET AJAX within custom web parts you build.

SharePoint and ASP.NET Developer Information

For more information on SharePoint and Web Parts, please check out these past posts of mine:

SharePoint 2007 -- Built on ASP.NET 2.0
Office 2007, VS 2005 Tools for Office, and VS 2005 Extensions for SharePoint
Writing Custom Web Parts for SharePoint 2007
Also check out the SmartPart control plug-in for SharePoint 2007 that allows you to deploy any ASP.NET 2.0 user control as a web part within SharePoint 2007.

SharePoint and ASP.NET Web Part Development Books

While on the subject of SharePoint Developer and ASP.NET Web Parts, there are two great books on SharePoint development that I've been hearing very good things about lately. The first book is Todd Bleeker's "Developer's Guide to the Windows SharePoint Services v3 Platform" which has a 5 star rating (out of 5) on Amazon after 11 reviews, and which has been burning up the Amazon most popular lists the last few months:

The second book is Darren Neimke's "ASP.NET 2.0 Web Parts in Action: Building Dynamic Web Portals" which provides a great way to learn how to build sites that use ASP.NET 2.0 Web Parts, as well as how to build custom Web Parts of your own:

The beauty of web parts is that with ASP.NET 2.0 you can now build ones that can work and be customized by end-users within any ASP.NET web site/application (no SharePoint required), as well as have these same web parts work and run within SharePoint 2007 (both the free Windows SharePoint Services edition as well as the Microsoft Office SharePoint Server version). This provides a tremendous amount of developer power, and opens up a lot of options.

Free Application Templates for Windows SharePoint Services 3.0

One of the things the SharePoint team has been very focused on the last few months has been with putting together free application templates that you can download and use with Windows SharePoint Services 3.0 (which is the free version of SharePoint that you can download and install on any Windows Server box).

You can learn more about these application templates here. Below is a list of some of the templates with custom web parts provided for free download today:Board of Directors
Business Performance Reporting Case Management for Government Agencies Classroom Management Clinical Trial Initiation and Management Competitive Analysis Site Discussion Database Disputed Invoice Management Employee Activities Site Employee Self-Service Benefits Employee Training Scheduling and Materials Equity Research Integrated Marketing Campaign Tracking Manufacturing Process Management New Store Opening Product and Marketing Requirements Planning Request for Proposal Sports League Team Work Site Timecard Management

What is great about these templates is that once you download and install them, you can optionally add custom ASP.NET web parts to it, and use standard ASP.NET 2.0 techniques to customize it further. This makes it dramatically easier to build and deploy common solution applications.

ASP.NET Add AutoNumber Column in GridView or DataList

Several times we need to display Auto Number or serial number for displaying records in gridview or other similar controls in ASp.NET.We can add AutoNumber column by using Container.DataItemIndex property in html markup of the Gridview.
We can add AutoNumber column by using Container.DataItemIndex property in html markup of the Gridview.




Here's the sample html markup for the page


<title>Auto Number Cloumn in GridView </title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" runat="server"
AllowPaging="True" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1" PageSize="6"
AlternatingRowStyle-BackColor="#006699"
AlternatingRowStyle-ForeColor="#FFFFFF" >
<Columns>
<asp:TemplateField HeaderText="Serial Number">
<ItemTemplate>
<%# Container.DataItemIndex + 1 %>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="Name"
SortExpression="Name" />
<asp:BoundField DataField="Location" HeaderText="Location"
SortExpression="Location" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT [Name], [Location] FROM [Details]">
</asp:SqlDataSource>


Hope this helps.

Ajax form validation in Confluence plugin using a JSON request

Today I describe how to make Ajax requests to XWork actions inside a Confluence plugin. A good example is server-side form validation. User fills a form, clicks Submit, then we validate the form in background and if there are no errors we allow submitting the form, otherwise show field errors.

Suppose we have a simple user info form with input fields like name, department, email etc:

<form id="saveform" action="doUpdate.action" method="post">
#tag( TextField "name='user.name'" "size='50'" )
#tag( Select "name='user.department'"
"list=departmentsDao.all"
"listKey=name" "listValue=name"
"emptyOption='true'" )
#tag( TextField "name='user.email'" "size='50'" )
...
#tag( Submit "id=userformsubmit"
"name='save'" "value='dot.button.save'"
)
#tag( Submit "name='cancel'" "value='dot.button.cancel'" )
</form>

One way to make form validation is to write it in javascript, but what if you already have it implemented in action? Write everything again? Maybe it's better to use existing server side code so you can switch on/off Ajax at any time and you'll not have the same logic implemented twice.

Here are the required steps:

edit atlassian-plugin.xml and create a package for you application with validation enabled, declare an action doUpdate for submitting a form and editValidate for Ajax validation.

<package name="userinfo" extends="default"
namespace="/dot/users"&gt;
<default-interceptor-ref name="validatingStack"/>
...
<action name="doUpdate"
class="dot.userinfo.users.action.EditUserInfo"
method="save">
<external-ref name="dotUsersDao">
usersDao</external-ref>
<external-ref name="dotDepartmentsDao">
departmentsDao</external-ref>
<external-ref name="dotCitiesDao">
citiesDao</external-ref>
<result name="input" type="velocity">
/templates/dot/userinfo/users/edituser.vm</result>
<result name="success" type="redirect"&gt;
/dot/users/usercard.action?id=${user.id}</result>
<result name="cancel" type="redirect">
/dot/users/observe.action</result>
</action>
...
<action name="editValidate"
class="dot.userinfo.users.action.EditUserInfo">
<result name="input" type="json" />
<result name="success" type="json" />
</action>
...
</package>

Action editValidate will be called in Ajax from javascript. In my experience, both input and success return types are required. input is returned in case of any field errors, success when everything is ok. Actually there is no need to return success to javascript, but instead I could save the form and redirect to another form. I'll try this in next post.

public class EditUserInfo
extends ConfluenceActionSupport
implements JSONAction {
...
public String getJSONString() {
try {
if (hasFieldErrors()) {
StringBuffer sb = new StringBuffer();
sb.append("[");
Map fieldErrors = getFieldErrors();
for (Object field : fieldErrors.keySet()) {
List<Object> msg =
(List<Object>) fieldErrors.get(field);
if (field != null && msg != null
&& msg.get(0) != null) {
sb.append("{field:'"+field+"',
error:'"+msg.get(0)+"'},");
}
}
if (sb.length() > 1) {
sb.deleteCharAt(sb.length()-1);
}
sb.append("]");
return sb.toString();
}
} catch (Exception e) {
// handle exception
}
return "";
}
}

By the time getJSONString() method is called validation was already done by WebWork so we can immediatelly process the errors. Here I generate a Javascript array of all field errors which I want to show next to input fieds. Write EditUserInfo-validation.xml file in the same package as java class. My validation file looks something like this

<validators>
<field name="user.name">
<field-validator type="requiredstring">
<message key="dot.field.error.required" />
</field-validator>
</field>
<field name="user.department">
<field-validator type="requiredstring">
<message key="dot.field.error.required" />
</field-validator>
</field>
<field name="user.email">
<field-validator type="requiredstring">
<message key="dot.field.error.required" />
</field-validator>
<field-validator type="email">
<message key="dot.field.error.email" />
</field-validator>
</field>
</validators>
Main stuff is done, last thing we need is to call validation from Javascript and show error messages.
  • attach click event to submit button
$("#userformsubmit").click(function(e) {
try {
var form = $("#saveform");
validateForm(form);
} catch (e) { alert(e); }
return false; // always!
});
  • My validateForm looks like this
function validateForm(form) {
$.ajax({url: "editValidate.action",
data: form.serialize(),
success: function(data) { try {
var fields = $("#saveform span.fielderror");
// delete old errors,
// error spans are found by class name

fields.html("");
// set received errors, iterate through span IDs
data = eval(data);
if (data && data.length > 0) {
for (i in data) {
var id = data[i].field.replace(/\./, "\\.")+
"-error";
var fe = $("#"+id);
if (fe) { fe.html(data[i].error); }
}
return false;
}
$("#saveform").submit();
return true;
} catch (e) { alert(e); } }
});
return false;
}

Here for every input control I have span with id ending with '-error' and class 'fielderror'. I still haven't tried to write macros so I implemented a separate file fielderror.vm

<span id="$!webwork.htmlEncode($f)-error"
class="fielderror">
#set( $err = $fieldErrors.get($f) )
#if( $err.size() > 0 )
$err.get(0)
#end
</span>
which I include in main page next to input fields. Example for user name field:

#set( $f = "user.name" )
#parse( "/templates/dot/userinfo/fielderror.vm" )

Next week I'll try to optimize the code. In current implementation I believe validation is called twice: 1st time in ajax, and 2nd time when form is submitted (this we can escape), for field errors I need macro..

JScript IntelliSense: Working with jQuery


JScript IntelliSense: Working with jQuery

We have good news for jQuery fans. The hotfix we released today fixes a bug in IntelliSense where it would fail with jQuery. Any page with jQuery should just work now. While experimenting with this new-found functionality today, I found annotating the library with a few XML Doc Comments really made a big difference. The key is to add a return type of "jQuery" like this:

doc comments

Here's some jQuery chaining with IntelliSense:

completion list


tooltip

There were only a few functions that (due to the way they were declared) were not able to be annotated. Special thanks to Brennan where I borrowed the comments from. If anyone will be making a fully annotated version of jQuery, I'd be happy to post a link to it from here.

To install the Ajax Control Toolkit

To install the Ajax Control Toolkit, first download the zip file from http://www.asp.net/ajax/3.5 SP1 Release is here.
Unzip the files into any directory. Give it a name like "AjaxControlToolkit."



Open your Visual Web Developer and right click in the Toolbox area. Select "Add Tab."



Name the tab with something like "Ajax Tookit."



Right click the new tab area, and select "Choose Items..."



This will bring up a dialog box to "Choose Toolbox Items." Select the "Browse" button.



Browse to the directory where you unzipped the Ajax Toolkit files. There is a "SampleWebSite" directory within your "AjaxControlToolkit" directory. Browse to the "Bin" directory within the "SampleWebSite" directory.



Find and select to open the "AjaxControlToolkit.dll" file.



The Choose Toolbox Items dialog will appear, this time with the Ajax Tookit controls selected. Select the "OK" button.


Open or create a web form within your project. Now when you open your toolbox, you will see all of the Ajax Control Toolkit controls, ready for use within your applications.

May your dreams be in ASP.net! More Refernce Click Here

How to Write An SPQuery Using Multiple AND OR Operators

Ok, if you’re like me, writing CAML queries can sometimes make your head hurt. Not because it’s terribly complicated, but because there’s not much useful information out there that demonstrates, with REAL examples, how these should be written. So let’s see if we can clarify this:

Scenario 1

Get me all items in a list WHERE fullName equals the currently logged in user.

1
2
3
4
5
6
7
8
9
10
11
SPWeb web = SPControl.GetContextWeb(Context);

string fullName = web.CurrentUser.Name;

SPQuery oQuery = new SPQuery();

oQuery.Query =
"<Where>" +
"<Eq><FieldRef Name='FullName'/><Value Type='Text'>'" + fullName + "'</Value></Eq>" +
"</Where>" +
"<OrderBy><FieldRef Name='StartTime' Ascending='FALSE'></FieldRef></OrderBy>";

Scenario 2

Get me all items in a list WHERE fullName equals the currently logged in user AND status equals ‘Complete’.

1
2
3
4
5
6
7
8
9
10
11
12
13
SPWeb web = SPControl.GetContextWeb(Context);

string fullName = web.CurrentUser.Name;

SPQuery oQuery = new SPQuery();
oQuery.Query =
"<Where>" +
"<And>" +
"<Eq><FieldRef Name='FullName'/><Value Type='Text'>'" + fullName + "'</Value></Eq>" +
"<Eq><FieldRef Name='Status'/><Value Type='Text'>Complete</Value></Eq>" +
"</And>" +
"</Where>" +
"<OrderBy><FieldRef Name='StartTime' Ascending='FALSE'></FieldRef></OrderBy>";

Scenario 3

Get me all items in a list WHERE fullName equals the currently logged in user AND status equals ‘Complete’ AND manager is James Lane.

This is where it gets a bit tricky. The following example is INCORRECT and will produce an error when run:

This is the correct way to do it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SPWeb web = SPControl.GetContextWeb(Context);

string fullName = web.CurrentUser.Name;

SPQuery oQuery = new SPQuery();
oQuery.Query =
"<Where>" +
"<And>" +
"<And>" +
"<Eq><FieldRef Name='FullName'/><Value Type='Text'>'" + fullName + "'</Value></Eq>" +
"<Eq><FieldRef Name='Status'/><Value Type='Text'>Complete</Value></Eq>" +
"</And>" +
"<Eq><FieldRef Name='Manager'/><Value Type='Text'>James Lane</Value></Eq>" +
"</And>" +
"</Where>" +
"<OrderBy><FieldRef Name='StartTime' Ascending='FALSE'></FieldRef></OrderBy>";

Scenario 4

Get me all items WHERE fullName equals the currently logged in user AND status equals ‘Complete’ OR status equals ‘On Hold’.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SPWeb web = SPControl.GetContextWeb(Context);

string fullName = web.CurrentUser.Name;

SPQuery oQuery = new SPQuery();
oQuery.Query =
"<Where>" +
"<And>" +
"<Eq><FieldRef Name='FullName'/><Value Type='Text'>'" + fullName + "'</Value></Eq>" +
"<Or>" +
"<Eq><FieldRef Name='Status'/><Value Type='Text'>Complete</Value></Eq>" +
"<Eq><FieldRef Name='Status'/><Value Type='Text'>On Hold</Value></Eq>" +
"</Or>" +
"</And>" +
"</Where>" +
"<OrderBy><FieldRef Name='StartTime' Ascending='FALSE'></FieldRef></OrderBy>";

I really do recommend if you’re doing any work with CAML queries that you download the U2U CAML Query Builder 2007. It doesn’t come without it’s issues, for example, doing a query on a list with a column of type Lookup does not always yield the results I would expect, but it’s still quite helpful. I also often find myself changing the Value Type from Lookup to Text but other than that it’s a huge resource when trying to determine if the data is actually in the list or if there is a problem with the query i’ve written.

Any feedback or questions, please drop me a line.

If you have better solution, just tell me !