Solving SharePoint 2010 Setup Errors Manually

2 Comments | Mar 13, 2012

If you are installing SharePoint 2010 on a new box you might see the Setup Errors notification from the installer. In my case, I am using Windows Server 2008 R2, but I have seen the similar Error on Windows 7 as well with little less requirements.

sperror

As you can understand all the “-“ bullets are the requirements that needs to be installed or configured on the box.

There are two ways to do this

1) Microsoft SharePoint 2010 Product Preparation tool

In the SharePoint 2010 Splash Form, you can find that with title “Install software prerequisites” or alternatively you can run file “PrerequisiteInstaller” on the same folder as of the setup file. 


2) Manual installation of Prerequisites

Now the question is, why would one select to chose the manual installation when we already have utility provided by Microsoft. The answer is that utility some time fails Smile for me at least, it fails 2 / 3 times.

So, let me explain all of them one by one.

- “A System restart …….”

Hopefully you will not see this because I am installing SharePoint 2010 just after an other installation that is why it is there. So if you see this better to restart your machine.

- “This product requires Windows Identity Foundation”

Download  KB Update from http://www.microsoft.com/download/en/details.aspx?id=17331
Select your operating system carefully. Windows 6.1 is for Windows 7 & 2008.

- “……… Sync Framework Runtime”

Download from http://www.microsoft.com/download/en/details.aspx?id=17616
It downloads a zip file which have five folders container some setup. Now, you don’t need to run all the setups. Execute the setup inside “Microsoft Sync Framework” and you are done with this step.

- “…….. SQL Server 2008 Native Client”

Download it form http://www.microsoft.com/download/en/details.aspx?DisplayLang=en&id=8824
Scroll down to find Microsoft SQL Server 2008 Native Client

- “Windows server features or role services required …. ”

For sure, you will not face this issue in Windows 7 because there is nothing like server featured in Windows 7 but In Windows 2008 (maybe) for security reasons you have configure the features that will be used through Server Manager. To do that

1) Go to Server Manager
2) Select the Features from the tree on the left hand
4) On the right hand you have a page with Feature Summary Panel. Click on Add Features and following window will appear.

spsf

From the list of Features  you have to select the following:

.Net Framework 3.5.1 Features with WCF Activation
Message Queue
Remote Server Administration Tool
Windows Process Activation Service with all sub options.
and feature settings is complete.

5) Select the “Roles” from the tree on the left hand.
5) If you are working on a new box, you will see only Role Summary section in the configuration on the right hand.
7) Click the Add Roles button on the Role Summary panel. The following window will appear

spbub

This window is only informing you about the security concerns. So just click next. The following window have the list of Server Roles available. Microsoft SharePoint 2010 require Application Server and Web Server to be installed. So select them from the window.

spssr

Notice the required sections are highlighted in the underline. Since I have all these requirement already installed that is why the buttons are disabled, but it should be enable for you.

In the Web Server (IIS) section, make sure to select asp.net. However, the default selection is what you needed. Once you finish this, your Roles window should look like this

sprw

Containing sections for Application Server and Web Server.

 

- “Microsoft Filter Pack 2.0 required ……..”

Ok, you will find Filter Pack 1.0 easily on internet, but that is not the requirement. Actually, Filter Pack 2.0 is available with the name of Microsoft Office 2010 Filter Packs which actually make sense because SharePoint 2010 is the part of Office Suit 2010. Anyway, you can get it from http://www.microsoft.com/download/en/details.aspx?id=17062


- “Internet Information Services 7.0 or higher is required …….”

In Windows 2008, If you have successfully completed the Features and Roles configuration, this is already done because in Role Configuration we already installed Web Server (IIS).

For Windows 7, you have to make sure that IIS 7.0 is installed and configure to  run asp.net.

- “IIS 6.0 Management Compatibility…….. ”

For windows 2008, it is completed with Features and Roles Configuration. But to make sure

1) Go to Server Manager
2) Roles
3) From the Web Server (IIS) panel on the right hand (not on the tree), maximize the Role Service and see if you have IIS 6 Management Compatibility there like below

spimc

For Windows 7,

1) Go to Program and Features
2) Select Turn Windows features on or off.
3) Make sure you have IIS Management Compatibility feature checked under Internet Information Services.

spimc7

- “Microsoft .net Framework 3.5.1 required  ……. “

For Windows 2008, if you have completed Features and Roles configuration you are done. For Windows 7, just make sure that you have .net Framework 3.5 SP 1 runtime is installed. Get it from http://www.microsoft.com/download/en/details.aspx?id=22

 

- “Hotfix for Microsoft Windows (KB976462)”

This is Windows 2008 R2 Specific, which can be found at
http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=23806

- “Microsoft Chart Control ……..”

It is straight forward setup download which you can get it from here
http://www.microsoft.com/download/en/details.aspx?id=14422

 

Hopefully once the above steps are taken, the setup errors will be finished. Your comments are welcome if you face any issue which is not listed above and you think that can help someone else.

Installing SQL Server 2008 on Windows Server 2008 R2

Add Comment | Mar 13, 2012

In my attempt of installing and configuring SharePoint 2010 Farm, I have given a new Windows Server 2008 R2 box that should have SQL Server 2008.

So when I attempt to install SQL Server 2008 on it, I came across the following error message.

sqlerror_thumb[3]

Not so weird because every server product have a set of requirement to be installed. First off, before you do any thing Just run the Windows Update. That’s recommended because there can be some thing else that is not mention in this post or any other but can hanged you for some time.

Ok now come to the second part of Enabling .Net Framework Core Role. For that you have to
1) Open Server Manager and Go to the Features on the tree available on left hand.
2) From the Features Summary, Click Add roles.
3) Following window will appear.

selfeatures_thumb[2]

4) You have to check the top most option which is (in my case) .net Framework 3.5.1 Feature. That’s it

if you are installing SQL Server 2008 for SharePoint, make sure to check WCF Activation also, Like I did.

Cheers

Ambiguous in the namespace problem

6 Comments | Feb 28, 2011

From the last few days, I was ignoring an error that keep coming at the compile time. I spent some two hours on it before but didn’t get it work. The error is quit confusing and of course difficult to manage.

'ApplicationSettingsBase' is ambiguous in the namespace 'System.Configuration'

'MailMessage' is ambiguous in the namespace 'System.Net.Mail'

And there are couple of other similar errors that is pointing to some ambiguous references in my project.  The confusing part is that the MailMessage object throws similar error when you are importing the old and new email namespace.

For example,

Imports System.Web.Mail
Imports System.Net.Mail

So if you are only encountering ambiguous problem in MailMessage object. It is more possible that you have define both the namespaces in your code behind which is actually confusing the compiler about your referencing object.

The quick solve for this problem is that remove Imports System.Web.Mail and it should work smooth. But with me, I never used the old asp.net mail namespace in my project.

Then I start looking at my references and luckily I found the problem there. Follow the steps below to investigate the issue

1. Go to your project

2. Then references

3. Right click on “System” and see properties. it should point to the following path

x:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll

Where x is name of your operating system directory. This was the problem with my project. I had my operating system install on “D” drive and some how it is pointing to “C” drive which is the root cause of this problem.

After that I verify all my references and found 5 –6 assemblies that are pointing to wrong path and get it worked.

Also note, the problem can occur in any type of project either it is website , web application etc.

Setting up SVN on Windows

6 Comments | Feb 05, 2010

Subversion is ultimately one of the best source control option we have in today’s world. it has very light instance running on Server and of course it is FREE.

To access the Subversion repository on the client machine we have multiple options. If we want to use shell integrated UI (means we can call your source control options in our windows explorer), we can use TortoiseSVN but being a developer based on Visual Studio it always looks good to get my source control on Solution Explorer inside Visual Studio world and for that we have Visual SVN  which off cost  and  AnkhSVN which is FREE.

One time server configuration is needed on almost every server software so as with SVN. After downloading and installing SVN following configuration is needed in order to work properly. By the way, we are assuming that you download the setup from CollabNet.

