måndag 19 maj 2008

DropDownList databinding versus manually adding ListItems: divergence of behavior

Symptom:
The following two ways of rendering data from a given datasource may yield two completely different results.

Datasource:
List<foo> items = new List<foo>();
{
   new Foo { Text = "A", Value = null },
   new Foo { Text = "B", Value = null },
   new Foo { Text = "C", Value = null }
}

Figure 1, databinding:
ddl.DataSource = items;
ddl.DataTextField = "Text";
ddl.DataValueField = "Value";
ddl.DataBind();

Figure 2, manually adding items:
foreach(Foo item in items)
   ddl.Items.Add(new ListItem(item.Text, item.Value));

Figure 1 will yield the following result:
<select ...>
   <option value="">A</option>
   <option value="">B</option>
   <option value="">C</option>
</select>

Figure 2, however, slightly deviates from this behavior, in that all values are assigned, even though they were null in the datasource:
<select ...>
   <option value="A">A</option>
   <option value="B">B</option>
   <option value="C">C</option>
</select>

Cause:
The reason why Figure 2 renders different client code, is the following way in which the Value for a ListItem is retreived (whereas the native databinding method doesn't bother with the detour of using ListItems, but simply renders the source as HTML):
public string Value
{
   get
   {
      if (this.value != null)
         return this.value;
      if (this.text != null)
         return this.value;
      return String.Empty;
   }
   ...
}

Thus, the value retreived in Figure 2 is that of the Text property, since the Value property is null.

Outcome:
While there is nothing particularly discomforting about any of the two approaches to rendering the same data, it is worth remarking that there are differences between them, and that code written in one way cannot always be rewritten in another, without unexpected side-effects.

How to start an SQlserver Agent from a Script.

Run this script in a query window agains Master DB, and if you have the rights to execute this SP (xp_servicecontrol) then it will start the sqlserverAgent even if you dont have access to SQlServer Configuration Manager. Or the server via Remote.

------------------------------------------------------------------------------------
DECLARE @Err int, @Msg varchar(100), @ServiceName sysname
SET @ServiceName = 'SQLServerAgent'

EXEC master.dbo.xp_servicecontrol 'START', @ServiceName

SET @Err = @@ERROR
IF @Err = 0

BEGIN
RAISERROR ('Successfully started SQL Server Agent', 1, 1) WITH LOG
END
ELSE
BEGIN
SET @Msg = 'Error occured while starting SQL Server Agent. Error code: ' + STR(@Err) RAISERROR (@Msg, 18, 1) WITH LOG
END
END

GO
------------------------------------------------------------------------------------

For startin the SqlServerAgent automatically when it goes down:

EXEC sp_procoption 'AutoStart_SQLAgent', 'startup', 'true'GO

------------------------------------------------------------------------------------

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.