Search

Jun 10, 2008

Some Weird/Good behaviour of Mozilla

I face one problem in Mozilla but with other browser it works fine.

The problem was like... the page get called twice!!! There is case when the server side code called twice, not client side.

After doing some good work found the solution, and was simpley good. The following line was causing the problem.

<asp:Image ID="imgTest" runat="Server" />

In first look you can see there is no problem with it. But there is still problem; the missing ImageUrl. Mozilla send request to current page asking for an image, which we havent set yet; as the value get assign from server side, by this reason the only server side code is get executed twice!!!!

Interesting, isn't it!!

So here is the solution:

<asp:Image ID="imgTest" runat="Server" ImageUrl="abc.jpg" />

Jun 8, 2008

Working with Extension less URL

Many of us are some time requires to hanlde request which does not contains the extension.

http://yourdomain.com/imran
http://yourdomain.com/knowledge
http://yourdomain.com/world

If you want to achive this functionality then you have to use third party ISAPI module or IIS 6.0 Wildcard mapping feature.

If you goes with ISAPI module, then you should have dedicated server to install that module. And with the other approch of IIS 6.0 Wildcard mapping, its created the proformance problem, as each and every request it tries to apply mapping and degrade the performance.

So in this case the following solutions is good and easy.

What if you made request to a page which out extension? Yes, you will get HTTP 404 page, and IIS are not automatically forward your request to ASP.NET; we can't serve the URL.

So here is the solution,

- Configure the IIS so that; each 404 error page should get redirect to an ASPX page.
- Write the few lines of .NET code.

Thats it.

Lets see how we can do this.

Step 1: Configure IIS for redirection








Step 2: Write the .NET code

You have to capture Application_BeginRequest and put the specilized code to grab 404 url.

protected void Application_BeginRequest(object sender, EventArgs e)
{
if (Request.Url.ToString().Contains("404;"))
{
string[] urlInfo404 = Request.Url.Query.ToString().Split(';');

if (urlInfo404.Length > 1)
{
string strRequestUrl = urlInfo404[1].Replace(":" + Request.Url.Port + "/", "/");

//You got the URL now take action on it.
}
}
}

Benefits:

- No third party ISAPI module
- No Wildcard mapping; leads to good profermance.

More on this article? Read the ScottGu's Blog on Tip/Trick: Url Rewriting with ASP.NET.

Jun 4, 2008

SQL SERVER 2008 (KATMAI): SQL Server 2008 (KATMAI) TSQL Enhancements - 1

SQL SERVER 2008 (KATMAI): SQL Server 2008 (KATMAI) TSQL Enhancements - 1

SQL Server And XML: XML Workshop XX - Generating an RSS 2.0 Feed with TSQL(SQL server 2000)

I love to work with RSS and ATOM. Here is one more good and powerful feature of Sql Server.

The FOR XML EXPLICIT approach will work for both SQL Server 2000 and 2005/2008. You can find the article here, here or here.

May 31, 2008

Duplicate key/value pair in Querystring

I was facing a problem, when the Application_AuthenticateRequest get fails and redirects to login page of the system along with the ReturnUrl which contains the actualy requested url.

Problem was like my ReturnUrl contains the same key twice, which leads to crash in system.

Apart from this, I found in Trace that the ReturnUrl is fine at the requested Page.
like... I made request for http://www.imran/MyProfile.aspx?id=102; it shows 302 as [redirected flag] and the ReturnUrl get the value of http://www.imran/MyProfile.aspx?id=102, but when it goes to Login.aspx it shows 2 query string params.

1. ReturnUrl = http://www.imran/MyProfile.aspx?id=102
2. id=102

Here is the problem, we can see the id is part of ReturnUrl, but in this case it generates following redirection url

Login.aspx?ReturnUrl=http://www.imran/MyProfile.aspx?id=102&id=102

Now when I ask for Request["id"], which gives me value comma saperate like 101,102 and this is what we can say a bug.

After searching long I found the solution, which include the Event that we have to capture in Global.asax, and one property of Response object which sets/gets the Http location Header, here is the code.


protected void Application_EndRequest(object sender, EventArgs e)
{
if (Response.RedirectLocation != null && Response.RedirectLocation.Contains("ReturnUrl"))
{
Response.RedirectLocation = string.Format("{0}ReturnUrl={1}",
Response.RedirectLocation.Remove(Response.RedirectLocation.IndexOf("ReturnUrl")
, (Request.RawUrl.Contains("ReturnUrl") ?
Request.RawUrl.Substring(Request.RawUrl.IndexOf("ReturnUrl") + 10)
: Request.RawUrl
)
));
}
}

This will add the RawUrl into ReturnUrl so there will be no duplication.

May 28, 2008

The generations of GC

As we all knows the .NET garbage collector provides a high-speed allocation service with good use of memory and no long-term fragmentation problems.

This article explains the generation of the GC.

When an object is created it will be on managed head. The managed heap are devided in mainly 3 groups, that are based on the age of variable. These is called Generations. Its useful to previent memory leak on managed heap. As far as performance is concern GC search the dead object on each of these generation at a time.

So lets see these groups [generations]

1. Gen0 [Generation 0]
The objects falles under this category are short leaving, and they are on the top zone of heap. GC is quick to collect and get them destroid, so this swipe is more ofen to release the memory space.

