Wednesday 27 January 2010

SQL Server 2008 Express Edition: Installing on a Domain Controller

If you try to install SQL Server 2008 Express Edition on a machine which acts as a Domain Controller using the packaged Web Platform installer, it will fail and you will see an error in the installation log.

This is because it will attempt to install using Network Service as the default account, which is not allowed on a domain controller. If you look in the logs, you will see an error such as:

Network Service or Local Service account is not permitted for the SQL Server service on a domain controller

If you experience this issue, you need to do a customised installation. This blog post highlights the issues involved and has links to the appropriate installlers to get you up and running.

NOTE: Microsoft do not recommend installing SQL Server on a Domain Controller, so you need to think about your performance requirements and the potential issues such an installation may cause.

ASP.NET Error: System.Web.HttpException: Maximum request length exceeded

On several applications I have developed, the users need to be able to upload binary documents (discussed in other posts).

After a while, I kept getting the error:

System.Web.HttpException: Maximum request length exceeded

Easy fix. The problem is that by default, the maximum request size is 4mb. So when a user tries to upload a file which is larger than that, an exception occurs. The resolution is to increase the maximum size of the request, so add the attribute below to web.config (you can use a maxRequestLength up to "2097151" (2 GB) for the .NET Framework 2.0):

<configuration>

<system.web>
<httpruntime maxrequestlength="10240">


This is also explained quite nicely but without much background in a Knowledge Base article on the Microsoft Support site.

Remember, if you are imposing a maximum file size for upload you should notify the user of this restriction and handle any attempt to upload a larger file, or they might see errors again.

Tuesday 19 January 2010

ASP.NET: Maintain Browser Scroll Position After Postback

In many applications, the screen can have many controls which cause postback events. And if the screen has any vertical scrollbars, users will typically object if the scroll position is not maintained (fair enough) and they have to scroll back down to find where they were and also to spot which changes the postback caused.

I had been mucking about with JavaScript solutions to this, which actually did work. But the easiest way is to follow one of these methods:

1. Set it programmatically

Page.MaintainScrollPositionOnPostBack = true;

2. In the page declaration:

<%@ Page MaintainScrollPositionOnPostback="true" %>

3. Or as a global setting in the web.config file, modify the pages section to add the property:

<pages maintainScrollPositionOnPostBack="true" >

Done!

Friday 15 January 2010

ASP.NET Error: Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control

If you are using controls which are bound in a cascading parent-child relationship, you might see the error:

Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control

I kept getting this, but then after reading this tutorial, I realised that I had been sorting a GridView in my Page_Load event, regardless of whether the page request was a PostBack or not.

This was causing the databinding events to get borked up, and hence the error. So I added a simple IF statement around the sorting command to only do so if the page request was not a postback. Et Voila! Success!

Lesson: If you see the above error, check that you are not attempting to bind to a dependent dropdown list a value from its container’s data context when the latter was not bound to the container.

In English: check where in the page lifecycle your binding/sorting takes place otherwise you will unhook your controls from their binding and break your code.

Thursday 7 January 2010

ASP.NET: Search GridView and Programatically Select Row

On the main page of one of my apps, I have a large GridView containing a lot of rows. They're paged, but the number of pages can run to ten or twenty.

So the users needed a quick way to locate a specific item within the GridView rather than having to manually search it each time. I added an AJAX Combo Box to the page, which displays an autocomplete selector for the items which also display in the GridView. On it's SelectedIndexChanged event, I needed it to automatically select the corresponding row on the GridView.

I searched the net to find the best way to do it, but there were several problems with the solutions people had found. There's no point dwelling on those at length, but the main issue was that if you loop through a GridView's DataKeys, you only loop through the DataKeys for that specific page, not the pages which are not currently displayed. The suggested code looked like this:

For n As Integer = 0 To myGridView.DataKeys.Count - 1
If myGridView.DataKeys(n).Value = myKeyObj Then
myGridView.SelectedIndex = n
End If
Next


That's fine if you only have one page on your GridView, but is not a lot of use when you have enabled paging and you have a requirement to search the entire data set.

A helpful person on the ASP.NET forums posted some code which allows you to loop through the pages of the GridView, so I modified it slightly and ended up with the following:

Dim i As Integer, DataSetIndex As Integer
Dim SelectedRowIndex As Integer
Dim dv As DataView = ObjectDataSourceClients.Select
Dim dt As DataTable = dv.ToTable

For i = 0 To dt.Rows.Count - 1
If dt.Rows(i)("Client_ID") = ComboBoxClientSearch.SelectedValue Then
DataSetIndex = i
Exit For
End If
Next

GridViewAllClients.PageIndex = DataSetIndex \ GridViewAllClients.PageSize
SelectedRowIndex = DataSetIndex - (GridViewAllClients.PageSize * GridViewAllClients.PageIndex)
GridViewAllClients.SelectedIndex = SelectedRowIndex

GridViewAllClients.DataBind()

Originally, as per the poster's code I had tried to just access the DataSet directly by using:

Dim ds As DataSet = GridViewAllClients.DataSource

This didn't work and I kept getting null reference exceptions because the GridView's DataSource is not persisted after a PostBack by the ViewState.

So in this case, I had to access the ObjectDataSource that the GridView was using, fire its Select method and convert the result to a DataTable which I could search.

That worked nicely, so I posted my findings back to the forum.

NOTE: The above code depends on the GridView and its DataSource being sorted the same way. So if you programatically sort your GridView after it's bound and then attempt to search using the above method, it won't work because the rows in the GridView and its DataSource will be out of sync.