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

torsdag 18 oktober 2007

ASP.NET Cache gets flushed, cleared or randomly disappear

Have you been having problems with the ASP.NET cache gets cleared, flushed or simply seems to disappear when running your ASP.NET 2.0 web application? Restarting the IIS seems to help for a while but eventually the cache gets flushed again.

This problem seem to appear especially computers with 2GB of ram or less.

The solution is quite simple, and should be good enough on a developing machine. Simply add the following lines in web.config in the .



 1: <caching> 

 2: <cache disableMemoryCollection = "true"

 3: disableExpiration = "false" 

 4: privateBytesLimit = "0" 

 5: percentagePhysicalMemoryUsedLimit = "90" 

 6: privateBytesPollTime = "00:02:00"/> 

 7: </caching>





There are a few tools that might be helpful when debugging cache.

Reference:

Thanks to Henrik for good google skills.

tisdag 16 oktober 2007

SQLQueryStress

I want to recommend a good tool when you are optimizing your queries.

Often after a trace you will find that only a couple of your queries ends up taking the majority of the cpu.

Sometimes it's as easy to solve the problems by just adding an index, and sometimes there will be other solutions.

Whatever solution you choose, it can be a good thing to test your query.

The SQLQueryStress tool written by Adam Machanic, can be downloaded here http://www.datamanipulation.net/SQLQueryStress/.

SQLQueryStress is very simple although very powerful. You can use parameter substitution so you can execute your queries with different parameters. You can set the number of iterations but also the number of threads (clients).

The output from this is "cpu seconds", "elapsed time", "client seconds", "logical reads", and more.

So when you compare two queries and booth queries takes the same time to execute, you can easily see in this program if one of them use less cpu or maybe less IO over several executions and with different parameters.

måndag 15 oktober 2007

Are you still using the repeater?

When asp.net first was released we quickly adapted to an object oriented way of creating and manage controls, instead of the old procedural asp ways. We started to use literals, datagrid and repeaters.

All the good functionality that came with the data binding controls also introduced performance problems. So – for example - instead of using the datagrid we started to use the repeater. However it’s easy to forget that even the repeaters data binding functionality comes with performance problems.

The repeater uses reflection internally, and for each object (text or image or whatever) in the itemtemplate it will create a new control, and if you have a rather complex repeater it will quickly add up and create a lot of controls. The creation of a control and all it’s rendering means extra cpu time, and also extra work for GC.

I have made some performance tests and found out that the repeater can be 30 times slower than using string concatenation with stringbuilder and then use response.write to ouput the result. And this is only the rendering time, we also have saved a lot of CPU time and therefore the application will scale better when we stress test it.

The problem with this solution is that it will give us headache when we need to add/edit the html or add an attribute of a control or something. What we can do is to create a usercontrol that has a public collection (of some sort), that we can set, and then use inline c# with other custom controls. This solution will still give us the same performance benefits.

Example
<%
for (int i = 0; i < myCollection.Count; i++){
myCustomControl.myAttribute = myCollection[i].SomeProperty;
%>
<div class="<%=myCollection[i].myDivClassProperty %>">some html</div>
<uc:myUc id="myCustomControl" runat="server" />
<%
}
%>

This way we will keep the rest of our code clean and use this optimized version of data rendering where you have a lot of posts to render or is one of the most viewed pages in your application.

fredag 5 oktober 2007

ASP.NET Ajax History control example

This is a short example how to set up the History control from ASP.NET Futures and ASP.NET AJAX.

<cc1:History ID="History1" runat="server"></cc1:History>

<asp:UpdatePanel ID="updPnl" runat="server" UpdateMode="Always" ChildrenAsTriggers="true">

<ContentTemplate>

<asp:MultiView ID="multiView" runat="server">

<asp:View id="viewStep1" runat="server">

...

</asp:View>

<asp:View ID="viewStep1" runat="server">

...

</asp:View>

</asp:MultiView>

</ContentTemplate>

<Triggers>

<asp:AsyncPostBackTrigger ControlID="History1" EventName="Navigate" />

</Triggers>

</asp:UpdatePanel>

Event that is fired when you press the back button.

public void History1_Navigate(object sender, Microsoft.Web.Preview.UI.Controls.HistoryEventArgs args)

{

string viewId = "";

View historyView = viewStep1;

if (args.State.ContainsKey("BookingSteps"))

{

viewId = (string)args.State["BookingSteps"];

}

foreach (View v in multiView.Views)

{

if (v.ID == viewId)

historyView = v;

}

setActiveView(historyView);

}

Set history point each time you change the view.

private void setActiveView(View view)

{

multiView.SetActiveView(view);

History1.AddHistoryPoint("BookingSteps", view.ID);

}

onsdag 3 oktober 2007

List IIS App pool processes

A common issue on a shared IIS server is to distinguish the CPU load between different web application when looking in the task manager.

The solution is to create one application pool for each web application in the IIS. IIS will then launch one individual "w3wp.exe" process with its own ID (PID - Process ID) for each application pool.

To list all running processes, Windows Server has a built in vbs-script to display all running application pools (w3wp processes) located in: "c:\windows\system32\iisapp.vbs".

You run this script from a command console using:
c:\windows\system32\cscript.exe iisapp.vbs

The output is a list of each running w3wp process together with its PID which can be matched to the PID in the task manager.

Using one application pool for each web application also has advantages when looking at performance counters as each counter can be selected for each application pool.

torsdag 20 september 2007

Using ToolkitScriptManager CombineScripts with url rewrite

When you use HttpModule to handle generated htm url's the ToolscriptsMangers CombineScript dosn't work.

To fix this you can add the CombineScriptsHandlerUrl and set this value to "/".

<ajaxtoolkit:toolkitscriptmanager id="ToolkitScriptManager1" runat="server" asyncpostbacktimeout="900" combinescripts="true" combinescriptshandlerurl="/" loadscriptsbeforeui="true">

AjaxControlToolkit: Events inside a Accordion

If you having problems with needing to click twice or more on a button inside a AccordionPane to get the Event to fire this is a workaround for you.

In this example we have the following structure.


  • MasterPage

    • Page

      • MyAccordion

        • MyUserControl

          • MyButton

In the Page OnInit you simply put the following line:

LinkButton btn =(LinkButton)(MyAccordion.Panes[0].FindControl("MyUserControl").FindControl("MyButton"));

This will make the Accordion to force to load the OnInit in MyUserControl and thus register the MyButton_Click event. It will also enable all other events inside the usercontrol

Hopefully a fix for this will come in a later version of the AjaxControlToolkit.

Reference: http://forums.asp.net/t/1047516.aspx