Saturday, December 20, 2008

Sorting with IComparable and Comparison Delegate on List<T>

One of the popular generic collection types in .Net 2.0 is List<T>, which we use to store a list of T items. For example, List<Country> stores a list of countries that defined by Country class. It works perfectly to bind the collection to a datasource to be displayed on, for instance drop down or grid view. But you may want the list to be sorted before it is bound to the datasource. Yes, List collection support a method called List<T>.sort() but in order to use sort() method, T must inherit IComparable interface.

To read more about this, visit here.

So let's take Country as the example. A typical Business Entity will look like:-

public partial class Country
{
public Country()
{
}

public Country(System.String countryName, System.Int32 id)
{
this.countryNameField = countryName;
this.idField = id;
}

private System.String countryNameField;

public System.String CountryName
{
get { return this.countryNameField; }
set { this.countryNameField = value; }
}

private System.Int32 idField;

public System.Int32 Id
{
get { return this.idField; }
set { this.idField = value; }
}
}


Next step is to inherit IComparable interface.



public partial class Country: IComparable<Country>



Once you have inherit the Interface, you are required to implement the definitions. In C#, you can right click on the Interface, and select Implement Interface > Implement Interface. Then the required method will be automatically added to your class. It will look similar to this:-



#region IComparable<Country> Members

public int CompareTo(Country other)
{
throw new Exception("The method or operation is not implemented.");
}

#endregion



Alright, you are almost done with a simple sorting. Now you need to implement the CompareTo method like this:-



#region IComparable<Country> Members

public int CompareTo(Country other)
{
return CountryName.CompareTo(other.CountryName);
}

#endregion


To test it, simply fill the List<Country> with data and call List<Country>.sort() method. It will automatically sort the list. Now is this what we need? If yes, move on to others. If no, what is the problem? Come to think of it, we may have different comparison in different scenario. For example, we may want to sort by ID in a GridView, and we may want to sort by Name (ASC or DESC) in a drop down box. So we want a more dynamic implementation.



Here, we need to use Generic Comparison delegate to provide different comparison methods. We may want to sort by ID or sort by Name in Descending order. Alright, you may simple need to write this:



#region Comparison Function

public static Comparison<Country> SortById = delegate(Country c1, Country c2)
{
return c1.Id.CompareTo(c2.Id);
};

// Sort by Name in DESC order
public static Comparison<Country> SortByName_DESC = delegate(Country c1, Country c2)
{
return c2.CountryName.CompareTo(c1.CountryName);
};

#endregion


So with Comparison delegates, you can come out with different kind of comparison to help you sort the list in your own way. The methods are being called in this way:



List<Country> list = new List<Country>();

list = GetCountries();

// Default Sorting
list.sort();

//Sort By ID
list.sort(Country.SortById);

//Sort By Name DESC
list.sort(Country.SortByName_DESC);



Done! If the above example does not help to solve your problem, you may want to consider creating a custom comparer class by inheriting from IComparer interface.



Cheers.

Monday, December 1, 2008

'Sys' is Undefined. Javascript error when you use AJAX extension

You probably will notice a scripting error when using ASP.Net AJAX Extension in your web pages.

Error: 'Sys' is undefined.

It is due to the ajax extension is not properly registered and configured in your web.config.

Solution:

There are a few things that you need to have in your web config.

1.) Make sure you have add below line to your assembly under <compilation><assemblies>

<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />



2.) Add following lines under <system.web>



<httpHandlers>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
</httpHandlers>



3.) Add following line under <system.web><httpModules>



<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>



Cheers. This has solve my problem. I hope it does the same to you.



Some updates from Scott.



http://weblogs.asp.net/scottgu/archive/2006/10/29/tip_2f00_trick_3a00_-handling-errors-with-the-updatepanel-control-using-asp.net-ajax.aspx

Tuesday, October 14, 2008

Store a type String value into type Guid

Sometimes, it is a good practice to use uniqueidentifier data type as your primary key in your database so that it eases your job when you are trying to merge your data from multiple data sources/locations.

however, the value is displayed as string in your application and when you want retrieve a data using the uniqueidentifier/Guid, the application will throw an exception because it does not allow you to input string for the type of Guid. Most of the function will look like:

public MembershipUser GetUserById(object key);