Download URL : http://www.open.collab.net/downloads/subversion/

Installing SVN (CollabNet):

This installation is next next stuff but the following screens needs a little awareness.

settingup_svn_service

Port will be the default port on which the Subversion server listen for the request and the repository is a location where your source code will be saved.

Notice the checkbox, titled “Install svnserve to run as Windows service”. If this box is checked SVN will run as windows service and will be available as soon as the Server Machine starts.

settingup_svn_apache

It is important to understand that the SVN works on the Apache web server. If you are already using any other web server such as IIS, it is important to change the port of the Web Server. Also, an other checkbox is available to run the Apache web server as windows service.

Configuration:

Well, the above mentioned setup has done almost every thing for us. But still following configuration needs to understand in case of getting command over SVN.

 

    1. Configure SVN to run as service (Manually)
    2. Creating Repository (Manually)
    3. Configure Security
      1. Enable / Disable anonymous access
      2. Create Users
      3. Authorization
    4. Firewall Consideration 

Configure SVN to run as service (Manually):

To create SVN run as Windows service, we need to open CMD and run the following command

sc create svnserve binpath= "
    \C:\Program Files (x86)\CollabNet\Subversion Server\svnserve.exe\"
    --service --root c:\repos" displayname= "SubVersion Server" 
    depend= tcpip start= auto

 

Notice that the path of the svnserve.exe might be change in your case. Once we run this we can now see our newly created service in the service console.

settingup_svn_servicelist

Just in case, if we want to delete the service we can run the following command in cmd
sc delete svnserve

Creating Repository (Manually):


To create repository we need to use svnadmin utility. Following is the procedure

    1. Go to Run (Ctrl + R) –> CMD
    2. Go to the install directory of SVN in my case it is ( C:\Program Files (x86)\CollabNet\Subversion Server)
    3. Run command : svnadmin create C:\svn_repository  (we can change the path according to our need)

Configure Security:

Like other source control, you can create users in svn, give them right what they can do and all that important stuff but the user right assignments are change from repository to repository.

Once you successfully create a repository, you will find the following items under the folder of repository.

settingup_svn_folder

Now open the “conf” folder and create the following file (if it is not already there)svnserve.conf

and add the following lines

[general]
anon-access = read
auth-access = write
authz-db = authz
password-db = passwd

Disable anonymous access:

Anonymous access can be very useful in many scenario but in our case, we want to disable this access. To do this, we will edit svnserve.conf file and comment the anon-access line. after editing that file, svnserve.conf file will look like as below

[general]
#anon-access = read
auth-access = write
authz-db = authz
password-db = passwd

Of course, to enable the access we have to un comment this line.

Create Users :

If you have notice the last line we wrote in svnserve.conf file, it is password-db = passwd. Basically, it is the name of the file which contains the information about users.

Now lets create a file named “passwd” with no extension and add the following lines.

[users]
admin = adminpassword
admin2 = admin2password
ausman = ausmanpassword
ruser = ruserpassword

Note that the string before “=” is user id and the later one is password. if you still confuse, here is the formulae :)

username = password

That’s how, this file is saving the user information. Now, create as many users you want.

Authorization:

Now notice the second last line of the svnserve.conf file, where it says authz-db = authz. Basically, it is the name of the file which contains the authorization information about the users.

Now let’s consider the situation, where you want to create two set of users in your repository. It can be “Administratots” and ‘Regular Users’. You want to give read / write permission to both the users but on some folders you want only “Administrators” to write  files.

Now lets create a file named “authz” with no extension and add the following lines.

[groups]
adminstrators = admin, admin2
regulars = ausman, ruser

[repository:/]
* =
@adminstrators = rw
@regulars = rw

[repository:/trunk/admin-files]
* =
@adminstrators = rw

Ok, now let me explain how we did the whole thing line by line.  In the first three lines we simple created two groups that we discussed before.
On line no 4-7, we gave general write permission on every folder of the repository to both the groups.
On line no 8-10, we gave a special write permission to group named “Administrators”  for a folder called “admin-files”.

There we go, every thing is configured and we are ready to access the files from SVN Client.

Firewall Consideration:

As mentioned earlier SVN server listen for the request on port number 3690. In my case of implementation, the server was using Windows 2008 built-in Firewall which means, I can access the SVN server locally but from any remote machine I wasn’t able to get the files..

To do that, we simply need to add the port 3690 in the exception list of Firewall and allow the traffic coming thru this port.

That’s it and we are all done :)

Getting started with Unit Testing in C#

One Comment | Aug 07, 2009

Introduction:

In this post, I will explain you how can we write a unit test in c#. It is a basic guideline for those who wants a quick start.

Unit testing is an integral part of any software that is developed. It is an advantage which most of us are either not aware of or we are neglecting it.  It actually helps a developer to write error free code.

To write unit test, we will first install a unit-testing framework.

 

About Unit-Testing Framework:

Well, Unit-Testing Frameworks are useful to simplify the process of unit testing. If you don’t want to use any framework then you can still do unit-testing by writing the client code which implements assertions, exception handling etc.

There are numerous framework available for unit testing. A list of which can be found here . But in our case, we will use NUnit to test our code because it is easy to use, show detail test reports and of course open source.

 

Installing NUnit:

To download the NUnit goto : http://www.nunit.com/ and download NUnit Windows MSI. The installation is a conventional next next stuff. So, you will not face any hard time.

 

Writing Testable code:

Now open visual studio and create a new console application (I name it TestAbleApp). Please note, to do unit-testing it is not important to write your code in console application. It is just a matter of my choice because I want to make it simple and easy to understand.

Create a new class call it “Utilities” and write the following code.

public class Utilities
{
    public enum Gender
    { Male =1,
      Female = 2
    }


    public string GetCompleteProfession(string professionName, Gender g)
    {
        string strPronoun = string.Empty;

        if (g == Gender.Male)
            strPronoun = "he";
        else
            strPronoun = "she";

        if (Regex.IsMatch(professionName,"^[aeiou]"))
            return strPronoun + " is an " + professionName;
        else
            return strPronoun + " is a " + professionName;
    }

    public decimal GetWeeks(DateTime dtFrom, DateTime dtTo)
    {
        int Days = ((TimeSpan)(dtTo - dtFrom)).Days;
        decimal Weeks = Math.Ceiling((decimal)Days / 7);
        return Weeks;
    }
    public decimal GetDays(DateTime dtFrom, DateTime dtTo)
    {
        int Days = ((TimeSpan)(dtTo - dtFrom)).Days;
        return Days;
    }
}

Let me explain, we have an enum here which hold the gender and we have a function which have Profession and Gender as parameter. it will simply return a formatted string. For example if someone pass

GetCompleteProfession(“System Analyst”,Gender.Male). It will return “He is a System Analyst”. A very simple function.

Then we have a function that will take date range as parameter and return the number of weeks in that range. We call it GetWeeks and another function is GetDays which takes same date range as parameter but return days instead of week.

We are completed with the testable code. If you want, you can check the output of the functions.

 

Writing Unit-Test:

To write a unit-test, create a class library project under the same solution and call it, “TestProject”. Now, create a new class and name it “UtilitiesUnderTest”. The naming convention can explain that this class contain the unit test of class “Utilities”.

Now, Add the executable of console application which we have created before (In my case, it is TestableApp ) as a reference in TestProject.

To use the NUnit Testing framework, we also need to add the reference of NUnit Dll which you will find under the .net Tab in Add Reference window.

sc_unittest_1

 

Create a class and call it UtilitiesUnderTest. Naming convention shows that we are creating a test code for class “Utilities”. Now write the following code.

[TestFixture]
class UtilitiesUnderTest
{
    [Test]
    public void GetCompleteProfession_Return_SheIsASoftwareEngineer()
    {
        
        Utilities objUtil = new Utilities();

        string strResult = objUtil.GetCompleteProfession("software engineer", Utilities.Gender.Female);

        StringAssert.AreEqualIgnoringCase("She is a software engineer", strResult);
    }

