Saturday, March 27, 2010

Configuring your HTC HD2 Leo email account to use Wi-Fi

If you've read any of my posts, you probably know I'm not one to shy of Microsoft's technology. So, when it came to buying a smart phone I went for the best Hardware available - even if it means using Window Mobile as my my OS. Getting the best HW these days means the HTC HD2 Leo
So, from time to time I'll post some tips here.

If you want your email account to use Wi-Fi in order to send/receive your mail (instead of the expensive GPRS default) - do this:

Start >> E-mail >> [select your account] >> Menu Options >> [select your account from the list (yea I know you did that in the previous step)] >> Edit Account Setup >>Next >> Next >> Next >> Next >> Advanced Server Settings >> In Network Connection select "The Internet" >> Done >> Next >> Next >> Finish

That's a well hidden configuration wouldn't you say?

Monday, March 15, 2010

Enabling incompatible add-ons in Firefox 3.6

It may be so 2008, but, I do love my Firefox with my choice selection of add-ons. That's why I was dismayed to find out that Firefox 3.6 has caused quite a few of them to be disabled due to incompatibility.
Today, I got tired of waiting for the new releases, so I decided to enable incompatible add-ons - I recalled doing it when I switched to version 3 by using the old extensions.checkCompatibility. This post used to be a big help.

It seems however, that the semi-official way of doing this in Firefox 3.6 is by installing the "add-on compatibility reporter".

If you would like to allow incompatible add-ons in Firefox 3.6 without installing this additional plugin, you now need to add the version name to the preference name, like so; extensions.checkCompatibility.{version}. Check out the Mozzila documentation here.

So, to summarize if you want to bypass Firefox's compatibility checking and allow your favorite add-ons to run.
  • Type about:config into Firefox’s address bar and click the “I’ll be careful, I promise!” button.
  • Right-click anywhere in the list and select New > Boolean.
  • Type extensions.checkCompatibility.3.6 and click OK.
  • Select false and click OK.
  • Restart your browser.

Tuesday, May 12, 2009

Enhanced performance for the ASP.NET AJAX autocomplete control

The Problem

AutoComplete controls have become a main feature in many interactive website and web applications.

In fact it is very common to explain the advantages of AJAX using the “Google Suggest” example, as this was one of the first powerful well known implementations implementations.

Microsoft has provided a very powerful and easy to use control in the ASP .NET AJAX Control Toolkit – the AutoCompleteExtender.

There are two approaches to creating AutoComplete controls. The first one is to transmit all possible data to the client, and implement the algorithm that suggests possible completions, in the browser using JavaScript. The other approach is to send an AJAX request to the server that will retrieve a list of suggested completion words. Such a request is being made every time a new prefix is entered in the AutoComplete text box.

The AutoCompleteExtender is implemented using the second approach – this approach works best when the vocabulary that needs to be considered for suggestions is potentially very large – this would make it impractical to download the full list of possibility to the client.

When you implement an AutoCompleteExtender you need to provide a web service that will be used to supply the word/sentence completions. But, the guide and sample stop there and do not instruct you how to build an effective web service.

You need to consider that such a web service is used in a highly interactive way, and may need to respond quickly to the waiting user by suggesting completions from a potentially large database. Furthermore each user is likely to make several such completion requests within a short period of time. If you intend to support many concurrent users, you have a potential load problem on your hands.

The trivial implementation for such a web service would select from the DB your data and convert it to a string array, there are quite a few such examples on the web, here’s a raw snippet for the service method:

[WebMethod]
public string[] GetStudentNames(string prefix)
{
string sql = "SELECT * from students WHERE name like @prefix";

...

string[] items = new string[dt.Rows.Count];
int i = 0;
foreach (DataRow dr in dt.Rows)
{
items.SetValue(dr["name"].ToString(), i);
i++;
}
return items;
}



The problem with the above code is that it will access the DB to retrieve and filter the required data every time the user will change the prefix in the the AutoComplete control. This puts unnecessary strain on both your DB server and the web server and will severely degrade the performance if the amount of data involved is large.

The common solution for unnecessary DB trips is caching, but here we encounter another problem – what is it that we need to cache and how?

In the above example we could potentially select all student names in the DB and cache that as a list in memory – but when the method is called we will need to filter only those names that start with the required prefix. A naive implementation will go over the whole list and check each string against the prefix (with a complexity of O(n) where n is the number of student names in the DB), but there are more appropriate data structures to handle this problem.



