ThreadAbortException

December 2005 Entries

"Unable to start debugging on the web server. You do not have permission to debug the application. The URL for this project is in the Internet zone."

You may receive the error "Error while trying to run project: Unable to start debugging on the web server. You do not have permission to debug the application. The URL for this project is in the Internet zone. Click Help for more information."

This is one of the various errors that appear when you are debugging and may haunt you until you do the following fix:-

1. In the Internet Explorer, "Tools" Menu, select "Internet Options".

2. Switch to "Security" Tab.

3. Click on "Internet" (The Globe Icon. Its actually the default selected).

4. Click on "Custom Level" in the bottom.

5. Scroll down to find the "User Authentication" section.

6. Select "Automatic logon with current username and password".

7. Click "Ok" twice to exit.

This should solve the issue.

Please note that this resolution is specific only if you get the exact error message as mentioned in the beginning of this article. There are various reasons you get the "Unable to start debugging on the webserver". For a complete list of solutions, please check http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vsdebug.asp

Cheers and Happy Programming !!!

ASP.NET DataGrid - Custom Paging using the Cache Object - Part II

This article is in continuation with the previous article on implementing Custom Paging for ASP.NET DataGrid using the Cache object.

In case you have missed out the previous article, please check Part I

Just to recall, we declared a DataGrid with AllowPaging="true" and set the PagerStyle-Visible="false". Also, we declared a Panel with LinkButtons for First, Previous, Next and Last links for Paging and set a Command event for the link buttons "NavigationLink_Click()".

We will examine the code for implementing paging.

Global Variables used for Paging

private int TotalPages;
private int TotalRecords;
private int CurrentPage;
private int PageSize;


Code for binding the Data to the DataGrid

private void BindData()
{
SqlConnection objCon = new SqlConnection("your connection string goes here");
SqlCommand objCmd = new SqlCommand("select * from customers", objCon);
DataSet dsNew = new DataSet();
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = objCmd;
da.Fill(ds);
Cache["AllRecords"] = ds;
dsNew = (DataSet)Cache["AllRecords"];
ViewState["TotalRecords"] = dsNew.Tables[0].Rows.Count;
DataGrid1.CurrentPageIndex = 0;
DataGrid1.DataSource = dsNew;
DataGrid1.DataBind();
TotalRecords = (int)ViewState["TotalRecords"];
ViewState["TotalPages"] = DataGrid1.PageCount;
ViewState["CurrentPage"] = 0;
PreviousPage.Enabled = false;
NextPage.Enabled = true;
FirstPage.Enabled = false;
LastPage.Enabled = true;
if(TotalRecords == 0)
{
DataGrid1.Visible = false;
Panel1.Visible = false;
}
else if(TotalRecords <= DataGrid1.PageSize) { DataGrid1.Visible = true; Panel1.Visible = true; lblPageDetails.Text = "1 - "+ TotalRecords.ToString() + " of " + TotalRecords.ToString(); NextPage.Enabled = false; LastPage.Enabled = false; } else { DataGrid1.Visible = true; Panel1.Visible = true; lblPageDetails.Text = "1 - "+ DataGrid1.PageSize.ToString() + " of " + TotalRecords.ToString(); } }


Code for the Pager link "NavigationLink_Click()"