    [Test]
    public void GetCompleteProfession_Return_HeIsAProjectManager()
    {
        Utilities objUtil = new Utilities();

        string strResult = objUtil.GetCompleteProfession("software engineer", Utilities.Gender.Male);

        StringAssert.AreEqualIgnoringCase("He is a software engineer", strResult);
    }

    [Test]
    public void GetCompleteProfession_Return_HeIsAnEngineer()
    {
        Utilities objUtil = new Utilities();

        string strResult = objUtil.GetCompleteProfession("engineer", Utilities.Gender.Male);

        StringAssert.AreEqualIgnoringCase("He is an engineer", strResult);
    }

    [Test]
    public void GetWeeks_Return_6()
    {
        Utilities objUtil = new Utilities();

        decimal weeks = objUtil.GetWeeks(DateTime.Now.AddDays(-42), DateTime.Now);

        Assert.AreEqual(6, weeks);
    }

    [Test]
    public void GetDays_Return_25()
    {
        Utilities objUtil = new Utilities();

        decimal days = objUtil.GetDays(DateTime.Now.AddDays(-25), DateTime.Now);

        Assert.AreEqual(25, days);
    }
}

Notice the Attribute, [TestFixture] is used to mark a class as a test class where as [Test] is used to mark a method as Unit-Test (test method). It is used by Unit testing framework like N-Unit to test the code.

Also notice, the name of methods. It is named like “{MethodUndertestName}_Return_{ExpectedReturnValue}”. The naming convention is there to make your tests readable for others.

Now come to the explanation part of the first three functions.

In the first of line each function we are creating an object of the class under test (In our case Utilities).
In the second line we are calling a method under test by specifying parameters.
In the third line we are using StringAssert to Assert the returned value.

Now notice the last two functions, the first two lines are same. The minor difference is in the last line. Instead of using StringAssert, we are using Assert to test the return value.

Once, you have complete writing the Unit-Test. Now its time to see it in action.

Running Unit-Tests:

Run NUnit, Goto File –> New Project and specify the location.
Now, Goto Project menu and select Add Assembly and locate your TestProject DLL, the one which you created to test your code.
Once, you have done that, you will all your Unit-Test in the left pane as shown below.

sc_unittest_2

Now, click the big run button on the right pane and you will see the result as give below.

sc_unittest_3

Happy ending, green progress bar means every thing went well. Now let’s create another unit-test in out test class which will fail out tests. So that, we can see how NUnit reacts when a test fails.

Lets add the following method in our test class.

[Test]
public void GetWeeks_Return_3()
{
    Utilities objUtil = new Utilities();

    decimal weeks = objUtil.GetWeeks(DateTime.Now.AddDays(-8), DateTime.Now);

    Assert.AreEqual(3, weeks);
}


Here I am giving the range of eight days and expecting my function to return 3 weeks instead of two. Now, when I run the test it will get fail and NUnit display us something like below.

sc_unittest_4

Red progress bar means, some thing went wrong and notice the text area at the bottom. It will show you the detail that you were expecting three but the function returns two. That is the test get fails.

Now lets see what happen when any exception occur in the function we are testing.  Add the following line in GetWeek function

throw new ArgumentOutOfRangeException();

 

Now, when we run out tests, we will see some thing like below.

sc_unittest_5

NUnit fails our test with the exception with Stacktrace at the botoom.

 

Conclusion:

This was just a quick start of doing test driver development and write Unit-Tests that is why we create unit-test for very simple functions. In future, I will be posting the unit-tests which I will write for some more complex functions.

I have tried to make it simple for you guys to grab it and start writing your own unit-test. The resource I found very valuable for starting test driven development is Roy Osherove’s The Art of Unit Testing.

Get Countries Name in .Net

5 Comments | Jul 26, 2009

Introduction:

In this post, I will explain you how can we get the countries name filled in any collection using .net without using any database.

It is a regular task, which we all as developers did some past day but the difference is we used database table or xml file to hold the country names. But .net framework provide us with all the countries information in Globalization namespace.

So, here is the code for that

Dictionary<string,string> objDic = new Dictionary<string,string>();
 
foreach (CultureInfo ObjCultureInfo in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
{
    RegionInfo objRegionInfo = new RegionInfo(ObjCultureInfo.Name);
    if (!objDic.ContainsKey(objRegionInfo.EnglishName))
    {
        objDic.Add(objRegionInfo.EnglishName, objRegionInfo.TwoLetterISORegionName.ToLower());
    }
}
 
var obj = objDic.OrderBy(p => p.Key );
foreach (KeyValuePair<string,string> val in obj)
{
    ddlCountries.Items.Add(new ListItem(val.Key, val.Value));
}

 

Explanation:

Notice that, we have used typed dictionary object to store the name and the values of the countries.

Then, we use CultureInfo.GetCultures to get the cultural information of the countries.

Later on, we use RegionInfo to get the regional information of that  culture.

Since, there can be multiple cultures of the same country that is why there is a condition which check either the country is already added in dictionary. If not, then simply add the country name and country two letter name. (Note : We are treating the two letter country name as the value)

After the loop, I used some LinQ stuff to sort county names, and then iterate through the returned object to add the values in drop down list.

That’s it. Now you are not only limited to show the English name of the country but you can also show the native name. For example, the name of my country in English is “Islamic Republic of Pakistan” but the native name is ???????.

Also, you can get the following country information using RegionInfo

 

sc_clbn_1

Some developers are habitual of using country id along with the country name. if they still want to use some id to save the country information they can use the GeoId property of the RegionInfo.

CodeGain.com .net Community Portal

Add Comment | Jul 21, 2009

A guy named RRaveen  has setup a .net community portal named CodeGain and located on http://www.codegain.com.

Yet the portal is still in process but the content which he has posted is really useful and in fact it really help me in some places.

The best part about this portal is, it is not .net or asp.net specific. You will find articles  on desktop applications, Java, Oracle etc.

Previously, RRaveen had also written some articles on HighOnCoding.com and is active .net community so he is on a great task.

CodeGain

Show Loading Message in Asp.net AJAX

6 Comments | Jul 19, 2009

In this post, I will explain you how can we show Loading message in asp.net ajax without using Update Progress. Now some one may asked, why do I want to skip Update Progress ?

Well, there can be several reasons for this, fist of all you have to work on every single page, and on every update panel to get the update progress working.

There are basically three methods of meeting this requirement.

  1. Using Master Pages : A very smart way, but not all of us are using them .. right ?
  2. Extending Page Class  : A little harder but to me it is very elegant way.
  3. Extending Script Manager : Similar to the page class one, but implementation is comparatively simple.

The Basics:

Before I start with exploring the different approaches let me first create a ground by showing what things will be involve in creating a loading message.

I want the background to be grayed and displayed a simple loading text at the top, for that we need a style sheet, which will apply to the loading message div.  Create a stylesheet and call it style.css

.ModalProgressContainer
    {
        z-index: 10005;
        position: fixed;
        cursor: wait; 
        top:0%; 
        background-color: #ffffff; 
        filter: alpha(opacity=50);
        opacity: 0.5;
        -moz-opacity: .5; 
        height: 100%;
        width: 100%;
        text-align: center; 
        
        } 
    .ModalProgressContent
    {
        padding: 10px; 
        border: solid 0px #000040; 
        font-weight: bold; 
        background-color:#ffffff;
        margin-top:300px;
    } 

Now lets read and understand the following script.

var prm = Sys.WebForms.PageRequestManager.getInstance();
 
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
 
// ----------------------------- //
// the below script will be saved in JS File, create a JS file and call it ajaxload.js and save the following script
 
function InitializeRequest(sender, args) {
    if (document.getElementById('ProgressDiv') != null)
        $get('ProgressDiv').style.display = 'block';
    else
        createContorl();
}
 
function EndRequest(sender, args) {
    if (document.getElementById('ProgressDiv') != null)
        $get('ProgressDiv').style.display = 'none';
    else
        createContorl();
}
 
function createContorl() {
 
    var parentDiv = document.createElement("div");
    parentDiv.setAttribute("class", "ModalProgressContainer");
    parentDiv.setAttribute("Id", "ProgressDiv");
 
 
    var innerContent = document.createElement("div");
    innerContent.setAttribute("class", "ModalProgressContent");
 
    var img = document.createElement("img");
    img.setAttribute("src", "/Images/Images/Loading.gif");
 
    var textDiv = document.createElement("div");
    textDiv.innerHTML = 'Loading....';
 
 
 
    innerContent.appendChild(img);
    innerContent.appendChild(textDiv);
 
    parentDiv.appendChild(innerContent);
 
    
 
    document.body.appendChild(parentDiv);
}

Notice,in the first three lines. We are getting the instance of PageRequestManager and then defining InitilizeRequest and EndRequest functions to display or hide the loading div. Where as, in createControl function we are simply writing DHTML, to be more specific there is no HTML of the loading div in our markup. So, we are writing that from JavaScript.

Also, note the that I have break down this script into two part by using comments. First is the declaration and second is definition of the functions.

note: The definition will take place on a seperate JS file where as the declaration need to be made in the page, under body markup.  Now we are all set to explore different approaches.

 

Using Master Pages :

A very simple approach, all you need to do is open your master page and paste the following lines in the head section.

<link href="style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="ajaxload.js"></script>

And in body, after form tag create a script section and paste the following JavaScript.

var prm = Sys.WebForms.PageRequestManager.getInstance();
 
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest); 

