tisdag 4 augusti 2009

Sorting in nHibernate using an aggregate function

I was recently porting the data layer in an application from LINQ to SQL to nHibernate.
While doing this I found some parts that turned out to be somewhat more tricky in nHib then in plain LINQ.

First, lets imaging we have the following bi-directional objects:

class Item
{
public int ID {get;set;}
public int Type {get;set;}
public List Reviews {get;set;}
}

class ItemReview
{
public int ID {get;set;}
public Item Item {get;set;}
public int Grade {get;set;}
}

class ItemProjection
{
public Item Item {get;set;}
public int GradeCount {get;set;}
}

Consider the following LINQ query:
var items =
db.Items
.Where(i=>i.Type==5)
.Select(i=> {
return new ItemProjection()
{
Item = i,
Grade = i.ItemReviews.Sum(x=>x.Grade)
};
})
.OrderByDescending(x=>x.Grade).Take(5).ToList();

Basically what we are doing is that we select the 5 items which has the highest summary of review grades and project those into a new object. LINQ to SQL does a fantastic job to translate this into one single SQL query that works perfectly.

Now over to nHibernate. First I thought that "LINQ to nHibernate" would be smart enough to translate the query into a valid SQL statement. Well, as you can imagine, it did not work.

So, I turned to Google and the nHibernate documentation and started to look a "Projection" and "aliases". By using "Projections" you can create aggregate functions in the query that can be used as an order statement.