The Solution

One of the best data structures to handle this problem is the Trie.


A .NET Trie implementation that is specifically tailored to serve the AutoCompleteExtender can be downloaded from CodePlex here.


The time complexity of building a Trie is considered to be O(n) where n is the total amount of strings to be contained in the Trie. To search for the existence of a prefix we need O(l) where l is the length of the prefix.


Retrieving a list of strings beginning with the prefix – is done at O(m) where m is the number of strings that will be retrieved.


You should consider that querying the DB, and building a large Trie can be costly in time and memory. But once the Trie is built you can cache it and use it repeatedly for fast search and string completions. Specifically, you can use a cached Trie to repeatedly return string suggestions from the AutoComplete web service.


How To Use

First download the code from CodePlex.


Follow the regular instructions on how to use the AutoCompleteExtender.


Make sure your web service builds the AutoCompletion Trie and stores it in cache, if it does not already exist. If and when it does exist use it to return the completion list:






    [WebMethod]
public string[] GetCustomers(string prefixText, int count)
{
Trie customersTrie = (Trie)Context.Cache["CustomersTrie"];
if (customersTrie == null)
{
customersTrie = new Trie();
customersTrie.Load("Donald Duck");
customersTrie.Load("Duffy Duck");
customersTrie.Load("Mini Mouse");
customersTrie.Load("Mickey Mouse");
customersTrie.Load("Pluto Dog");
customersTrie.Load("Guffy Dog");
Context.Cache["CustomersTrie"] = customersTrie;
}
List<string> list = customersTrie.FindCompletions(prefixText);
return list.ToArray();
}




Note that the Trie is thread safe for multiple readers only. You should protect the Trie from concurrent read/write operations.


Check out the code and unit tests for some further details, to run the unit tests you will need NUnit. If you want to run the performance test you will need an external dictionary you can use the AGID wordlist from: http://wordlist.sourceforge.net/ or modify the code to use a different large word list.


Here are some posts I have found helpful while building this Trie:
http://sujitpal.blogspot.com/2007/02/three-autocomplete-implementations.html
http://rmandvikar.blogspot.com/2008/07/tries.html
http://rmandvikar.blogspot.com/2008/10/trie-examples.html



Share & Enjoy.

Thursday, April 2, 2009

Containing Child Controls inside a UserControl

User Controls are a very quick and effective method to develop reusable controls for your application. They are usually much easier to develop than writing your own custom server controls.

I ran into a situation the other day that a user control we’ve made and had been working on for some time, just got a new requirement to be able to contain child server controls. I was a bit surprised to discover this is not a trivial matter.

It seems there is a weird limitation on User controls. If you try to put child controls in them or nest a user control inside another, the designer will complain. Furthermore if you thought you could use the PersistChildrenAttribute in order to convince the designer that your control is really intended to support this behavior, then think again – it seems that the designer simply ignores this possibility when it comes to user controls.

While searching for a solution, I discovered this post by Bobby DeRosa that suggested a reasonable solution. The problem with this solution is that you get XHTML validation errors. However, a comment in the post suggests a better solution.

While a Container User Control is not directly supported, a templated user control is supported by Microsoft.

And so, the below suggested solution will work nicely. Just to make things more interesting I made the sample control support two areas that can contain child controls; a header section and a content section.

The User Control’s code behind looks like this:

public partial class ContainerUserControl : UserControl
{
[PersistenceMode(PersistenceMode.InnerProperty)]
publicITemplate Header { get; set; }

[PersistenceMode(PersistenceMode.InnerProperty)]
publicITemplate Content { get; set; }

protected override voidOnInit(EventArgs e)
{
base.OnInit(e);
Content.InstantiateIn(ContentPlaceHolder);
Header.InstantiateIn(HeaderPlaceHolder);
}
}

While the markup should have a place holder for each section that will contain child elements:


  

<%@ControlLanguage="C#"AutoEventWireup="true"CodeBehind="ContainerUserControl.ascx.cs"Inherits="TestWebApp.ContainerUserControl"%>
<div>
<
asp:PlaceHolder ID="HeaderPlaceHolder"runat="server">
</
asp:PlaceHolder>

<
asp:PlaceHolder ID="ContentPlaceHolder"runat="server">
</
asp:PlaceHolder>
</
div>

And here is a sample of the usage:

 

