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>

onsdag 30 januari 2008

NHibernate mapping with enum

When mapping a property of an enumeration type you should always set the type attribute of that property in the mapping file to that enumaration type.

Often you don't set the type at all or you set it to Int32 since your enum is represented as an int in the database. It's easy to assume that setting the attribute type to Int32 will have the same effect as using the enum type. And it will work!

When using an In32 your code will execute without exception. The field will be selected and updated as usual.
However, during the session flush nhibernate will recognize that the current value of the property differs from the originall value causing an update to the database. Another disadvantage is that the query cache for this class won't work either.

tisdag 22 januari 2008

Using Fiddler on localhost

Fiddler is a great tool to analyse http traffic to the server. But it's sometimes difficult to make it work on localhost. But if you enter a simple dot (.) after "localhost" in the url it works.

So intead of http://localhost:8081/...,
use http://localhost.:8081/...

Reference:
http://weblogs.asp.net/lorenh/archive/2008/01/10/tip-for-using-fiddler-on-localhost.aspx

NHibernate: Enable second level cache using MemCached

The second level cache is a powerful feature used by NHibernate to cache objects and queries to limit the number of database queries.

NHibernate uses a provider based architecture where cache providers can be plugged in using the config file.

NHibernate is shipped with several cache providers, example:
- SysCache (uses ASP.NET Cache Objects to cache data)
- MemCached (distributed in-memory Cache running as a separate Windows Service)

We will use MemCached in this example.

There are several win32 ports of MemCached available. We will use one available at:
http://jehiah.cz/projects/memcached-win32/

Start by downloading MemCached from the URL above and from a Command prompt type:
memcached -d install <enter>
memcached -d start <enter>

This will start the MemCached service on your computer.

Next, we will configure MemCached in your application. Add a new configuration settings in your config file under <configSettings>:
<section name="memcache" type="NHibernate.Caches.MemCache.MemCacheSectionHandler,NHibernate.Caches.MemCache" />

Add the MemCached settings using:
<memcache>
<memcached host="192.168.1.0" port="11211" weight="1"/>
</memcache>

The next step is to enable caching in your NHiberate project. Under the <NHibernate> node, add the following application settings:
<add key="hibernate.cache.provider_class" value="NHibernate.Caches.MemCache.MemCacheProvider,NHibernate.Caches.MemCache" />
<add key="hibernate.cache.use_query_cache" value="true"/>
<add key="expiration" value="120" />


At last we need to enable caching for the persistant classes in your application. This is done in the hbm.xml file using the <cache> element:
<class name="NameSpace.Class, NameSpace" table="tblInDb">
<cache usage="read-write"/>
...
</class>


To enable caching for relations, add the <cache> element for each relation:
<bag name="Childs" lazy="true">
<cache usage="read-write"/>
<key column="ParentId"/>
<one-to-many class="NameSpace.ChildClass, NameSpace"/>
</bag>



The second level cache is used by NHibernate in the following scenarios:
- Single objects retrieved using ISession.Load
- Lists of objects retrieved using IQuery.List (if hibernate.cache.use_query_cache is set to true)
- Relational objects (when the bag is marked with <cache>)

Note that NHibernate does not use the second level cache when using ICriteria.

torsdag 29 november 2007

DataContractSerializer requires alphabetic element order

When using the DataContractSerializer to deserialize objects either from pure XML or implicit using WCF it requires the XML elements to appear in alphatic order.

Let says we have the following class:
[DataContract]public class auth
{
[DataMember]
public string username;
[DataMember]
public string password;
}

...and the following XML input:
<auth>
<username>ABC</username>
<password>DEF</password>
</auth>

Using this XML, the DataContractSerializer would deserialize the "Auth" class and Username property correctly - but the Password property would be null.

The reason is that the DataContractSerializer requires the element order in the XML to be in alphabetic order, ie:
<auth>
<password>DEF</password>
<username>ABC</username>
</auth>


The sort order can be set explicitly using the "Order" property on the "DataMember" attribute - however: it would still require the XML input to follow a specific order.
Example using the "Order" property and allowing the username element to appear before the password element:
[DataContract]
public class auth
{
[DataMember(Order=1)]
public string username;
[DataMember(Order=2)]
public string password;
}



WCF: Adding a behavior extension requires careful notation of the assembly path

When registering a behavior extension in the .config file the inialization might fail with the following error message:

An error occurred creating the configuration section handler for system.serviceModel/behaviors: Extension element 'myService' cannot be added to this element. Verify that the extension is registered in the extension collection at system.serviceModel/extensions/behaviorExtensions.Parameter name: element

This might be the case even if the syntax for the assembly/class is correct and even if the service host has access to the assembly.

The reason is that for this particular configuration, .NET requires you to:
1. Add the fully qualified name for the assembly
Example:
"MyAssembly.MyClass, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
instead of:
"MyAssembly.MyClass, MyAssembly" - which normally does the job

2. Use the exact syntax for the assembly
You are not allowed to use any line break of white spaces at the wrong places.
Example:
"MyAssembly.MyClass, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
instead of:
"MyAssembly.MyClass,MyAssembly,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null" - note the missing white spaces between each attribute.

Microsoft has acknowledged this; yet not classified it as a bug:
https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=216431