2. Gen1 [Generation 1]
It contains all the living objects from Gen0 that have survived to several Gen0 collects. That means they are upgraded from Generation 0 to Generation 1!!. The zone of Gen1 is in the middle of the heap and so the swipe is less then Gen0

3. Gen2 [Generation 2]
The last group which contains all the living objects from Gen1 that have survived to several Gen2 collects. The age of these object are logner then all and its expensive to destory them, by this reason GC will hardly swipe this area. Its in the lowest memore zone of the heap that is at the bottom.

Read more : Framework-Internals

Extension Methods in C# 3.0

Extension methods are static methods that can be invoked using instance method syntax. In effect, extension methods make it possible to extend existing types and constructed types with additional methods.
Note: Extension methods are less discoverable and more limited in functionality than instance methods. For those reasons, it is recommended that extension methods be used sparingly and only in situations where instance methods are not feasible or possible.
Extension members of other kinds, such as properties, events, and operators, are being considered but are currently not supported.
Lets see the example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Features
{
public static class Extensions
{
public static int ToInt32(this string s)
{
return Int32.Parse(s);
}
}

class Program
{
static void Main(string[] args)
{
string strTest = "1";
Console.WriteLine(strTest.ToInt32()); //Will print 1
}
}
}


Now lets look close to the following statement
(this string s)

This means, method ToInt32 is applied to a variable which type is string.

So simple as that :)

Reand More on C# 3.0

May 15, 2008

How one can generate objects scripts with DROP and Create in same file in SQl Server 2005 Like in SQl Server 2000

I often generate scripts of stored procedures and save that code in a txt file,in development env its very crucial because to overwrite stored procedures any other development db.

For my this task sql server 2000 was very good it generated drop and create statemntments implicitly. But now in sql server its very difficult and in our development environment there are more than 3000 procs so when i try to generate script in sql server 2005 ,first i need to generate "drop to" and then "create to" and it also take a very long time and often goes to stuck...

I found solution from Microsoft site, we just need to install SQL Server 2005 SP2.

If you interested to see whats new in SQL Server 2005 SP2 then check it out here.

May 7, 2008

Converting row to column in Sql Server 2005

Consider the following data and our target is to have all the ClientId starting form 247 to 252 will be in column
name Client1, Client2... etc. 
UserID      CaseID      CaseNumber  ClientID
----------- ----------- ----------- -----------
80 216 1087 247
80 216 1087 248
80 216 1087 249
80 216 1087 250
80 216 1087 251
80 216 1087 252
80 276 1140 328
80 277 1143 329
80 347 1191 438
80 348 1192 439

SQL Server 2005 introduced Ranking, Partitioning and Pivoting. By using all togather
we can achive our goal.



Ranking functions that provide the ability to rank a record within a partition. 
In this case, we can use RANK() to assign a unique number for each record, and partition
by the ClientID (so that the RANK will reset for each ClientID)

By prefixing some text to the rank number, we end up with something like:


SELECT UserID, C.CaseID, CaseNumber, ClientID, 
'ClientId' + CAST(
RANK() OVER (
PARTITION BY C.CaseID, CaseNumber
ORDER BY ClientID) AS VARCHAR(10)) ClientIdListing
FROM [Case] C, CaseClient CC
WHERE C.CaseId = CC.CaseID AND USerID = 80

Result:


UserID      CaseID      CaseNumber  ClientID    ClientIdListing
----------- ----------- ----------- ----------- ------------------
80 216 1087 247 ClientId1
80 216 1087 248 ClientId2
80 216 1087 249 ClientId3
80 216 1087 250 ClientId4
80 216 1087 251 ClientId5
80 216 1087 252 ClientId6
80 276 1140 328 ClientId1
80 277 1143 329 ClientId1
80 347 1191 438 ClientId1
80 348 1192 439 ClientId1

The new column (ClientIdListing) is the concatenation of the literal string "ClientId"
and the string representation of the number that the RANK function returned. But
the bigger point is that now this column can be used for pivoting, and result in
a series of new columns called [ClientId1], [ClientId2], [ClientId3], etc.




Pivoting in SQL Server 2005 requires explicit declaration of values as a column
list. In this case, we can't just say "Pivot on the ClientIdListing column", but
rather must say "Pivot on the ClientIdListing column, and make new columns only
for these specific values". This restriction is a little bit of a downside because
we need knowledge of the values in the column. Or, in this case, we need to know
how many ClientIds a Case could possibly have so that we create enough columns in
the result.




So here is the final query:

SELECT * FROM
(SELECT UserID, C.CaseID, CaseNumber, ClientID, 'ClientId'
+ CAST(RANK() OVER (PARTITION BY C.CaseID, CaseNumber
ORDER BY ClientID)
AS VARCHAR(10)) ClientIdListing
FROM [Case] C, CaseClient CC
WHERE C.CaseId = CC.CaseID
AND USerID = 80) P

PIVOT
(MAX(ClientID) FOR ClientIdListing IN
(ClientID1, ClientID2, ClientID3, ClientID4, ClientID5, ClientID6)
) AS Clients

And here is the Output:


UserID CaseID CaseNumber ClientID1 ClientID2 ClientID3 ClientID4 ClientID5 ClientID6
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
80 216 1087 247 248 249 250 251 252
80 276 1140 328 NULL NULL NULL NULL NULL
80 277 1143 329 NULL NULL NULL NULL NULL
80 347 1191 438 NULL NULL NULL NULL NULL
80 348 1192 439 NULL NULL NULL NULL NULL