so if you call below statement will cause you an error:

MembershipUser user = GetUserById("23c46d23-8459-46fe-9e19-2da6800ef654"); //wrong

In fact, you need to use this:

MembershipUser user = GetUserById(new Guid("23c46d23-8459-46fe-9e19-2da6800ef654")); //Correct

Monday, October 13, 2008

How to Generate Validation Key and Decryption Key for Encryption

Usually when you deal with Membership Provider in ASP.Net, you will need to supply validation key and decryption key manually for Password Format using Hashed or Encryption. AutoGenerate is only valid for Password Format = Clear.

before you generate the keys, you have to keep in mind that

1.) ValidationKey is 64bit of hex value. So you will require varchar(128).

2.) DescryptionKey is 24bit of hex value. So you will require varchar(48).

You either choose to assign your own value or use this link to generate a random value for your application.

http://www.eggheadcafe.com/articles/GenerateMachineKey/GenerateMachineKey.aspx

Friday, September 5, 2008

Microsoft Popfly (Mashup) Sample

Recently, I have created a mashup sample using Microsoft Popfly. Here is a video player that play a list of Youtube videos with the keyword "Mister Cupid".





Saturday, August 30, 2008

Cross-Page Posting for handling some combination of user input

I believe everybody know ASP .Net supports same page Postback function by default. For example, same page posting back to the same page. For those that do not know, ASP .Net 2.0 introduces a new capability whereby pages can post to pages other than themselves. We call this Cross-Page posting and usually it gives a tight coupling for these pages.

Now, let's see what we need to create here.

Let's use Page 1 as a Posting Page and Page 2 as the Receiving Page.

  1. To create a Cross Page posting, we can use PostbackURL from the button (LinkButton, Button, ImageButton) in Page 1 and point it to Page 2.
  2. <asp:Button ID="Button1" runat="server" Text="Button" PostBackUrl="~/Page 2.aspx" />



  3. In Page 2, add a PreviousPageType directive. This will allow you know set your previous page to Page 1.


  4. <%@ PreviousPageType VirtualPath="~/Page 1.aspx" %>




Or Use TypeName to Class name



<%@ PreviousPageType TypeName="_Page_1" %>



Above steps will let you set the tight coupling relationship between Page 1 and Page 2 and you can access the properties, control or functions in Page 1 from Page 2.



public partial class Page_2 : System.Web.UI.Page
{
_Page_1 PostingPage;

protected void Page_Load(object sender, EventArgs e)
{
if (this.PreviousPage != null)
{
PostingPage = this.PreviousPage;

Label1.Text = PostingPage.Page1_Propertise;
}
else
{
Label1.Text = "Previous Page is Null";
}
}
}



Usually you can use when creating wizard or pages that required tight coupling. You have to set PreviousPageType directive in order to access Page 1 properties.



Okie now, you might ask how to access a page's properties, control, or function without using PreviousPageType directive. The answer is..you may use Reference directive. Let's create the scenario now.



Now, we do not want to use PostbackURL at the button in Page 1, instead, we use a normal navigation method.



<asp:Button ID="Button1" runat="server" Text="Button"OnClick="Button1_Click" />


In the Page 1 code behind,



protected void Button1_Click(object sender, EventArgs e)
{
Server.Transfer("~/Page 2.aspx");
}



Now, we need to add reference in Page 2 so that it can access Page 1 with no problem.



<%@ Reference Page="~/_Page_1.aspx" %>


By using reference page, you may need to cast your page object like the code below.



public partial class Page_2 : System.Web.UI.Page
{
_Page_1 PostingPage;

protected void Page_Load(object sender, EventArgs e)
{
if (this.PreviousPage != null)
{
PostingPage = (_Page_1)this.PreviousPage;

Label1.Text = ((Label)PostingPage.FindControl("Label2")).Text;
}
else
{
Label1.Text = "Previous Page is Null";
}
}
}


Now, Questions raised when come to validation and Cross Page posting. If client-side validation (using javascript) is disabled on a web form, the validation will greatly depend on server-side validation. But using PostbackUrl on button will redirect to a new page. Although the server side validation has been in place, the problem is being ignored.



What you can do here is to use PreviousPage.IsValid() function.



See the samples below:



protected void Page_Load(object sender, EventArgs e)
{
if (PreviousPage != null)
{
if (PreviousPage.IsValid == true )
{
//Continue
}
else
{
//Return to previous page
}
}
}

Hope the content helps. Cross Page posting may come handy when you really need a tight coupling pages like Wizards.



Thursday, August 21, 2008

SQL Server FullText Search service could not be started

After you have installed SQL Server 2005 on Window Vista, you might find your the service above could not be started, and it returns you error like "the dependency service is missing or marked for future deletion".

The problem is that one of the service named "NTLMSSP" does not exist in Window Vista environment. If you want to know better about NTLMSSP, Live-Search it.

The solution is simple, install SQL Server SP2 for Vista. Then you will find the dependency service removed.

If the problem persisted, DIY method at below:

  1. type in "regedit" in Search to open Registry Editor.
  2. Go to HKEY_LOCAL_MACHINE -> SYSTEM -> CurrentControlSet -> Services
  3. Select msftesql. Check that the display name is SQL Server FullText Search.
  4. Find the item named "DependOnService". Right Click -> Modify
  5. remove the NTLMSSP from the list and Click Ok
  6. Reboot and you can try starting the service again.

Hope it helps.

SQL Server Management Studio missing after installing SQL Server 2005 on Window Vista

Sometimes this could happen when you install or reinstall SQL Server on Window Vista. I am not very sure what is the cause of it but it took away 1-3 days to figure out what was wrong with all these. It will be even worst when you find your Business Intelligence Development Studio missing as well.

Ok, do not worry about it.

What you need to do is

  1. Do not uninstall it.
  2. Go to your Microsoft SQL Server folder -> 90 -> Tools. And rename the Tools folder name to Tools-Bak
  3. Insert your SQL Server DVD and Browse it.
  4. Find a folder named Tools and execute the installer in the folder. It will basically install the missing tools (Management Studio, etc) and Sample Database.
  5. if you have problem with the SQL Server instance attaching the sample databases, do not install it else it will bring more headaches to you.
  6. Once you have finished installing the tools.. you will find a new Tools folder appear in your Microsoft SQL Server -> 90 folder.
  7. Now it should solve your headaches. Do not think it is finished, Apply Service Pack 2.

Hope It helps.

Thursday, August 7, 2008

How to deploy Silverlight component on IIS

When you publish your website to IIS, most probably you will find your xap file copied along into the server. But when you open it in your web browser, you may not be able to see the Silverlight component in your website. There is one thing that you may need to do in order to see it, it is to

Register your silverlight extension to MIME type

Go to your IIS, Add MIME type

Extension: .xap

Application: application/x-silverlight-app

How to integrate Silverlight component into ASP.Net Website

To integrate your Silverlight component into ASP.Net Website, all you need is your xap file. You may find it under Bin folder inside your Silverlight project folder. Before you copy it, make sure you have build and compiled it.

Steps:

  1. In your Website project, create a folder named “ClientBin”.
  2. Copy the xap file from your Silverlight application project into the ClientBin folder.
  3. Open your Website project in VS 2008, and include the ClientBin folder into the solution. To include it, you need to open your Solution Explorer, click on the “Show All File” icon, and then right click on the invisible (ClientBin) folder and select “Include In Project”.
  4. Then open the web page that you want to insert your silverlight component.
  5. <!-- If ASPX page, use ScriptManager and Silverlight control -->
    <form id="form1" runat="server" style="height:100%;">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div style="height:100%;">
    <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/Sample.xap" MinimumVersion="2.0.30523" Width="100%" Height="100%" />
    </div>
    </form>

    <!-- If HTML page, use Object control -->
    <div id="silverlightControlHost">
    <object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="100%" height="100%">
    <param name="source" value="ClientBin/Sample.xap"/>
    <param name="background" value="white" />

    <a href=http://go.microsoft.com/fwlink/?LinkID=115261 style="text-decoration: none;">
    <img src="http://o.microsoft.com/fwlink/?LinkId=108181" alt="Gt Microsoft Silverlight" style="border-style: none"/>
    </a>
    </object>

    <iframe style='visibility:hidden;height:0;width:0;border:0px'>
    </iframe>
    </div>



  6. Verify it by debugging your website project and view the page.