<form id="form1" runat="server">
<
div>
<
uc:ContainerUserControl runat="server" ID="OuterContainer">
<
Header>
<
asp:Label ID="Label1" Text="Main label" runat="server" />
</
Header>
<
Content>
<
asp:Button ID="btnTest" runat="server" Text="Test me" />
</
Content>
</
uc:ContainerUserControl>
</
div>
</
form>

You can even nest a user control inside another user control:

<uc:ContainerUserControl runat="server" ID="OuterContainer">
<
Header>
<
asp:Label ID="Label1" Text="Main label" runat="server" />
</
Header>
<
Content>
<
uc:ContainerUserControl ID="InnerContainer" runat="server">
<
Header>
<
asp:Label runat="server" Text="Nested label"/>
</
Header>
<
Content>
<
h2>This is a nested content</h2>
</
Content>
</
uc:ContainerUserControl>
<
asp:Button ID="btnTest" runat="server" Text="Test me" />
</
Content>
</
uc:ContainerUserControl>

One more point to remember is that because the designer does not really support the inner content of the user control, you will not be able to refer directly to controls such as the above button. The reason is that the generated aspx.designer.cs will not include the inner controls as they are a part of the template. Therefore you will need code such as this to refer to the button:

this.OuterContainer.FindControl("btnTest");

Hopefully this will save you some time developing a full blown server control.

Tuesday, March 17, 2009

SSL must not be enabled for pickup-directory delivery methods

Maybe I'm just getting soft and lazy.
It seems I've gotten used to just finding the answer to everything I need by googling it and relying on the community to solve it for me.

I mean, at least when I’m not dealing with the bleeding edge of technology, I should expect to find a post from somebody who’s already ran into a similar problem – right?

Well, I was a bit surprised when I tried to implement a simple email client using the totally mundane System.Net.Mail (really not bleeding edge, is it?), and received the following exception:

SSL must not be enabled for pickup-directory delivery methods

Happily I searched the web for this error message only to find two (2!) whole articles about it, none of which was any help at all.

So, I figured it’s a good enough reason for my first blog post. After all, the blog itself has been ready and waiting for several months now for me to find the time and motivation to write something.

But, I was doing something really trivial - there must be thousands of blog posts about how to write an SMTP client to send mail using the SmtpClient class.

The code itself goes something like this:

MailMessage emailMessage = new MailMessage();
emailMessage.From = from;
foreach (MailAddress ma in to)
emailMessage.To.Add(ma);
emailMessage.Subject = subject;
emailMessage.Body = message;

SmtpClient smtp = new SmtpClient(_smtpHost, 587);

smtp.UseDefaultCredentials = false;
smtp.Credentials = new System.Net.NetworkCredential("myGmailAccount", "myGmailPassword");
smtp.EnableSsl = true;
smtp.Send(emailMessage);

A textbook sample, isn’t it?

As it turns out, the error is really self explanatory if you you’re aware of the SmtpClient‘s DeliveryMethod Property and its usage.

But I wasn’t messing with the DeliveryMethod - so why would it mess with me?

It took me a while to find out that someone has left a surprise for me in the web.config:

<system.net>
<
mailSettings>
<
smtp deliveryMethod="PickupDirectoryFromIis">
<
network defaultCredentials="true" host="localhost" port="25"/>
</
smtp>
</
mailSettings>
</
system.net>

And while I was overriding all the other parameters in my code, the DeliveryMethod was defaulting to PickupDirectoryFromIis, which is obviously incompatible with SSL (it makes perfect sense actually, if you’re going to write the emails to a queue directory on your file system, then you obviously won’t need to be using SSL).

If you want to know more about DeliveryMethod you may find Marco’s post useful.

The solution for me was to just get rid of the whole configuration section. I’m one of the people who think MS has messed up implementing the default configuration system, and it really shouldn’t be used for anything more complicated then switching between your own environments. If you use web.config or app.config to actually manage real configuration parameters that change between different installations then you’re in a world of pain. But I digress.

On the other hand, some other parts of the framework such as the ASP.NET membership controls rely on this configuration section. So if you don’t want to face the consequences of taking away a piece of configuration that may be used elsewhere in the system, then you can explicitly override the DeliveryMethod in your code like this:

smtp.DeliveryMethod = SmtpDeliveryMethod.Network;

I hope this has made things a bit clearer regarding the usage of DeliveryMethod and its pitfalls.