Notice it is the same declaration section which we have discussed above and that’s it you are done. All the content form of your web application should now display loading div on each partial postback.

 

Extending Page Class  :

For this, create a class file and call it ajaxPage and inherit it from System.Web.UI.Page and write the following code.

public class ajaxPage : Page
 
   protected override void OnLoad(EventArgs e)
   {
       //Include CSS File
       Page.Header.Controls.Add(new LiteralControl("<link href='style.css' rel='stylesheet' type='text/css' />"));
 
 
       //Include JS file on the page
       ClientScript.RegisterClientScriptInclude("ajaxload", ResolveUrl("~/ajaxload.js"));
 
       //Writing declaration script 
       String script = "var prm = Sys.WebForms.PageRequestManager.getInstance();";
       script += "prm.add_initializeRequest(InitializeRequest);";
       script += "prm.add_endRequest(EndRequest);";
 
       ClientScript.RegisterStartupScript(typeof(string), "body", script, true);
 
       base.OnLoad(e);
   }
 

Well, we have simply extend the System.Web.UI.Page into our own class and override OnLoad function to include the JS file and write the declaration markup.

Now, on the page code behind where you want to implement Loading message change the inherit namespace from System.Web.UI.Page to ajaxPage (make sure you namespace).

 

Extending Script Manager :

Now instead of extending page class we will extend Script Manager control and for that create a new class file and call it ScrtipManagerExt and write the following code.

public class ScriptManagerExt : ScriptManager
{
    protected override void OnLoad(EventArgs e)
    {
 
        //Include CSS File
        Page.Header.Controls.Add(new LiteralControl("<link href='style.css' rel='stylesheet' type='text/css' />"));
 
        RegisterClientScriptInclude(this, typeof(Page), "ajaload", ResolveClientUrl("~/ajaxload.js"));
 
        String script = "var prm = Sys.WebForms.PageRequestManager.getInstance();";
        script += "prm.add_initializeRequest(InitializeRequest);";
        script += "prm.add_endRequest(EndRequest);";
 
        RegisterStartupScript(this, typeof(Page), "ajaxtest", script, true);
        base.OnLoad(e);
    }
}

Almost the same thing we did in extend page approach, only the implementation will be change. Instead of using the old Script Manager we will use our new one. the include directive and markup will look like as below.

<%@ Register Assembly="AssmblyName" Namespace="NameSpace" TagPrefix="cc1" %>
 
<cc1:ScriptManagerExt ID="ScriptManagerExt1" runat="server">
</cc1:ScriptManagerExt>

That’s it we are done. I tried to make it simpler and show you every possible way I know of doing this task. Again, any approach selection will be on you and your project type. You can also download  the VS 2008 project file.

Migrate from WordPress to BlogEngine.net

Add Comment | Jul 19, 2009

In this post, I will explain how to migrate a blog running on Word Press (Self Hosted) to BlogEngine. But before I start let me say, that Word Press simply rocks. The reason why I plan to switch my blog is customization. Since I am a dotnet geek, I really have no great idea of what I can make out of Word Press using PHP and when it comes to Blogging in .net, I guess I made a very right decision to use BlogEngine. It is open source and included all the necessary blogging utilities.

The main thing which I want to migrate is as follows

  • Post
  • Categories
  • Tags
  • Comments

The moment I start, I was thinking to get some export / import tool. Then I came to know about BlogML. A format that is created to interchange content between different bloging engines. Natively, Word Press don’t support BlogML but Robert McLaws did great job on wiring this tool. Unfortunately, that tool didn’t work for me, for some reason it is keep giving me error.

Finally, I tried it in my own way. Since that blog was self hosted, I have access to mysql database engine through phpMyAdmin. Hence, I decided to export SQL of my related tables and data in MSSQL (TSQL) format.

 

  1. After the login into phpMyAdmin, go to the table list by selecting the databases comes at left.
  2. From the tab at the top select export.
  3. In the export group, select SQL and tables in my case it is wp_comments, wp_posts, wp_term_relationships, wp_term_taxonomy, and wp_term
  4. Now from the SQL Compatibility Mode, Select MSSQL. Save the file and your are complete.

Your selection screen should like like below.

sc_wp_to_be

 

Now open the generated SQL in MSSQL and before you run you might need to fix some column names and some data type issues of the table. But believe that is pretty easy. To help you more, please see the table creation script below