protected void NavigationLink_Click (Object sender, CommandEventArgs e)
{
int RecordCount;
DataSet dSet = null;
dSet = (DataSet)Cache["AllRecords"];
PageSize = DataGrid1.PageSize;
switch ( e.CommandName )
{
case "First":
ViewState["CurrentPage"] = 0;
DataGrid1.CurrentPageIndex = 0;
DataGrid1.DataSource = dSet;
DataGrid1.DataBind();
PreviousPage.Enabled = false;
NextPage.Enabled = true;
FirstPage.Enabled = false;
LastPage.Enabled = true;
TotalRecords = (int)ViewState["TotalRecords"];
lblPageDetails.Text = "1 - "+ PageSize.ToString() + " of " + TotalRecords.ToString();
break;
case "Last":
TotalPages = (int) ViewState["TotalPages"] ;
ViewState["CurrentPage"] = TotalPages - 1;
DataGrid1.CurrentPageIndex = TotalPages - 1 ; //since page number starts from 0
DataGrid1.DataSource = dSet;
DataGrid1.DataBind();
NextPage.Enabled = false;
PreviousPage.Enabled = true;
LastPage.Enabled = false;
FirstPage.Enabled = true;
RecordCount = (TotalPages - 1)* PageSize;
TotalRecords = (int)ViewState["TotalRecords"];
lblPageDetails.Text = (RecordCount+1).ToString()+" - "+ TotalRecords.ToString() + " of " + TotalRecords.ToString();
break;
case "Next":
CurrentPage =(int) ViewState["CurrentPage"];
CurrentPage = CurrentPage + 1;
ViewState["CurrentPage"] = CurrentPage;
DataGrid1.CurrentPageIndex = CurrentPage;
DataGrid1.DataSource = dSet;
DataGrid1.DataBind();
RecordCount = CurrentPage * PageSize;
TotalRecords = (int)ViewState["TotalRecords"];
if(CurrentPage == DataGrid1.PageCount-1)
{
NextPage.Enabled = false;
PreviousPage.Enabled = true;
LastPage.Enabled = false;
FirstPage.Enabled = true;
lblPageDetails.Text = (RecordCount+1).ToString()+" - "+ TotalRecords.ToString() + " of " + TotalRecords.ToString();
}
else
{
NextPage.Enabled = true;
PreviousPage.Enabled = true;
LastPage.Enabled = true;
FirstPage.Enabled = true;
lblPageDetails.Text = (RecordCount+1).ToString()+" - "+ (RecordCount+PageSize).ToString() + " of " + TotalRecords.ToString();
}
break;
case "Prev":
CurrentPage =(int) ViewState["CurrentPage"];
CurrentPage = CurrentPage - 1;
ViewState["CurrentPage"] = CurrentPage;
DataGrid1.CurrentPageIndex = CurrentPage;
DataGrid1.DataSource = dSet;
DataGrid1.DataBind();
RecordCount = CurrentPage * PageSize;
TotalRecords = (int)ViewState["TotalRecords"];
if(CurrentPage == 0)
{
PreviousPage.Enabled = false;
NextPage.Enabled = true;
FirstPage.Enabled = false;
LastPage.Enabled = true;
lblPageDetails.Text = "1 - "+ PageSize.ToString() + " of " +TotalRecords.ToString();
}
else
{
NextPage.Enabled = true;
PreviousPage.Enabled = true;
LastPage.Enabled = true;
FirstPage.Enabled = true;
lblPageDetails.Text = (RecordCount+1).ToString()+" - "+ (RecordCount+PageSize).ToString() + " of " + TotalRecords.ToString();
}
break;
}
}


Calling the DataGrid Binding method in the Page_Load Event


private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
BindData();
}
}


We will examine the code step-by-step:-

1. Declaring Global variables
We have declared certain global variables such that they are useful across the methods.

2. Binding the Data to the DataGrid
The first seven lines of code must be a familiar one for whoever creates a connection object, dataadapter and a dataset. We have used a sample "Customer" Table for this sample.

What is changed is that, we dont directly bind the DataGrid with the DataSet. Instead, we store the DataSet into the Cache object. The reason is that, the Cache object is going to store all the records that we retrieve from the Database in one shot and then remain useful in moving next,previous link buttons in the paging.

We then typecast the ViewState data into a new DataSet which is used to bind the DataGrid.

We then store the total number of records into ViewState. This is useful in showing the total records in the Pager Panel.

Then, we assign the current page index to 0 so that the DataGrid's first page is shown when the control generates for the first time.

