Friday, January 21, 2011

ASP.NET and asynchronous communication

Today I had to add a delete function to an old ASP.NET WebForms website. It was missing because there are a lot of relational data. So the steps to delete a record are:
- Click delete button
- Proof of existing relational data
- Show the result to the customer (and ask what to do)
- Delete all or cancel the delete action

Because I'm used to work with ASP.NET MVC, I thought on jQuery to solve the problem. Async calls to an Action on a Controller class and showing the result in a modal popup are easy tasks to do in ASP.NET MVC. This because of the MVC architecture, specially the Routing Engine used in MVC.
But in this case, I had to deal with ASP.NET WebForms and no routing to a Controller class. So how to solve the problem? I saw four different ways to do it:
1) Build a WCF Service and call it with jQuery
2) Create a ashx handler and call it with jQuery
3) Set the [WebMethod] Attribute to a method in the aspx page and call it with jQuery
4) Use the ScriptManager, the [WebMethod] and [ScriptMethod] Attribute


The first option (1), building a WCF Service is to much work for this small task.


The secound option (2) is quite good. The only thing I don't like is, I have to deal with two files what makes maintainance harder. Let's take a look at this solution anyway.
The jQuery code to call the handler looks like:

$(document).ready(function () {
$("#deleteButton").click(function () {
$.ajax({
type: "POST",
url: "Handler1.ashx",
data: "{'siteId':'" + id + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
// What you like to do on success
},
fail: function (msg) {
// What you like to do on error
}
});
});
});

The Handler (ashx-File) can be added easily with Visual Studio. Just select the Generic Handler template. The code looks like:

public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// Check for relational data and generate the message
var message = "Generated message for the user";

context.Response.ContentType = "text/plain";
context.Response.Write(message);
}
...
}


The third option (3) is in this case my favorite. Simple and easy. The jQuery call is the same, just the URL changes to something like
...
url: "SiteName.aspx/IsDeletable",
...
where the parameter after the slash is the name of the method.
In the ASPX-File we have to add a static method and decorate it with the [WebMethod] attribute. That's it! The code looks like:

[WebMethod]
public static string IsDeletable(Guid siteId)
{
// Check for relational data and generate the message
var message = "Generated message for the user";
return message;
}

IMPORTANT: The method has to be static.


The last option is ASP.NET WebForms specific and uses the ScriptManager. In my opinion do we have a better solution with the jQuery version. Anyway, here is what you need:

Add a ScriptManager as follow:
... ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" ...

Add JavaScript code to make the call:
...
PageMethods.IsDeletable(id);
...
Notice that this is just the call. Get and handle the return value has to be added as well.

And on the method in our aspx-File we do need an additional attribute:
[System.Web.Script.Services.ScriptMethod()]


Now it's up to you to choose your right solution.

Friday, January 14, 2011

Everything just random?

Today I had to fix some code of a colleague. To test the class I've fixed, there was a mock class generating random testdata. But this testdata were always the same. So I looked also at this problem and found the following code:

for (int i = foo; i < bar; i++)
{
return new Random().Next();
}

Looks good at first glance, but this will always return the same number (at least in the same second). This is because the Random class uses in the default constructor a time-dependent default seed value.

An easy way to fix the problem would be to use the overloaded constructor and provide a unique seed value. For example just the int value i used for the for loop. This could look like:

for (int i = foo; i < bar; i++)
{
return new Random(i).Next();
}

Another way to get random numbers would be in using the Next method in a correct way. This meens on the same instance of the Random class. In this case the initialization of the Random class has to be outside the loop. The code would look like this:

var r = new Random();
for (int i = foo; i < bar; i++)
{
return new r.Next();
}

This way would definitely be better, then we need just one instance of the Random class.

Further information on the Random class can be found here http://msdn.microsoft.com/en-us/library/system.random.aspx.

Tuesday, January 04, 2011

Relaunch

Welcome back!
After a pretty long break in blogging I'm starting over again. Trivadis gave me a good reason for it ;-) Hopefully there are coming up a lot of interesting themes in 2011.

I'm sure ASP.NET MVC will be big also this year with the release of version 3. I'm doing definitely some interesting post about it. But my first activity is a speech for MSUGS on February 17, 2011. For more infos visit MSUGS. And I will do a session at TechDays 2011 in May as well.

Further there will be the first public beta release of Silverlight 5 in spring with many new cool features like:

  • Richer Media Support
  • 3D Support
  • P/Invoke
  • Elevated rights in the browser
  • Vector printing
  • Multiple windows (out-of-Browser only)
  • Improved DataBinding (almost like in WPF)
  • Custom MarkupExtensions
  • Debugging DataBinding
  • UI Testing

So stay tuned!