CREATE TABLE [dbo].[wp_comments](
    [comment_ID] [bigint] IDENTITY(1,1) NOT NULL,
    [comment_post_ID] [int] NOT NULL,
    [comment_author] [varchar](200) NOT NULL,
    [comment_author_email] [varchar](100) NOT NULL,
    [comment_author_url] [varchar](200) NOT NULL,
    [comment_author_IP] [varchar](100) NOT NULL,
    [comment_date] [datetime] NOT NULL,
    [comment_date_gmt] [datetime] NOT NULL,
    [comment_content] [text] NOT NULL,
    [comment_karma] [int] NOT NULL,
    [comment_approved] [varchar](20) NOT NULL,
    [comment_agent] [varchar](255) NOT NULL,
    [comment_type] [varchar](20) NOT NULL,
    [comment_parent] [bigint] NOT NULL,
    [user_id] [bigint] NOT NULL,
    [comment_subscribe] [varchar](1) NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [comment_ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
 
GO
 
CREATE TABLE [dbo].[wp_posts](
    [ID] [bigint] NOT NULL,
    [post_author] [bigint] NOT NULL,
    [post_date] [datetime] NOT NULL,
    [post_date_gmt] [datetime] NOT NULL,
    [post_content] [text] NOT NULL,
    [post_title] [text] NOT NULL,
    [post_category] [int] NOT NULL,
    [post_excerpt] [text] NOT NULL,
    [post_status] [varchar](20) NOT NULL,
    [comment_status] [varchar](20) NOT NULL,
    [ping_status] [varchar](20) NOT NULL,
    [post_password] [varchar](20) NOT NULL,
    [post_name] [varchar](200) NOT NULL,
    [to_ping] [text] NOT NULL,
    [pinged] [text] NOT NULL,
    [post_modified] [datetime] NOT NULL,
    [post_modified_gmt] [datetime] NOT NULL,
    [post_content_filtered] [text] NOT NULL,
    [post_parent] [bigint] NOT NULL,
    [guid] [varchar](255) NOT NULL,
    [menu_order] [int] NOT NULL,
    [post_type] [varchar](20) NOT NULL,
    [post_mime_type] [varchar](100) NOT NULL,
    [comment_count] [bigint] NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
 
GO
 
CREATE TABLE [dbo].[wp_terms](
    [term_id] [bigint] IDENTITY(1,1) NOT NULL,
    [name] [varchar](200) NOT NULL,
    [slug] [varchar](200) NOT NULL,
    [term_group] [bigint] NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [term_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
 
GO
 
SET ANSI_PADDING OFF
GO
 
CREATE TABLE [dbo].[wp_term_relationships](
    [object_id] [bigint] NOT NULL,
    [term_taxonomy_id] [bigint] NOT NULL,
    [term_order] [int] NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [object_id] ASC,
    [term_taxonomy_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
 
GO
CREATE TABLE [dbo].[wp_term_taxonomy](
    [term_taxonomy_id] [bigint] IDENTITY(1,1) NOT NULL,
    [term_id] [bigint] NOT NULL,
    [taxonomy] [varchar](32) NOT NULL,
    [description] [text] NOT NULL,
    [parent] [bigint] NOT NULL,
    [count] [bigint] NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [term_taxonomy_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
 
GO 
 

Please note  that it is just the schema script. All you data will be included in mysql generated SQL File which we have created before.

Now, we have all the required tables with data imported from Word Press to Blog Engine Db but we will fill Blog engine tables to show imported data. Lets first start with category.

 

Category:

There is no such table in wp_categories in word press instead it uses wp_term and wp_term_taxonomy to store categories where as in Blog engine we have a table called be_categories which hold categories information. So following query will dump the data from wp_terms , wp_taxonomy to be_categories.

INSERT INTO [dbo].[be_Categories]
           ([CategoryID]
           ,[CategoryName]
           ,[Description]
           ,[ParentID]
           ,[Slug])
     SELECT
           NEWID(),
           w1.[name],
           ('Posts in ' + w1.[name]) as Description,
           NULL, -- as I am not going to make any parent child relation now ...
           w1.[slug]
           FROM [BlogEngine].[dbo].[wp_terms] w1
  INNER JOIN  wp_term_taxonomy w2 on w1.term_id = w2.term_id and w2.taxonomy = 'category'
GO

Posts:

Now lets deal with posts, a very easy query because we have the post table in both the blogging engines. In Word Press it is wp_posts where as in Blog Engine it is be_post.

INSERT INTO [dbo].[be_Posts]
      ([PostID]
      ,[Title]
      ,[Description]
      ,[PostContent]
      ,[DateCreated]
      ,[DateModified]
      ,[Author]
      ,[IsPublished]
      ,[IsCommentEnabled]
      ,[Raters]
      ,[Rating]
      ,[Slug])
 
SELECT newid(),
       post_title,
       post_excerpt,
       post_content,
       post_date,
       post_modified,
      'username',
      1,
      1,
      0,
      0,
      post_name
from wp_posts where post_type ='post'

Post Category Relation:

Now its time to set, which post have which categories. The table which is repsonsible for saving this information is called wp_term_relationship in Word Press and be_PostCategory in Blog Engine. See the following query.

select  wp.post_title ,wtr.name into #temp1 from wp_term_relationships wr inner join 
wp_term_taxonomy wt on wr.term_taxonomy_id = wt.term_taxonomy_id and wt.taxonomy = 'category' 
inner join wp_terms wtr on wt.term_id = wtr.term_id
inner join wp_posts wp on wr.object_id = wp.ID and post_type = 'post'
 
 
 
INSERT INTO [dbo].[be_PostCategory]
           ([PostID]
           ,[CategoryID])
select (select postId from be_Posts where Title= convert(nvarchar(max),t.post_title)),
(select CategoryID from  be_Categories where CategoryName = t.name) from #temp1 t
 
drop table #temp1
 
GO

I guess this query might need some explanation. See, in the top query I am getting the title of posts and name of categories and storing it to temp table.

Now come to the second part, here I insert new reords in be_postcategory based on the category names and post titles we filled before.

 

Tag:

In Blog Engine we have a table called be_PostTag which manage all the tags related stuff but in wordpress again involve all the tables containing wp_term. So, I write the following query which get the data from those tables and store it in Tags.

INSERT INTO [dbo].[be_PostTag]
         ([PostID]
         ,[Tag])
         
         
         
   SELECT
         (select postId from be_Posts where Title= convert(nvarchar(max),wp.post_title)) ,SUBSTRING(w1.[name], 1, 50)
         FROM [BlogEngine].[dbo].[wp_terms] w1
INNER JOIN  wp_term_taxonomy w2 on w1.term_id = w2.term_id and w2.taxonomy = 'post_tag'
inner join  wp_term_relationships wr on wr.term_taxonomy_id = w2.term_taxonomy_id
inner join  wp_posts wp on wr.object_id = wp.ID 
 

Comment:

This one is comparatively easy. We have table called wp_comments in Word Press and be_postcomment in Blog Engine to manage the comments. Here is the final query.

INSERT INTO be_PostComment]
         ([PostCommentID]
         ,[PostID]
         ,[ParentCommentID]
         ,[CommentDate]
         ,[Author]
         ,[Email]
         ,[Website]
         ,[Comment]
         ,[Country]
         ,[Ip]
         ,[IsApproved])
 
SELECT 
      newId()
    ,(select postId from be_Posts where Title= convert(nvarchar(max),wpp.post_title)) as PostID
    ,(select postId from be_Posts where Title= convert(nvarchar(max),wpp.post_title)) as PostID
    ,[comment_date_gmt]
    ,[comment_author]
    ,[comment_author_email]
    ,[comment_author_url]
    ,[comment_content]
    ,NULL
    ,[comment_author_IP]
    ,1
    
FROM [wp_comments] wpc
INNER JOIN BlogEngine.dbo.wp_posts wpp on wpc.comment_post_ID = wpp.ID
where wpc.comment_approved = '1'  

Note : You might see some /r/n between some post and comments. Don’t get afraid of this, just replace “/r/n”  with “<br/>” on effected using Replace function of TSQL.

 

That’s how you can  import all the data from Word Press to Blog Engine and this is fairly a huge issue why people don’t move their blogs.  I have tried to explain the method by making it more simple, if you still face any issue please feel free to contact me.

How to show and select month/year in Calendar Extender

4 Comments | May 31, 2009

In this post I will explain you, How to make calendar extender control to show month / year view by default and instead of selecting dates how can we use calendar extender to select months.

Before I start, let me say that I got extensive support from this forum post http://forums.asp.net/t/1349086.aspx. Thanks to Zhi-Qiang Ni, but the way he follow was a little bit lengthy. However, all credit still goes to him because I gain the exact idea from his post.

Let me start by creating a calendar extender control and attach it to a textbox.

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<cc1:CalendarExtender ID="TextBox1_CalendarExtender" runat="server" OnClientHidden="onCalendarHidden"  OnClientShown="onCalendarShown" BehaviorID="calendar1"
    Enabled="True" TargetControlID="TextBox1">
</cc1:CalendarExtender>


Now, in extender markup, notice onClientHidden and OnClientShown event which I implemented as below.

function onCalendarShown() {
 
     var cal = $find("calendar1");
     //Setting the default mode to month
     cal._switchMode("months", true);
     
     //Iterate every month Item and attach click event to it
     if (cal._monthsBody) {
         for (var i = 0; i < cal._monthsBody.rows.length; i++) {
             var row = cal._monthsBody.rows[i];
             for (var j = 0; j < row.cells.length; j++) {
                 Sys.UI.DomEvent.addHandler(row.cells[j].firstChild, "click", call);
             }
         }
     }
 }
 
 function onCalendarHidden() 
 {
     var cal = $find("calendar1");
     //Iterate every month Item and remove click event from it
       if (cal._monthsBody) {
         for (var i = 0; i < cal._monthsBody.rows.length; i++) {
             var row = cal._monthsBody.rows[i];
             for (var j = 0; j < row.cells.length; j++) {
                 Sys.UI.DomEvent.removeHandler(row.cells[j].firstChild,"click",call);
             }
         }
     }
 
 }

Pretty simple, In onCalendarShown method I just set the default mode to month and then iterate the control to get month item and attach on click event to it. So that, it will not go further to show us dates of that month and select the first day of that month instead.

Where as, In onCalendarHidden I am simply detaching the click event from month items. Now notice the last parameter of Sys.UI.DomEvent.addHandler function, it is the name of the function which will do the rest of the magic as below.

function call(eventElement)
        {
            var target = eventElement.target;
            switch (target.mode) {
            case "month":
                var cal = $find("calendar1");
                cal._visibleDate = target.date;
                cal.set_selectedDate(target.date);
                cal._switchMonth(target.date);
                cal._blur.post(true);
                cal.raiseDateSelectionChanged();
                break;
            }
        }

Here we are simply selecting the month as the selected date of calendar control. and finally the control will look like as below.

cal_extender

You can get the source code from here :
http://cid-cdbfe38dc780f729.skydrive.live.com/self.aspx/.Public/Calendar%20Extender%20Month.zip

Show images on Grid View from File Stream

One Comment | May 26, 2009

 

Background :

In my last post about SQL Server 2008 new feature File Stream (Saving and Retrieving File Using FileStream SQL Server 2008), we did an example of saving an image to the file stream and then retrieve it back and make it available for download.

The result of that example looks like as below.

fs_snapshot1

But, one has to press the button to download the image file. One of my blog reader raise a point that he wants to display the same image instead of Get File button which is going to download.

Introduction :

So, in this post I will explain you, how can we rendered the image before actually downloading it and show that in the grid (Maybe as thumbnail, but this post will not discuss any thing about generating thumbnails).

Note : If you want to know. How to add files to the file stream please see my post Saving and Retrieving File Using FileStream SQL Server 2008

Getting Started:

We will complete this goal by using HttpHandler. lets first alter our gridview.

   1: <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
   2:         onrowcommand="GridView1_RowCommand">
   3:         <Columns>
   4:             <asp:BoundField DataField="ID" HeaderText="ID" />
   5:             <asp:BoundField DataField="SystemNumber" HeaderText="System Id" />
   6:             <asp:TemplateField>
   7:                 <ItemTemplate>
   8:                     <asp:LinkButton ID="lbGetFile" runat="server" CommandName="GetFile" CommandArgument='<%#Eval("ID") %>' ><img src='<%#Eval("ID") %>.jpg' /></asp:LinkButton>
   9:                 </ItemTemplate>
  10:             </asp:TemplateField>
  11:         </Columns>
  12:     
  13:     </asp:GridView>


Notice the link button on line no 8. I have now specify an image tag inside Link button and pass the primarykey of tbl_files as the file name along with random “.jpg”. So that, it can finally looks like as follows

8e7af927-cc7e-4515-8409-d94566246de8.jpg
a3de6abb-382f-484c-822c-7f93e0ede0c7.jpg
4ad64bf1-ea6e-4228-bdc0-300a0cd90f5a.jpg

The idea is, I will attach the handler with jpg file type to accommodate the incoming requests.

Now, lets create HttpHandler and name it “imageHandler”

public class imageHandler : IHttpHandler
{
 
    #region IHttpHandler Members
 
    public bool IsReusable
    {
        get { return false; }
    }
 
    public void ProcessRequest(HttpContext context)
    {
        //Getting file name from incoming request.
        string url = Path.GetFileName(context.Request.Path);
        Guid FileId;
     
        try
        {
            //Since we have all our primary keys stored in GUID
            //Try parsing the file name to Guid
            FileId = new Guid(Path.GetFileNameWithoutExtension(url));
 
        }
        catch (FormatException)
        {
            //If some other JPG file is requested
            FileId = Guid.Empty;
        }
 
        if (FileId != Guid.Empty) // If the call is for valid Image File Stream
        {
            SqlConnection objSqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
            objSqlCon.Open();
            SqlTransaction objSqlTran = objSqlCon.BeginTransaction();
 
            SqlCommand objSqlCmd = new SqlCommand("FileGet", objSqlCon, objSqlTran);
            objSqlCmd.CommandType = CommandType.StoredProcedure;
 
            SqlParameter objSqlParam1 = new SqlParameter("@ID", SqlDbType.VarChar);
            objSqlParam1.Value = FileId.ToString();
 
            objSqlCmd.Parameters.Add(objSqlParam1);
            string path = string.Empty;
            string fileType = string.Empty;
 
            using (SqlDataReader sdr = objSqlCmd.ExecuteReader())
            {
                while (sdr.Read())
                {
                    path = sdr[0].ToString();
                    fileType = sdr[1].ToString();
                }
 
            }
 
            objSqlCmd = new SqlCommand("SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()", objSqlCon, objSqlTran);
 
            byte[] objContext = (byte[])objSqlCmd.ExecuteScalar();
 
 
            SqlFileStream objSqlFileStream = new SqlFileStream(path, objContext, FileAccess.Read);
 
            byte[] buffer = new byte[(int)objSqlFileStream.Length];
            objSqlFileStream.Read(buffer, 0, buffer.Length);
            objSqlFileStream.Close();
 
            objSqlTran.Commit();
 
            context.Response.AddHeader("Content-disposition", "attachment; filename=" + Path.GetFileName(path) + fileType);
            // Here you need to manage the download file stuff according to your need
            context.Response.ContentType = "application/octet-stream";
 
            context.Response.BinaryWrite(buffer);
        }
        else
        { // If the call is for some other JPG file, nothing to do with file stream.
            context.Response.WriteFile(context.Request.Path);
        }
    }

Well, read the comments I wrote in the code. That will of course help you to understand what actually I have done.

And then register the HttpHandler.

<httpHandlers>
    <add verb="*" path="*.jpg" type="LearningApp.imageHandler, LearningApp"/>
</httpHandlers>
Conclusion:

There we go, In this way we can show the images stored on file stream in grid view. You can download both VS 2008 and VS 2010 project files.

Custom Paging in Grid view

9 Comments | May 18, 2009

So, it takes too long for me to write this post. even though I completed the coding stuff a week back but it is really hard to manage time these days.

In this post, I will explain and demonstrate you how to create custom paging in Grid view control. Paging which works like the Google Paging. Let me elaborate more, say for example you have a record set of 500 items and you want to display 10 items per page. Now what happen to the pages numbers. Either you use the default with “..” sign after 10th page link which cause the post back and then get some new page numbers. Or you want to make it like Google. i.e as soon as user move forward on page index, hide the previous pages and show the new numbers and when user is getting back hide new numbers and show the previous page links. following image can give you some idea what we are going to do.

gvpaging_sc


 gvpaging_sc2

To start, lets first create a Grid view .

   1: <asp:GridView ID="GridView1" runat="server" AllowPaging="True" 
   2:     onrowcreated="GridView1_RowCreated" >
   3: </asp:GridView>

Yes, we have allow the paging but we are not going to use the default paging of asp.net. That is why we have write onrowcreated implementation in which we will simply detect and hide the pager row.

   1: protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
   2:  {
   3:      if (e.Row.RowType == DataControlRowType.Pager)
   4:      {
   5:          e.Row.Visible = false;
   6:      }
   7:  }

Now lets move to some global variables which we need through out our code.

   1: const int pageSize = 10;
   2: const int pageDispCount = 10;
   3: private DataTable dt = new DataTable();

pagesSize : number of records we want to display per page.
pageDispCount : number of page numbers we want to display on custom paging.
dt : A datatable which we will use to store data and use it on different post backs.

Ok, now we need to get data from database, dump it to datatable and define the datasource of grid view.

   1: protected void bindData()
   2: {
   3:     SqlConnection objSqlCon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["AdventureWorksConnectionString"].ToString());
   4:     objSqlCon.Open();
   5:  
   6:     SqlDataAdapter objSqlDa = new SqlDataAdapter("select * from Production.Product", objSqlCon);
   7:     
   8:     objSqlDa.Fill(dt);
   9:  
  10:     GridView1.DataSource = dt;
  11:     GridView1.DataBind();
  12:  
  13:     managePaging(dt);
  14: }

 

 

On line number 13, managePaging function will be used later to implement the paging logic. But before that, lets understand that we have taken the datatable as a global variable and each time after postback when we try to read our datatable we will get no results because there is no state management for this object.

So lets override the LoadViewState and SaveViewState function of System.Web.UI.Page to save and restore the datatable by using viewstate.

 

   1: protected override object SaveViewState()
   2: {
   3:   object baseState = base.SaveViewState();
   4:   return new object[] { baseState, dt };
   5: }  
   6: protected override void LoadViewState(object savedState)
   7: {
   8:   object[] myState = (object[])savedState;
   9:   if (myState[0] != null)
  10:       base.LoadViewState(myState[0]);
  11:  
  12:   if (myState[1] != null)
  13:   {
  14:       dt = (DataTable) myState[1];
  15:       GridView1.DataSource = dt;
  16:       GridView1.DataBind();
  17:  
  18:       managePaging(dt);
  19:   }
  20:   
  21:   }

Well, SaveViewState function is simply putting the base.SaveViewState object and datatable in and object and returning it. A Simple Logic :)

Where as, LoadViewState is retrieving and type casting the object exactly in the sequence it was save in the SaveViewState method.

   1: protected void managePaging(DataTable _dt)
   2: {
   3:     if (_dt.Rows.Count > 0)
   4:     {
   5:  
   6:         // Variable declaration
   7:         int numberOfPages;
   8:         int numberOfRecords = dt.Rows.Count;
   9:         int currentPage = (GridView1.PageIndex);
  10:         StringBuilder strSummary = new StringBuilder();
  11:  
  12:  
  13:         // If number of records is more then the page size (specified in global variable)
  14:         // Just to check either gridview have enough records to implement paging
  15:         if (numberOfRecords > pageSize)
  16:         {
  17:             // Calculating the total number of pages
  18:             numberOfPages = (int)Math.Ceiling((double)numberOfRecords / (double)pageSize);
  19:         }
  20:         else
  21:         {
  22:             numberOfPages = 1;
  23:         }
  24:  
  25:  
  26:         // Creating a small summary for records.
  27:         strSummary.Append("Displaying <b>");
  28:  
  29:         // Creating X f X Records
  30:         int floor = (currentPage * pageSize) + 1;
  31:         strSummary.Append(floor.ToString());
  32:         strSummary.Append("</b>-<b>");
  33:         int ceil = ((currentPage * pageSize) + pageSize);
  34:  
  35:         //let say you have 26 records and you specified 10 page size, 
  36:         // On the third page it will return 30 instead of 25 as that is based on pageSize
  37:         // So this check will see if the ceil value is increasing the number of records. Consider numberOfRecords
  38:         if (ceil > numberOfRecords)
  39:         {
  40:             strSummary.Append(numberOfRecords.ToString());
  41:         }
  42:         else
  43:         {
  44:             strSummary.Append(ceil.ToString());
  45:         }
  46:  
  47:         // Displaying Total number of records Creating X of X of About X records.
  48:         strSummary.Append("</b> of About <b>");
  49:         strSummary.Append(numberOfRecords.ToString());
  50:         strSummary.Append("</b>Records</br>");
  51:  
  52:         
  53:         litPagingSummary.Text =  strSummary.ToString();
  54:  
  55:  
  56:         //Variable declaration 
  57:         //these variables will used to calculate page number display
  58:         int pageShowLimitStart = 1;
  59:         int pageShowLimitEnd = 1;
  60:  
  61:  
  62:  
  63:         // Just to check, either there is enough pages to implement page number display logic.
  64:         if (pageDispCount > numberOfPages)
  65:         {
  66:             pageShowLimitEnd = numberOfPages; // Setting the end limit to the number of pages. Means show all page numbers
  67:         }
  68:         else
  69:         {
  70:             if (currentPage > 4) // If page index is more then 4 then need to less the page numbers from start and show more on end.
  71:             {
  72:                 //Calculating end limit to show more page numbers
  73:                 pageShowLimitEnd = currentPage + (int)(Math.Floor((decimal)pageDispCount / 2));
  74:                 //Calculating Start limit to hide previous page numbers
  75:                 pageShowLimitStart = currentPage - (int)(Math.Floor((decimal)pageDispCount / 2));
  76:             }
  77:             else
  78:             {
  79:                 //Simply Displaying the 10 pages. no need to remove / add page numbers
  80:                 pageShowLimitEnd = pageDispCount;
  81:             }
  82:         }
  83:  
  84:         // Since the pageDispCount can be changed and limit calculation can cause < 0 values 
  85:         // Simply, set the limit start value to 1 if it is less
  86:         if (pageShowLimitStart < 1)
  87:             pageShowLimitStart = 1;
  88:  
  89:  
  90:         //Dynamic creation of link buttons
  91:  
  92:         // First Link button to display with paging
  93:         LinkButton objLbFirst = new LinkButton();
  94:         objLbFirst.Click += new EventHandler(objLb_Click);
  95:         objLbFirst.Text = "First";
  96:         objLbFirst.ID = "lb_FirstPage";
  97:         objLbFirst.CommandName = "pgChange";
  98:         objLbFirst.EnableViewState = true;
  99:         objLbFirst.CommandArgument = "1";
 100:  
 101:         //Previous Link button to display with paging
 102:         LinkButton objLbPrevious = new LinkButton();
 103:         objLbPrevious.Click += new EventHandler(objLb_Click);
 104:         objLbPrevious.Text = "Previous";
 105:         objLbPrevious.ID = "lb_PreviousPage";
 106:         objLbPrevious.CommandName = "pgChange";
 107:         objLbPrevious.EnableViewState = true;
 108:         objLbPrevious.CommandArgument = currentPage.ToString();
 109:  
 110:  
 111:         //of course if the page is the 1st page, then there is no need of First or Previous
 112:         if (currentPage == 0)
 113:         {
 114:             objLbFirst.Enabled = false;
 115:             objLbPrevious.Enabled = false;
 116:         }
 117:         else
 118:         {
 119:             objLbFirst.Enabled = true;
 120:             objLbPrevious.Enabled = true;
 121:         }
 122:  
 123:  
 124:         //Adding control in a place holder
 125:         plcPaging.Controls.Add(objLbFirst);
 126:         plcPaging.Controls.Add(new LiteralControl("&nbsp; | &nbsp;")); // Just to give some space 
 127:         plcPaging.Controls.Add(objLbPrevious);
 128:         plcPaging.Controls.Add(new LiteralControl("&nbsp; | &nbsp;"));
 129:  
 130:  
 131:         // Creatig page numbers based on the start and end limit variables.
 132:         for (int i = pageShowLimitStart; i <= pageShowLimitEnd; i++)
 133:         {
 134:             if ((Page.FindControl("lb_" + i.ToString()) == null) && i <= numberOfPages)
 135:             {
 136:                 LinkButton objLb = new LinkButton();
 137:                 objLb.Click += new EventHandler(objLb_Click);
 138:                 objLb.Text = i.ToString();
 139:                 objLb.ID = "lb_" + i.ToString();
 140:                 objLb.CommandName = "pgChange";
 141:                 objLb.EnableViewState = true;
 142:                 objLb.CommandArgument = i.ToString();
 143:  
 144:                 if ((currentPage + 1) == i)
 145:                 {
 146:                     objLb.Enabled = false;
 147:                 }
 148:  
 149:  
 150:                 plcPaging.Controls.Add(objLb);
 151:                 plcPaging.Controls.Add(new LiteralControl("&nbsp; | &nbsp;"));
 152:             }
 153:         }
 154:  
 155:         // Last Link button to display with paging
 156:         LinkButton objLbLast = new LinkButton();
 157:         objLbLast.Click += new EventHandler(objLb_Click);
 158:         objLbLast.Text = "Last";
 159:         objLbLast.ID = "lb_LastPage";
 160:         objLbLast.CommandName = "pgChange";
 161:         objLbLast.EnableViewState = true;
 162:         objLbLast.CommandArgument = numberOfPages.ToString();
 163:  
 164:         // Next Link button to display with paging
 165:         LinkButton objLbNext = new LinkButton();
 166:         objLbNext.Click += new EventHandler(objLb_Click);
 167:         objLbNext.Text = "Next";
 168:         objLbNext.ID = "lb_NextPage";
 169:         objLbNext.CommandName = "pgChange";
 170:         objLbNext.EnableViewState = true;
 171:         objLbNext.CommandArgument = (currentPage + 2).ToString();
 172:  
 173:         //of course if the page is the last page, then there is no need of last or next
 174:         if ((currentPage + 1) == numberOfPages)
 175:         {
 176:             objLbLast.Enabled = false;
 177:             objLbNext.Enabled = false;
 178:         }
 179:         else
 180:         {
 181:             objLbLast.Enabled = true;
 182:             objLbNext.Enabled = true;
 183:         }
 184:  
 185:  
 186:         // Adding Control to the place holder
 187:         plcPaging.Controls.Add(objLbNext);
 188:         plcPaging.Controls.Add(new LiteralControl("&nbsp; | &nbsp;"));
 189:         plcPaging.Controls.Add(objLbLast);
 190:         plcPaging.Controls.Add(new LiteralControl("&nbsp; | &nbsp;"));
 191:     }
 192:  
 193: }

Yes, the code is complex that is why I wrote proper comments which will let you understand the stuff easily.

One last thing which is left, is the implementation of dynamically created link button onclick event.

   1: void objLb_Click(object sender, EventArgs e)
   2: {
   3:     plcPaging.Controls.Clear();
   4:     LinkButton objlb = (LinkButton)sender;
   5:     GridView1.PageIndex = (int.Parse(objlb.CommandArgument.ToString()) - 1);
   6:     
   7:     managePaging(dt);
   8: }

 

There it is, we have now completed Custom Paging in Grid View. If you want to download the source code, here is the VS 2008 Solution.

Modification:

I have been receiving emails regarding the issues of this post. Especially with the initial five page numbers. I have modified this post to fix the bug it had. Please feel free to point further issues. Also, the download links are also modified.

Datatable to JSON

8 Comments | May 16, 2009

In this post I will explain you, how can we serialize Datatable to JSON. So that, it can easily pass to JavaScript to get the AJAX done.

First of all fill a Datatable with some results.

DataTable dt = new DataTable();
 
SqlConnection objSqlCon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["AdventureWorksConnectionString"].ToString());
objSqlCon.Open();
 
SqlDataAdapter objSqlDa = new SqlDataAdapter("select * from Production.Product", objSqlCon);
 
objSqlDa.Fill(dt);

Now create a String Builder object that will contain the JSON text and JavascriptSerializer which will serialize the output in JSON.

StringBuilder objSb = new StringBuilder();
JavaScriptSerializer objSer = new JavaScriptSerializer();

Now here we are going to iterate each row and column of data table and put all of them in Dictionary

Dictionary<string, object> resultMain = new Dictionary<string, object>();
int index = 0;
 
foreach (DataRow dr in dt.Rows)
{
    Dictionary<string, object> result = new Dictionary<string, object>();
 
    foreach (DataColumn dc in dt.Columns)
    {
        result.Add(dc.ColumnName, dr[dc].ToString());
    }
    resultMain.Add(index.ToString(), result);
    index++;
}

Notice that, I have created a new dictionary object for every row and finally put all of the dictionaries in Another dictionary I.E. resultMain.

In the end, I have simply Serialize the resultMain Dictionary to render JSON.

A complete post of utilizing Datatable  in JavaScript through AJAX is in the process, I will post that soon.

Authenticated File Access using HTTP Handler.

One Comment | May 08, 2009

In this post I will explain you how authenticate the request directly coming to access a file that is downloadable. some thing like *.pdf or *.zip.

Mostly, people make it working by creating an *.aspx page and then write binary of that file in Response.WriteFile. So, user will have no idea where the file is coming from. now this is the fair approach but what if somebody, somehow know the path of downloadable files.

So, to stop the un authenticated access to our files, we will first create a session enable HTTP handler.

public class MyHttpHandler : IHttpHandler, IReadOnlySessionState
{
 
    public void ProcessRequest(HttpContext context)
    {
        if (context.Session["userId"] == null)
        // I am using a session variable you can also use context.User.Identity.IsAuthenticated
        {
            context.Response.Redirect("/login.aspx?retUrl=" + context.Request.RawUrl);
            //Redirecting to the login page ... alternatively you can also set context.Response.StatusCode 
        }
    }
 
    public bool IsReusable
    {
 
        get { return false; }
    }
}

Now, once we have created that. Let me register my newly creater handler for *.zip and *.pdf files in web.config.

 

<httpHandlers>
  <add verb="*" path="*.zip" type="LearningApp.MyHttpHandler, LearningApp"/>
  <add verb="*" path="*.pdf" type="LearningApp.MyHttpHandler, LearningApp"/>
</httpHandlers>

That’s it. If you want more file types to be authenticated add more verbs in handler section of HttpHandler.

Don’t try to put *.* : That can create some serious problem because then each of your *.aspx, *asmx and all your logic stuff will need authentication.

Disable Special Keys in Win App C#

45 Comments | Apr 26, 2009

Today, when I was planning to write an article on Grid View. I got a message from a very good friend of mine who is asking to disable the special keys(Windows Keys) in his application. When I start researching on it, I was thinking that it can be done using e.KeyChar but unfortunately, it is not showing any information about windows keys.

So in this post I will explain you, how can we disable the special keys (in our case windows keys) in C# Application.

1. Crete a c# windows application project
2. On the code behind of your default form add the following references

   1: using System.Diagnostics;
   2: using System.Runtime.InteropServices;

3. Now before the constructor of your form place the following code.

   1: // Structure contain information about low-level keyboard input event
   2: [StructLayout(LayoutKind.Sequential)]
   3: private struct KBDLLHOOKSTRUCT
   4: {
   5:     public Keys key;
   6:     public int scanCode;
   7:     public int flags;
   8:     public int time;
   9:     public IntPtr extra;
  10: }
  11:  
  12: //System level functions to be used for hook and unhook keyboard input
  13: private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
  14: [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  15: private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);
  16: [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  17: private static extern bool UnhookWindowsHookEx(IntPtr hook);
  18: [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  19: private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp);
  20: [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  21: private static extern IntPtr GetModuleHandle(string name);
  22: [DllImport("user32.dll", CharSet = CharSet.Auto)]
  23: private static extern short GetAsyncKeyState(Keys key);
  24:  
  25:  
  26: //Declaring Global objects
  27: private IntPtr ptrHook;
  28: private LowLevelKeyboardProc objKeyboardProcess; 

4. Now add the following code on your constructor.

   1: public Form1()
   2: {
   3:     ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule; //Get Current Module
   4:     objKeyboardProcess = new LowLevelKeyboardProc(captureKey); //Assign callback function each time keyboard process
   5:     ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0); //Setting Hook of Keyboard Process for current module
   6:  
   7:  
   8:     InitializeComponent();
   9: }

5. Now Implement the callback function

   1: private IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
   2: {
   3:     if (nCode >= 0)
   4:     {
   5:         KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
   6:  
   7:         if (objKeyInfo.key == Keys.RWin || objKeyInfo.key == Keys.LWin) // Disabling Windows keys
   8:         {
   9:             return (IntPtr)1;
  10:         }
  11:     }
  12:     return CallNextHookEx(ptrHook, nCode, wp, lp);
  13: }

6. Now go to your designer class and replace your dispose method.

   1: /// <summary>
   2: /// Clean up any resources being used.
   3: /// </summary>
   4: /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
   5: protected override void Dispose(bool disposing)
   6: {
   7:     if (disposing && (components != null))
   8:     {
   9:  
  10:         components.Dispose();
  11:     }
  12:     if (ptrHook != IntPtr.Zero)
  13:     {
  14:         UnhookWindowsHookEx(ptrHook);
  15:         ptrHook = IntPtr.Zero;
  16:     }
  17:     base.Dispose(disposing);
  18: }

So, in this way we can stop the windows key operation till your application is running.You can find the VS 2008 Source code here.