The DataGrid is then bound to the New DataSet.

Then, the TotalPages the DataGrid requies to show all the records is set to ViewState and also the CurrentPageIndex is set to ViewState.

We then do various checkings to show, enable and disable the pager links based on the number of records etc., which is self-explanatory.

3. The Navigation_Link Method Code
The first thing we do in this method is to get the items from the Cache. Remember, this event is going to fire for any of the pager links clicked.

We then do a switch based on the CommandName argument that is passed and do relevant calculations to show respective count on the Pager links.

4. Page_Load Event
In the Page_Load event, the DataGrid binding method is called within the PostBack Condition check.

As you are aware, there are various calculations done based on the Link clicked such that it shows, the relevant items in the format "1-5 of 10", "6-10 of 10" etc., and also there is a First and Last link which can take you to the first page and last page of the records.

This also improves the performance since the bulk of records is stored in the Cache object and thereafter, there is no Database call unlike the traditional built-in paging functionality. This also accounts to quicker response.

You can also notice that the format of the Pager (text) is now in our control we can configure the Text as per our requirement unlike the limited options in the built-in paging mechanism.

This concludes the 2 part article series on implementing Custom Paging using the Cache object for ASP.NET DataGrid.

Cheers and Happy Programming !!!

ASP.NET DataGrid - Custom Paging using the Cache Object - Part I

ASP.NET DataGrid is one of the coolest controls (well its quite late now to remark, but I cannot stop from starting like this) that has been used by almost everyone who does coding in ASP.NET. Though there are other controls like Repeater, DataList, the popularity DataGrid has got among developers is enviable.

One of the primary concerns when using DataGrid web server control is the Paging functionality. In real world scenario you will always end up with huge data that cannot be showed once for all in a single page. The DataGrid needs to implement paging by which you show only limited number of records and provide navigation links for seeing the next set of records, previous records, etc., However, there are certain limitations in using the built-in paging functionality. They are


1. The Pager Style mode is limited to "Next Previous" or Numeric "1,2,.." etc., whereas in certain places we would like to have custom text which says 1-5 of 10 records, First page, Last Page in addition to the previous, next page etc.,

2. Everytime, the page link is clicked, the entire set of records is going to be retreived though only the actual number of items will be shown. Assume you have 10,000 records. Everytime the 10,000 records will be retrieved when you navigate between the pager links. This can be heavy over the network.

3. You need to bind the DataGrid everytime on the PageIndexChanged event.

While the above are certain performance overheads, still, for basic paging requirement, the built-in paging mechanism is more than enough. However, if you care for performance and want to implement your own way of efficient paging, DataGrid still offers you the way to do it. It welcomes you to implement custom paging for which you have to write the code. In built-in paging, it does the plumbing work internally whereas, in custom paging, you need to dirty your hands in code.

There are several ways in which you can implement custom paging. There have been wealth of articles on the same ever since ASP.NET 1.0 got released and I am sure there must be some articles already on the topic I am writing now. But this is just another approach to help people who want to implement custom paging and expand the possibilities with DataGrid.

Having said that, lets start our first step in implementing Custom Paging.

1. Declare the DataGrid with AllowPaging="true"

&lt;ASP:DATAGRID id="DataGrid1" Runat="server" AutoGenerateColumns="true" PageSize="5" AllowPaging="true" PagerStyle-Visible="False">
&lt;/ASP:DATAGRID>


If you notice in the above declaration, we have set AllowPaging="true" which is normal in any case where you implement paging. Secondly, we have set the PagerStyle-Visible="false" to ensure that DataGrid doesnt show up its default pager style "< >" since we have set the allowpaging to true.

2. The next step is declaring a Panel which contains the Pager links

&lt;asp:Panel id="Panel1" Runat="server" Visible="False">

&lt;TR>

&lt;TD id="LinkButtons" colSpan="2" runat="server">