This is what I came up with:
var criteria = session.CreateCriteria("itemReview")
.CreateAlias("itemReview.Item", "item")
.SetProjection(
Projections.ProjectionList()
.Add(Projections.Sum("Grade"), "gradeSum")
.Add(Projections.GroupProperty("Item"))
)
.AddOrder(Order.Desc("gradeSum"))
.Add(NHibernate.Criterion.Expression.Eq("item.TypeID", typeID));
criteria.SetMaxResults(top);
var list = criteria.List();
return list.Select(o =>return new ItemProjection() {Item=(Item)o[1], Grade=(int)o[0]).ToList();


We start to create a "Criteria" for the "ItemReview" and then we add a few aliases followed by a "ProjectionList" that includes one "Sum" and on "GroupProperty" projection. The Summary is then used as an Order criteria. At last we "List<>" the criteria using the "object[]" type and projects the list into the "ItemProjection" type (I know, I know, the uggly cast between the object array and the properties isn't very nice...).

tisdag 19 maj 2009

Extended OrderBy

Extension methods for OrderBy and ThenBy methods, introducing two new features:
* The possibility to determine sort direction ascending/descending by passing a boolean value, rather than using a whole different method.
* The possibility to pass a string value for the property to sort by, which will be resolved using reflection

Both features may come in handy when sorting depends upon user input, such as the ability to resort a table by clicking table headers.

Courtesy of David Hedlund.

public static IOrderedEnumerable<TResult> OrderBy<TResult>(this IEnumerable<TResult> source, string propertyName)
{
   return OrderBy(source, propertyName, true);
}

public static IOrderedEnumerable<TResult> OrderByDescending<TResult>(this IEnumerable<TResult> source, string propertyName)
{
   return OrderBy(source, propertyName, false);
}

public static IOrderedEnumerable<TResult> OrderBy<TResult>(this IEnumerable<TResult> source, string propertyName, bool ascending)
{
   System.Reflection.PropertyInfo prop = typeof(TResult).GetProperty(propertyName);
   Func<TResult, object> orderBy = (i => prop.GetValue(i, null));
   return source.OrderBy(orderBy, ascending);
}

public static IOrderedEnumerable<TResult> OrderBy<TResult,TKey>(this IEnumerable<TResult> source, Func<TResult, TKey> keySelector, bool ascending)
{
   Func<Func<TResult, TKey>, IOrderedEnumerable<TResult>> orderMethod = source.OrderBy;

   if(!ascending)
      orderMethod = source.OrderByDescending;

   return orderMethod.Invoke(keySelector);
}

public static IOrderedEnumerable<TResult> ThenBy<TResult>(this IOrderedEnumerable<TResult> source, string propertyName)
{
   return ThenBy(source, propertyName, true);
}

public static IOrderedEnumerable<TResult> ThenByDescending<TResult>(this IOrderedEnumerable<TResult> source, string propertyName)
{
   return ThenBy(source, propertyName, false);
}

public static IOrderedEnumerable<TResult> ThenBy<TResult>(this IOrderedEnumerable<TResult> source, string propertyName, bool ascending)
{
   System.Reflection.PropertyInfo prop = typeof(TResult).GetProperty(propertyName);
   Func<TResult, object> orderBy = (i => prop.GetValue(i, null));
   return source.ThenBy(orderBy, ascending);
}

public static IOrderedEnumerable<TResult> ThenBy<TResult,TKey>(this IOrderedEnumerable<TResult> source, Func<TResult, TKey> keySelector, bool ascending)
{
   Func<Func<TResult, TKey>, IOrderedEnumerable<TResult>> orderMethod = source.ThenBy;

   if(!ascending)
      orderMethod = source.ThenByDescending;

   return orderMethod.Invoke(keySelector);
}

tisdag 31 mars 2009

Removing a subdirectory from your application will cost you your session state

Encountered a curious error, with users being logged out from an admin application, when they removed a folder. Turns out the behavior is by design: Removing a folder anywhere in your application, programatically or manually, will cause a full AppDomain recycle, in just the same manner as uploading a DLL file to bin or making a change to web.config does, and that's all there's to it.

Managed to come up with only one work-around, that'll still allow the file change notifier to monitor web.config and bin directory, and it's not very pretty, but it seems to work:
private void SafelyDeleteFolder(string folder, bool recursive)
{
   //FIX disable AppDomain restart when deleting subdirectory
   //This code will turn off monitoring from the root website directory.
   //Monitoring of Bin, App_Themes and other folders will still be operational, so updated DLLs will still auto deploy.

   System.Reflection.PropertyInfo p = typeof(HttpRuntime).GetProperty("FileChangesMonitor", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);

   object o = p.GetValue(null, null);
   System.Reflection.FieldInfo f = o.GetType().GetField("_dirMonSubdirs", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.IgnoreCase);

   object monitor = f.GetValue(o);
   System.Reflection.MethodInfo m = monitor.GetType().GetMethod("StopMonitoring", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
   m.Invoke(monitor, new object[] { });

   System.IO.Directory.Delete(folder, recursive);
}

tisdag 24 mars 2009

Default AJAX Object for calling WebMethods from jQuery

Calling WebMethods from jQuery is a neat way of dealing with AJAX requests, both on the client- and serverside, but the AJAX object expected by jQuery requires a lot of parameters to be set, in order to work properly with .NET WebMethods. Properties that usually remain constant, yet always have to be previded (i.e. a lot of unnecessary duplication of code). To resolve the issue, I have written the following snippet:
Object.prototype.toAjaxObject = function()
{
   if(!this.type) this.type = 'POST';
   if(!this.contentType) this.contentType = 'application/json; charset=utf-8';
   if(!this.dataType) this.dataType = 'json';

   if(!this.url && typeof this.method == 'string')
   {
      this.url = location.href.substring(0, location.href.indexOf('?')) + '/' + this.method.toString();
      this.method = undefined;
   }

   if(typeof this.data != 'string' && typeof JSON =='object')
      if(typeof JSON.stringify == 'function')
         this.data = JSON.stringify(this.data);

   return this;
}
The above code adds an extension method to all JavaScript objects, which populates some properties with default values provided that these values have not already been set. Hence, you can still always override the use of any default value, at will.

As added value, there is a check for whether the data parameter is an object, and the function JSON.stringify is defined. If they are, data will be stringified. That is, if you know you're working in a project where JSON serialization functions will always be at hand, you can pass the data object as a custom JSON object, rather than a valid JSON-parseable string.

Another feature is that the url parameter is not required. Instead, it is possible to pass a method parameter, which will set url to a WebMethod call to that method, assuming the current url is used, and then remove the method parameter from the object. For this to work, it is required that url is not set.

Including the above snippet, it is therefore possible to reduce this piece of code code:
$.ajax({
   type: 'POST',
   url: 'MyPage.aspx/GetUser',
   contentType: 'application/json; charset=utf-8',
   dataType: 'json',
   data: '{"id":'+id+'"}',
   success: myCallback
});
To the following:
$.ajax({
   method: 'GetUser',
   data: {id:id},
   success: myCallback
}.toAjaxObject());
Again, provided that a serializer function called JSON.stringify is present. Otherwise, the data property must still be passed as a string in the manner of the first example.

Update


Looks like jQuery wasn't quite ready for object extension like this. The code works fine, but what Object.prototype does is to extend all Objects with some new functionality. Ran in to trouble as dialog wasn't prepared that the object passed might be extended with a function like this one. Eventually retorted to what feels pretty much like a hack. I would rather see that the jQuery UI team fixed up their components to allow the use of regular JavaScript like this, but for now, the following will do the trick:
$.ajaxCore = $.ajax;
$.ajax = function(opts)
{
   var addDefaults = arguments[0] ? arguments[0] : false;
   if(addDefaults)
   {
      if(!opts.type) opts.type = 'POST';
      if(!opts.contentType) opts.contentType = 'application/json; charset=utf-8';
      if(!opts.dataType) opts.dataType = 'json';

      if(!opts.url && typeof opts.method == 'string')
      {
         opts.url = location.href.substring(0, location.href.indexOf('?')) + '/' + opts.method.toString();
         opts.method = undefined;
      }

      if(typeof opts.data != 'string' && typeof JSON =='object')
         if(typeof JSON.stringify == 'function')
            opts.data = JSON.stringify(opts.data);
   }

   $.ajaxCore(opts);
}
The method call should, then, be modified accordingly:
$.ajax({
   method: 'GetUser',
   data: {id:id},
   success: myCallback
}, true);

fredag 27 februari 2009

Potentially dangerous Request in MVC

While developing an admin-page in MVC I kept getting the old "Potentially dangerous Request..." which occurs when trying to submit form data including html tags.

After adding the "validateRequest=false" to the pages-element in web.config (which turns this feature off in asp.net webforms) and checking that the page directive didn't ovveride this setting I was getting quite annoyed that I still got the exception on my page.

However - in MVC you need to set an attribute on your action in the controller to turn off validation:

[ValidateInput(false)]
public ActionResult Edit(int id, FormCollection collection)
{}


In my opionon I think that the setting is web.config should be read by the MVC actions as well as you otherwise need to define this attribute on all actions that might include html as a string parameter.

tisdag 17 februari 2009

JavaScript context binding

One of the neatest features in the JavaScript library Prototype is its helper function for context binding. This is one feature to which I have yet to find the correspondence in jQuery. The following code is the functional equivalent of the Prototype solution, which I've found use for too many times:

<script type="text/javascript">
Function.prototype.bind = function(context)
{
   var __method = this;
   var __args = new Array();

   for(it = 1; it < arguments.length; it++)
      __args.push(arguments[it]);

   return function() {
      for(ait = 0; ait < arguments.length; ait++)
         __args.push(arguments[ait]);

      __method.apply(context, __args)
   };
}
</script>
So what does it do? Well, it makes sure that all functions will have a function of their own, called bind. Bind receives a context, and makes sure that the function is always invoked from that context - i.e. that the "this." notation in the function will always reference the given context.

This solves a common JavaScript problem, when working with callback functions. Consider the following:

function User(username, password)
{
   this.username = username;
   this.password = password;
   this.tryLogin = function()
   {
      $.ajax({
         type: "POST",
         url: "Default.aspx/Login",
         ...
         success: function(msg)
         {
            if(msg == 'true')
               alert('Welcome '+this.username);
         }
   }
}
In the above code, the function passed along as a callback will be called from the jQuery AJAX handler, hence "this.username" will look for a username property in $.ajax() (and presumably fail to find one). Now, if we had included the snippet at the top of this entry, we would've been able to modify the callback declaration to the following:

success: function(msg)
{
   alert('Welcome '+this.username);
}.bind(this);
Here, instead of passing in assigning the success property with function x, we're passing x to bind, and assigning the value that bind returns, which is x hooked up to a specified context (this, as passed to bind).

For added value, bind also comes with the option to specify additional arguments to be passed along to the function, as it is being invoked. To demonstrate why this is useful, consider the following scenario:

<button id="btn0">Button0</button>
<button id="btn1">Button1</button>
<button id="btn2">Button2</button>
<script type="text/javascript">
function Person(name) {
   this.name = name;
   this.logClick = function(x) {
      alert(this.name + ' clicked button ' + x);
   };
   this.start = function() {
      for(var i = 0; i < 3; i++)
      {
         $('#btn'+i).onclick = function() { this.logClick(i) }.bind(this);
      }
   };
}

var p = new Person('Test');
p.start();
</script>
Now, the start function will hook up the three buttons with onclick events that will trigger the highlighted function. The bind is there, so we will be able to access this.name in logClick without a problem, but our desired effect here - to get Button1, say, to alert "Test clicked button 1" - will still not be met: the i parameter won't be accessed until the actual click event occurs, and by then, the for loop will have completed, and i will have the value of "3". All buttons will produce the same output. What we want, here, is to tell the function to use the value that the variable contained at the time of the event wireup. Again, bind comes to the rescue:

$('#btn'+i).onclick = function(x) { this.logClick(x) }.bind(this, i);
The above modification will solve the issue, and produce the desired output. Now that we're binding the parameter in bind, we can, of course, get rid of the delegate entirely:

$('#btn'+i).onclick = this.logClick.bind(this, i);

tisdag 30 december 2008

Making the JsonResult in MVC ignore a property

In MVC each controller action returns an "ActionResult". This can be a View, Content (plain text) or JsonResult for example. With JsonResult the output will (obviously) be serialized to JSON.

However - when using any serializeri on classes with bi-directional fields/properties you will run into problems as the serialization will lead to a endless loop trying to follow the bi-directional fields back and forth.

Using other serializer such as an XML serializer for example you just tag the bi-directional property with an "XMLIgnore" attribute and the serializer will basically ignore the field during serialization.

But trying to find a way for the JsonResult was not very easy as there is basically no subjects on this to be found using Google (at this time). However, using Reflector I found that the JsonResult is using the serializer "JavaScriptSerializer" found in "System.Web.Scrtipt.Serializer" (System.Web.Extensions.dll version 3.5). Following the code I found that the attribute to use to ignore a field is "ScriptIgnore" also found in "System.Web.Script.Serialization".

So, problem solved: Use the "ScriptIgnore" attribute to make the Json serializer in MVC ignore your bi-directional fields!

onsdag 5 november 2008

SEO-friendly 404 Exceptions

Custom 404 pages is a simple means of approaching a user-friendly experience even in the (albeit rather specific) case of an unhandled exception. In order to take the step from user-friendly to SEO-friendly, however, merely adjusting the customErrors tag in web.config is sub-par.

The problem
Modifying customErrors to redirect a user to a custom 404 page in the case of a fileNotFoundException will do just that - redirect the user - which means taking the detour to the client, informing of the redirect, which in turn means a 302 response from the server, before the user lands at the 404 page. The only implication of this is that search engine will fail to treat the response as a proper 404.

The solution
To resolve the issue, we have to drop the customErrors clause, and invoke Global.asax. Catching all exceptions in Global.asax, we are able to filter out the 404's, and render the appropriate site without tampering with redirects


void Application_Error(object sender, EventArgs e)
{
   HttpException ex = Server.GetLastError() as HttpException;

   if(ex != null && ex.GetHttpCode() == 404)
   {
      Response.Clear();
      Response.StatusCode = 404;
      Response.WriteFile("~/Pages/404.html");
      Response.End();
   }
}

A brief note on deployment
Finally, when deploying a project with a Global.asax file, from a web deployment project, make sure that the following files are updated:
- PrecompiledApp.config
- bin\App_global.asax.cs
- bin\App_global.asax.cs.compiled

Note that Global.asax is compiled in its entirety, and need not be uploaded to the production environment.

torsdag 31 juli 2008

Exlude files and directories when building deploy project

Its quite ezy ®.


  • Rightclick the deployment project and click "Open project file".
  • Insert the following code (example):
      <ItemGroup>
    <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Test\**\*.*"/>
    <ExcludeFromBuild
    Include="$(SourceWebPhysicalPath)\Images\**\*.*"/>
    </ItemGroup>


  • Done! Now it wont copy all those directories to your release folder, in the long run it will save you a lifetime of waiting.


torsdag 22 maj 2008

LINQ to SQL: On null values in coalesce expressions

The T-SQL function COALESCE is a convenient way of using optional parameters in an SQL query. It accepts a number of parameters, and returns the first non-null value in the set. When all the values in the set are null, the function returns a null value. For those more acquainted with SQL CASE, the following two expressions are exactly identical:

SELECT COALESCE(@param1, @param2, 'Default value')

SELECT
   CASE WHEN @param1 IS NOT NULL THEN @param1 ELSE
      CASE WHEN @param2 IS NOT NULL THEN @param2 ELSE
         'Default value'
      END
   END

C# provides a convenient shorthand - expr1 ?? expr2 - for coalesce expressions, which allows us to create a function as such:
public int Coalesce(int? var, int defaultValue)
{
   return var ?? defaultValue;
}

In LINQ to SQL, the ?? shorthand is always translated into COALESCE when the SQL query is generated, which equips us with the ability to use optional parameters as seen in figure 1:

Figure 1

public IEnumerable GetItems(int? parentId, int? typeId)
{
   myDataContext db = new myDataContext();
   return from item in db.Items
          where
             item.ParentId == (parentId ?? item.ParentId)
             && item.TypeId == (typeId ?? item.TypeId)
          select item;
}

As a side-remark, note the necessity of brackets in the above code. This code will render the following SQL query:
SELECT
   *
FROM
   Items
WHERE
   ParentId = COALESCE(@parentId, ParentId)
   AND TypeId = COALESCE(@typeId, TypeId)

So far so good, but this, in fact, poses a problem when using nullable database fields. Consider the following table structure:
Items
-----------------------------------
Field name     Type      Allow null
-----------------------------------
Id             int       false
ParentId       int       true
TypeId         int       false

Now, assume we want to find all items of TypeId 5, regardless of their parent items; indeed, regardless of whether they have a parent at all. The following request seems intuitive enough: GetItems(null, 5);. This will result in the C# expression item.ParentId == (null ?? item.ParentId), which is completely valid, but it will translate to the following SQL:
SELECT
   *
FROM
   Items
WHERE
   ParentId = COALESCE(null, ParentId)
   AND TypeId = COALESCE(5, TypeId)

For a record of ParentId 1 and TypeId 5, this will be just the way to do things, but if we consider the fact that there could exist an item with ParentId null and TypeId 5, the first COALESCE would return null, as both of its parameters would be of a null value. In SQL, this results in a null = null comparison, which will return false (hence the IS NULL syntax). Consequently, items with a ParentId of null will not be returned, even though the intention was to specify that the query should disregard of ParentId completely.

A workaround for the problem would be to rewrite a method accordingly:

Figure 2
public IEnumerable GetItems(int? parentId, int? typeId)
{
   myDataContext db = new myDataContext();
   return from item in db.Items
          where
             ((item.ParentId == null && parentId == null) || item.ParentId == (parentId ?? item.ParentId))
             && item.TypeId == (typeId ?? item.TypeId)
          select item;
}

Now, you don't have to look at figure 2 to realize that there's probably a better way to solve this problem. Expression trees would do the trick, for sure, but for our simple implementation, it turns out there's a less complex solution:

Figure 3
public IEnumerable GetItems(int? parentId, int? typeId)
{
   myDataContext db = new myDataContext();
   var items = from item in db.Items select item;

   if(parentId != null)
      items = from item in items where item.ParentItemID == parentId select item;

   if(typeId != null)
      items = from item in items where item.ItemTypeID == typeId select item;

return items;
}

Beginning by selecting the entire set of items available, we then proceed to filter the results to match any of the criterias that may or may not be provided. At first glance, this would appear to begin by executing a plain SELECT * FROM Items query, returning all items in the table, even when we know that's not always requested, but as the result set - items - is never enumerated before the return statement, LINQ to SQL optimizes the above code into one query at runtime, depending on what values have been specified.

An SQL Profiler trace gives us the answers in plain text:
Figure 1
exec sp_executesql N'SELECT Id, TypeId, ParentId FROM Items WHERE (ParentId = (COALESCE(@p0,ParentId))) AND (TypeId = (COALESCE(@p1,TypeId)))',N'@p0 int,@p1 int',@p0=NULL,@p1=5

The query generated in Figure 1 returns 0 rows, which is not what we expect, given the data in the table.

Figure 2
exec sp_executesql N'SELECT Id, TypeId, ParentId FROM Items WHERE ((ParentId IS NULL) OR (ParentId = (COALESCE(@p0,ParentId)))) AND (TypeId = (COALESCE(@p1,TypeId)))',N'@p0 int,@p1 int',@p0=NULL,@p1=5

The query from Figure 2 gives us the result we want, but in a verbose and inconvenient query

Figure 3
exec sp_executesql N'SELECT Id, TypeId, ParentId FROM Items WHERE TypeId = @p0',N'@p0 int',@p0=5

From Figure 3, only one query is executed (although we appear to have begun by selecting everything in the table), and only the non-null parameter is passed.

Visual Studio 2008 fails to open certain projects

Visual Studio 2008 might fail when opening a project using an add-on package. The package might be a silverligt plug-in as well as the standard LINQ-to-SQL dialog.

When this happens VS gives you the following error message:
"Project <Name> could not be opened because the Microsoft Visual C# .NET compiler could not be created. QueryService for '{74946829-37A0-11D2-A273-00C04F8EF4FF}' failed."

...and the project will fail to load.


This is really weird, but the solution is to open "regedit" and navigate to:
"HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Packages\"

Under this element you will find several "GUID"s (none with the GUID in the error message though). Open each of the GUID-elements and change the "SkipLoading" value to "0" (zero).

Restart VS 2008 and voilá - it is working again!

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.

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>