måndag 19 maj 2008

ASP.NET Ajax and the need of UTF-8 encoding

When using ASP.NET Ajax and non standard characters in the page title (such as the swedish "ö"), the Ajax framework might stop working complaining about illegal use of "Response.Write, Response.Filter etc".

The problem has actually nothing to do with this but is related to the character encoding set in web.config. To make Ajax work with special characters the encoding of the "globalization"-element must be set to "UTF-8" in web.config.

The reasons is that the server will return a non legal coding for the special character which will mess up the javascript code in Ajax on the client side.

This is actually a quite old and commonly known issue, but personally I had totally forgot about it since it was a long time I read about it...

fredag 16 maj 2008

Problem with $find on TabContainer using Master Pages

If you've placed your TabContainer on a page using a Master page you can't get the behaviour of the TabContainer the usual way (which would work on a page without master):

var tabContainer = $find('TabContainer1');

Therefore, if your page has a Master Page you must instead use the $get method and send the UniqueId of the TabContainer as a parameter. Through the retrurned object, you can get the control object which represents the behaviour of the TabContainer:

var tabContainer = $get('<%= this.TabContainer1.ClientID%><%= TabPassengerInfo.ClientID%>').control;

torsdag 27 mars 2008

Use Extensions Methods to create those methods you always wanted...

With C# 3.0 and Visual Studio 2008 Microsoft gave us the power to extend existing classes with our own methods without doing any inheritance, partial classes etc.

This is done using virtual classes and virtual methods together with the new "this" keyword. Example:
namespace myExtensions
{
public static class Extensions
{
   public static int ParseToInt(this string s)
   {
      return int.Parse(s);
   }
}
}


We can now use this method:
string s = "123";
int i = s.ParseToInt();


As you can imagine this is a fantastic feature as we can create our own library of useful methods. One specific method that I've been missing is a generic way to obtain a control in the Repeater ItemDataBound event:
protected void myRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
   if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
   {
      ((Literal)e.Item.FindControl("myLiteral")).Text = "Something...";
   }
}


We can now create two useful extensions:
//Method to check whether the current RepeaterItem is of itemType "Item" or "AlternatingItem"
public static bool IsContentItem(this RepeaterItem item)
{
   return (item.ItemType == ListItemType.AlternatingItem || item.ItemType == ListItemType.Item);
}

//Method to retrieve a control from the RepeaterItem
public static T FindControl<T>(this RepeaterItem item, string id) where T : Control
{
   return item.FindControl(id) as T;
}


Usage:
protected void myRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.IsContentItem())
{
   e.Item.FindControl<Literal>("myLiteral").Text = "Something...";
}
}


Pretty nice huh? :)

fredag 14 mars 2008

Decimal type; howto control the decimal output

Formatting a decimal value to display only the applicable number of decimals might not seem to be an easy thing if you are using only the "ToString" method.

Example:
decimal d1 = decimal.Parse("100.510");
decimal d2 = decimal.Parse("100.00");
decimal d3 = decimal.Parse("100.50");


Lets say you want to output the value just with its applicable number of decimals, ie #1 = 2 decimals, #2 = 0 decimals and #3 = 1 decimal.

To do this, you definitely do not need to use any string formatting or such, instead simply use the ToString method with the the following format: "G29".
The solution is really simple and has been around since .NET 1.0.

Example:
d1.ToString("G29"); //100.51
d2.ToString("G29"); //100
d3.ToString("G29"); //100.5

onsdag 12 mars 2008

Using an anonymous type outside its scope

With C# 3.0, Microsoft introduced "Anonymous Types" which gives us the ability to create new types in runtime.

Example:
var x = new {Name = "Fredrik", Country = "Sweden"};
x.Name = "New Name";


As you can see, object X is assigned to a new type where the properties are created in runtime. Each property type is interpreted by the assigned value which means that we still have type safety.