&lt;ASP:LINKBUTTON id="FirstPage" Runat="server" text="First" OnCommand="NavigationLink_Click" CommandName="First">&lt;/ASP:LINKBUTTON>

&lt;ASP:LINKBUTTON id="PreviousPage" Runat="server" text="Previous" OnCommand="NavigationLink_Click" CommandName="Prev">&lt;/ASP:LINKBUTTON>

&lt;ASP:LABEL id="lblPageDetails" runat="Server" >&lt;/ASP:LABEL>

&lt;ASP:LINKBUTTON id="NextPage" Runat="server" text="Next" OnCommand="NavigationLink_Click" CommandName="Next">&lt;/ASP:LINKBUTTON>

&lt;ASP:LINKBUTTON id="LastPage" Runat="server" text="Last" OnCommand="NavigationLink_Click" CommandName="Last">&lt;/ASP:LINKBUTTON>

&lt;/TD>

&lt;/TR>

&lt;/asp:Panel>

In the above code you can notice that we have 4 linkbuttons one each for "First, Last, Previous, Next". All of them link to a single method "NavigationLink_Click", but pass different CommandNames such as "First", "Previous", "Next", "Last" to specify which button is clicked.

Also, we have a panel covering these link buttons. We will explore on how to implement the NavigationLink_Click method in the next part of this article.

Cheers and Happy Programming !!!

A better way of working with IE Webcontrols - Part II

I have written an article on the same lines some time back and thought of updating the same with a newer approach which came to my mind while implementing Tabstrip control in ASP.NET 1.1.

Fortunately, this has been very well replaced in ASP.NET 2.0 by using the MultiView - View Controls which provide an excellent mechanism for Tabbed Viewing or Partial Viewing of pages. Check my Recent Article on the same.

Well, now lets get back to ASP.NET 1.1, because I feel its still time for people to move to ASP.NET 2.0 and I am very much aware and used to the Clients who dont really want to jump for new technologies immediately, unless considerable number of implementations are made in the new technologies worldwide.

In ASP.NET 1.1, we dont have built in Tab strip control and we need to rely on the IE Webcontrols or other third party controls. The idea of third party controls is out of focus for this article and hence we would limit it to IE Tabstrip control.

An important point worth mentioning here is, IE Webcontrols are not supported by Microsoft and there is no reliability or scalability guarantee provided by Microsoft about these controls.

Ok, definitely now, I would get into business.

When implementing Tabs and Multipages in IE Tabstrip, we resort to showing different sections upon switching between different tabs.

However, there are certain limitations.

1. The Tab Index Change should happen at the client side and not at the server side. The server side is the default since AutoPostback is set to "true" by default. This causes a fractional ugly UI until the other tab loads.

2. For a single changed event, the whole page is reloading and thereby increasing the load.

3. You cannot have Validator controls across the tabs and happily submit one tab's data.

This happens because though the Tab shows different sections of the page, the validation is done at a Page Level as a whole where it checks the document.all (javascript function currently supported only by IE) or does a Page.IsValid in the case of server side.

So, in case we have a required field validator and a textbox and button in one tab, and a similar set of controls in another tab, no matter where you are, it wont allow you to submit the form unless all the validators, across the tabs are satisfied. This can partially be painful because sometimes you will keep clicking and wondering why the h*ll it is not submitting, when, actually if you switch to the other tab, it would be prettily showing the dreaded Red error messsage.

4. The controls you declare within the Tabstrip will not be automatically delcared in the codebehind and you have to manually declare them or do a FindControl everytime you want to access the properties.

5. In case you resort to Autopostback="false" scenario you have to explicitly load all the contents of the tabs and fetch any look up data being populated for all the tabs at one shot in the page_load, which may be a little slow in the beginning.

Well, though I keep complaining of the above points often, Tabstrip is still the only, trusted way of implementing Tab feature that I have seen across many projects.

Solution (not the best but definitely solves the purpose)

We can have the contents of each of the Tab in separate pages and provide an iframe link to those pages from the MultiPage defined for the Tabstrip.

Syntax

<IEWC:TABSTRIP id="Tabstrip1" runat="server" Visible="true" SelectedIndex="0" AutoPostBack="false" TargetID="MultiPage1">

<IEWC:TAB Text="Cricket"></IEWC:TAB>
<IEWC:TAB Text="Business"></IEWC:TAB>
<IEWC:TAB Text="Weather"></IEWC:TAB>
<IEWC:TAB Text="Stock"></IEWC:TAB>
<IEWC:TAB Text="Entertainment"></IEWC:TAB>
<IEWC:TAB Text="Health"></IEWC:TAB>

</IEWC:TABSTRIP>


<IEWC:MULTIPAGE id="MultiPage1" runat="server" Visible="true" BorderWidth="0px" Width="100%">

<IEWC:PAGEVIEW id="Cricket"> <iframe id="Iframe1" runat="server" src="Cricket.aspx" frameborder="0" width="100%" height="700px" scrolling="no"></iframe></IEWC:PAGEVIEW>

<IEWC:PAGEVIEW id="Business"> <iframe id="Iframe2" runat="server" src="Business.aspx" frameborder="0" width="100%" height="700px" scrolling="no"></iframe></IEWC:PAGEVIEW>

<IEWC:PAGEVIEW id="Weather"> <iframe id="Iframe3" runat="server" src="Weather.aspx" frameborder="0" width="100%" height="700px" scrolling="no"></iframe></IEWC:PAGEVIEW>

<IEWC:PAGEVIEW id="Stock"> <iframe id="Iframe4" runat="server" src="Stock.aspx" frameborder="0" width="100%" height="700px" scrolling="no"></iframe>
</IEWC:PAGEVIEW>

<IEWC:PAGEVIEW id="Entertainment"> <iframe id="Iframe4" runat="server" src="Entertainment.aspx" frameborder="0" width="100%" height="700px" scrolling="no"></iframe></IEWC:PAGEVIEW>

<IEWC:PAGEVIEW id="Health"> <iframe id="Iframe5" runat="server" src="Health.aspx" frameborder="0" width="100%" height="700px" scrolling="no"></iframe></IEWC:PAGEVIEW>

</IEWC:MULTIPAGE>

Thats it all about. If you see the above code, you can make out that I have mentioned different pages like Cricket.aspx, Weather.aspx etc., in the src attribute of the Iframes.

All of these pages are individual pages which can be developed independently and then linked to the tabstrip through the iframes.

The advantages of this approach

Pages can be developed independently, so debugging, control declaration, etc., will be simple.

Tomorrow, if we would like to remove one of the Tabs, its as simple as removing the <IEWC:Tab> and the respective MultiPage without worrying about the code corresponding to that Tab.

The Main page where we have our Tabstrip and Multipage becomes simple in terms of control tree, methods, debugging, maintenance etc.,

ASP.NET Validator Controls can exist happily across the tabs as each page can have its own Validator control and it doesnt stop the page corresponding to another tab's submission. This is because, the validators check at Page level and since all of them are individual pages, they dont stop the other page.

For every postback event raised within the Pages, only the corresponding page is loaded and not the entire main page with the Tab controls and they remain stable.

In case of Team Development, people can work independently on different pages and not worry about integration.

The true potential of this approach can only be recognized where you have a lot of Tabs and Multipages required in a single page.

Constraints
The pages may take a little time to load initially since the main page has to load different pages.

Communicating between the Tabbed pages become tricky.

Iframe is not the best recommended though it doesnt have any significant defect (Support for down level browsers might just be the only concern).

So, that concludes this article. Having said that, as already discussed, most of these issues have been take care in ASP.NET 2.0 and its just for the sake of ASP.NET 1.X Version where you need to rely on the IE Webcontrols.