The anonymous type is however only available in the current scope, ie in the current method, if-statement etc. This is fine, as we normally do not want to expose the type to external code as this code does not know anything about the new type or its properties.

There are however occasions where we might need the anonymous type outside the scope. Lets say within an ASP.NET Page where you bind a control (eg. Repeater) to a list of anonymous types. Example:

IEnumerable orders = GetOrders(); //get list of orders
IEnumerable orderLines = GetOrderLines(); //get another list of order lines

//create new list based on orders and orderLines
var list = from order in orders
join orderLine in orderLines on o.OrderId equals orderLine.OrderId
select new {Customer = o.CustomerName, LineAmount = orderLine.Amount};

//create a delegate method to handle the ItemDataBound event
this.repeaterOrders.ItemDataBound += new RepeaterItemEventHandler(repeaterOrders_ItemDataBound);

//bind the repeater
this.repeaterOrders.DataSource = list;
this.repeaterOrders.DataBind();


Now, in the method for "ItemDataBound" we want to cast the DataItem to the Anonymous type to be able to use it for the Repeater output.
We can do this be creating a new generic method that casts the object to the anonymous type.


private T Cast<t>(object o, T type)
{ return ( T )o; }


Using this in the code, looks like the following:


protected void repeaterOrders_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item e.Item.ItemType == ListItemType.AlternatingItem)
{

//cast the "DataItem" property into the anonymous type
var x = Cast(e.Item.DataItem, new {Customer="", LineAmount=0});

//use the x object with ites properties based on the anonymous type
totalAmount+= x.LineAmount;

}
}


As you can see, the "client" using the Cast method must know the internal structure of the anonymous type. This is not a very nice solution when passing data between different layers, but when used in the same ASP.NET page or class I feel that it is a quite nice solution to solve the problem. And in the end...that's what really matters.

onsdag 13 februari 2008

Don't be to quick on blaming the Ajax Accordion

The ASP.NET Ajax Accordion control is a powerful and easy to use control to create nice GUI.

However, the Accordion has one famous bug related to server side buttons located inside an AccordionPane (More on that bug here).

When having problems with server side controls located in an AccordionPane you are therefore quick to blame the Accordion for controls that does not trigger or work properly. So, you end up spending a lot of time trying to make it working using all dirty hacks you can Google on this issue.

Exactly this happend to me recently.
In this case I had two AccordionPanes, one with the button and one with a UserControl containing Textboxes as well as a few Validators. As I couldn't see neither the textboxes nor the validators the result was that of course, my button triggered the validators which probably displayed their message in the hidden AccordionPane...but for me, I blamed it all on the Accordion and started to Google and tweak it to obey my will. I even removed the whole thing and created an AnimationExtender to the exact same thing...

Conclusion; use your basic knowledge first when it comes to finding bugs.

onsdag 6 februari 2008

ASP.NET Ajax Services

A simple but yet powerful feature in ASP.NET is the ability to call a server side Webservice using Javascript.

Simple add an <asp:ServiceReference> node to your <ScriptManager>, example:
<asp:ScriptManager ID="sctMgr" runat="server">
<Services>
<asp:ServiceReference Path="~/AjaxService/Service.asmx" />
</Services>
</asp:ScriptManager>

Assume that you in your "Service.asmx" have the following declaration:
[WebMethod()]
public string UpdateData(string inputData)
{
//do something with "inputData"...

//return something...
return DateTime.Now.ToString();
}


This will enable us to do the following from a javascript:
<script type="text/javascript">
Service.UpdateData("ABC");
</script>


Using Visual Studio 2008 you will even get intellisense for the Web Methods in your service.

To retrieve the return value from the Web Method we simply add a call back method:
function OnServiceUpdateComplete(result)
{
alert("The Result from the Web Method call was: " +result);
}


...and associate it with the service call:
<script type="text/javascript">
Service.UpdateData("ABC", OnServiceUpdateComplete);
</script>