Read
Part I.

Cheers and Happy Programming !!!

ASP.NET 2.0 MultiView Control - No more TabStrip / Panel Show-Hide

One of the most ignored or rather not talked about control in ASP.NET 2.0 (no more code name "whidbey") is the MultiView Control.

How many times we have wanted a scenario where we need to show only certain portions of a section and show the other based on a click event and allow users to toggle between the two. The solution for this in ASP.NET 1.X versions is to either go for a Tabstrip control or have a Button, Image Button etc., and have Panels which you can show and Hide.

Neither of the two were very efficient due to the following reasons.

Tabstrip
It wasnt a 100% solution for Tabbed Pages. It was a wonderful Web Control
but still had its own limitations.

Validators cannot exist happily across tabs where submission of neither of them will happen unless all the validators are satisfied.

You have to explicitly declare the Controls in the Code Behind unlike the traditional way, where you drag and drop a control and automatically, it adds the control declaration in the codebehind.

Microsoft does not support the IE Webcontrols and therefore there is no proper documentation / support for them and nor there is any reliability of performance.

Panels
You have to explicitly show a Panel and hide the other panels. Say you have 3 panels.

Then, you need to set Panel1.Visible = true and others Panel2.visible = false & Panel3.visible = false explicitly. You have to repeat these steps everytime you want to change between the panels.


Maintaining the Code becomes too tough if more panels get added.

ASP.NET 2.0 Provies a wonderful solution by means of MultiView Control. The MultiView Control combined with the View Control can provide different UI on different scenarios as and when required.

Herebelow, is the syntax for the same

<asp:MultiView ID="MultiView1" runat="server" >
<asp:View ID="View1" runat="server">
This is one section where you can have a set of controls / contents.
</asp:View>
<asp:View ID="View2" runat="server">
This is another section where you can have a different set of controls / contents.
</asp:View>
</asp:MultiView>

Now, to show the different tabs based on different events, we just need to set the following code:-

protected void Button1_Click(object sender, EventArgs e)
{
MultiView1.SetActiveView(View1);
}
protected void Button2_Click(object sender, EventArgs e)
{
MultiView1.SetActiveView(View2);
}

Thats all I need to show the different parts of the UI based on scenario. This is really useful in cases of Lengthy DataForms, collecting different information from different control types based on user's input.

The MultiView control for sure is going to change the way we have been coding heavily using Panels.

Cheers and Happy Programming !!!

MVP RoundTable Snaps

 

Somasegar, Corp. Vice President, Developer Division, Microsoft, keenly listening to one of our MVPs' query



 

 

 

 

 

 

 






                                                                               Myself, Sudhakar (Microsoft) and Anjana (SQL Server MVP)




Keenly into a Serious Discussion




My Fellow MVP 'Anil', Community Member Sasi, Arun - XML WebServices MVP, and Community Member Venkata Murthy

Thanks to Rayappa, MVP for sharing the snaps !!!

MVP Round Table with Somasegar, Corp. Vice President, Microsoft Developer Division, Microsoft


Last week I had a chance to meet Somasegar (fondly called as "Soma"), Corp. Vice President, Developer Division, Microsoft.

Soma heads the Developer Division and had been heading the release of several exciting products including the recently launched Visual Studio 2005.

What I admire in him is his excitement and openness in discussing issues with MVPs. Indeed, it was a round table with MVPs in Microsoft Hyderabad Campus, Gachibowli.

Along with him, were
Paramesh, Sriram and quite a few Microsoft Employees.

There were discussions on the recent Visual Studio 2005 release and other MVP initiatives, the Community Launch and couple of other things.

Soma actively writes at his
Weblog and surprisingly, finds time to respond to the comments posted. His blog is one of the heavily commented ones and wonder how he gets the time and patience to reply for all queries.

The round table concluded with a High Tea !!! I have posted some of the snaps in this post and the following post.

Cheers !!!