Raj Kaimal

Silverlight 4 = death of WPF?

I was really blown away by the new features in Silverlight 4 demoed at the PDC keynote yesterday. The list is too long to include here so go here instead.

If we have all these features in Silverlight, then why even bother with WPF? This will be one less technology we will have to learn about. The VS 2010 editor should simply have been written in Silverlight :-)

I am anxiously awaiting the release of the source codes for the demos.

Posted by rajbk | 3 comment(s)
Filed under: , ,

Bing vs Google maps – closing the left panel

I have completed a search for a place on both Google and Bing and now wish to close the left panel. Which one is more obvious?

googlemaps bingmaps

In case you are unable to find it, the action to close the left panel in Bing is in the map itself. You can see it at the bottom right (above Blvd). I was still confused after finding it – am I going to close the left panel or am I going to scroll left?

Posted by rajbk | with no comments
Filed under: , ,

VS 2010 Beta 2 Installation instructions

For those of you that have VS 2010 Beta 1 installed.

http://go.microsoft.com/fwlink/?LinkID=166199 

http://go.microsoft.com/fwlink/?LinkID=167718 (addendum)

 

Other observations: 

I was prompted for my VS 2010 Beta 1 media when uninstalling it so have your iso or media ready.

VS 2010 Beta 2 prompted for a OS restart during installation.

 See announcement for more details.

Posted by rajbk | with no comments
Filed under: , ,

XMLSerializer and invalid XML

A user had pasted some text from powerpoint into a textarea in one of our web apps which was eventually serialized into XML. Upon trying to de-serialize the XML, the web server threw the exception below:

System.InvalidOperationException: There is an error in XML document (1, 50). ---> System.Xml.XmlException: '♂', hexadecimal value 0x0B, is an invalid character. Line 1, position 50.

The XML that was about to be de-serialized looked like something this:

<?xml version="1.0" encoding="utf-16"?>
<string>Quick&#xB;Brown
Fox
</string>

The code used to de-serialze the xml is shown below:

public static T DeSerializeObject<T>(string xml)
{
    using (System.IO.StringReader sr = new System.IO.StringReader(xml))
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        return (T)serializer.Deserialize(sr);
    }
}


As seen from the exception above, the de-serializer was complaining about the invalid character - &#xB;.  

The PowerPoint slide that text was being pasted from looked something like this:

ppt
The user had used the Shift-Enter key combination to force a line break between text in a bullet. So “Brown” is started on a new line for the same bullet as “Quick”.

By selecting all the text on the slide and pasting it into a hex editor, we see the standard hex values for carriage return and line feed – 0x0D 0x0A between “Brown” and “Fox”. But we see 0x0B was generated for the new line between “Quick” and “Brown”. 0x0B in ASCII stands for a vertical line tab which is an invalid character in XML. 
ppthex

The code used to serialize the string is shown below:

private static string SerializeObject<T>(T source)
{
    var serializer = new XmlSerializer(typeof(T));
 
    using (var sw = new System.IO.StringWriter())
    using (var writer = new XmlTextWriter(sw))
    {
        serializer.Serialize(writer, source);
        return sw.ToString();
    }
}

The problem with this code is that the XmlTextWriter class which inherits from XmlWriter, does not, on its own, validate each character before serializing it.

The recommended way to serialize is to use the static XmlWriter.Create method. The method has overloads where you specify an XmlWriterSettings class. If you do not specify one, the default values for the XmlWriterSettings class is used. One of the properties of this class is the XmlWriterSettings.CheckCharacters Property which is set to true by default. This property ensures that the XmlWriter instance created by the .Create method will perform character checking. By implementing the .Create* method in our code, we ensure that the serializer will throw an exception if it encounters invalid XML.

We, therefore, can rewrite our serializer class like so:

private static string SerializeObject<T>(T source)
{
    var serializer = new XmlSerializer(typeof(T));
    using (var sw = new System.IO.StringWriter())
    using (var writer = XmlWriter.Create(sw))
    {
        serializer.Serialize(writer, source);
        return sw.ToString();
    }
}

* The writer created in this case is of type System.Xml.XmlWellFormedWriter. It will vary based on the .Create overload used.

Posted by rajbk | 5 comment(s)
Filed under: , , ,

LINQ to SQL Paging Gotcha

Framework Version: 3.5

I ran into an issue with how LINQ to SQL implements the Skip and Take operators which leads to records being repeated or missing when performing custom paging.

I am using the Northwind database. My UI will display the City and ContactName of all Customers five records at a time. The LINQ expression projects to an anonymous type with properties of City and ContactName. We see below the LINQ expression, the SQL generated and the data returned for the first and next 5 records.

First 5 Records (Page 1)   Next 5 Records (Page 2)
LINQ Expression
(from c in Customers
        select new {
            c.City,
            c.ContactName
        }).Skip(0).Take(5)
        LINQ Expression
(from c in Customers
        select new {
            c.City,
            c.ContactName
        }).Skip(5).Take(5)
Generated SQL
SELECT TOP (5) [t0].[City], [t0].[ContactName]
FROM [Customers] AS [t0]
  Generated SQL
DECLARE @p0 Int = 5
DECLARE @p1 Int = 5

SELECT [t1].[City], [t1].[ContactName]
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY [t0].[City], [t0].[ContactName]) AS [ROW_NUMBER], 
    [t0].[City], [t0].[ContactName]
    FROM [Customers] AS [t0]
    ) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
ORDER BY [t1].[ROW_NUMBER]
Result set
City            ContactName
--------------- ------------------------------
Berlin          Maria Anders
México D.F.     Ana Trujillo
México D.F.     Antonio Moreno
London          Thomas Hardy
Luleå           Christina Berglund
  Result set
City            ContactName
--------------- ------------------------------
Barquisimeto    Carlos González
Bergamo         Giovanni Rovelli
Berlin          Maria Anders
Bern            Yang Wang
Boise           Jose Pavarotti

From the result set, we see that Maria Anders is repeated in Page 1 and Page 2!  The same behavior can also be observed with a LinqDataSource as defined below:

<asp:GridView ID="GridView1" runat="server" AllowPaging="True" AutoGenerateColumns="False"
    DataSourceID="LinqDataSource1" PageSize="5">
    <Columns>
        <asp:BoundField DataField="City" HeaderText="City" ReadOnly="True" SortExpression="City" />
        <asp:BoundField DataField="ContactName" HeaderText="ContactName" ReadOnly="True"
            SortExpression="ContactName" />
    </Columns>
</asp:GridView>
<asp:LinqDataSource ID="LinqDataSource1" runat="server" ContextTypeName="DataClassesDataContext"
     Select="new (City, ContactName)" TableName="Customers">
</asp:LinqDataSource>


The reason for this behavior is because the SQL generated for Page 1 does not have an order specified which results in the records being returned in an unknown order

SELECT TOP (5) [t0].[City], [t0].[ContactName]
FROM [Customers] AS [t0]

while for subsequent pages, the SQL generated has an order by clause (required for the ROW_NUMBER() function).

(ORDER BY [t0].[City], [t0].[ContactName]) 

While paging through the result set, this will either result in repeating records or missing records*. 

The best way to work around this issue in framework version 3.5 is to always specify an orderby in the expression before the Take and Skip operators. By doing this, you guarantee that the order used for the first page (with the TOP operator) will be the same as the order used for subsequent pages (using the ROW_NUMBER() OVER ORDER function)

(from c in Customers
 orderby c.ContactName
        select new {
            c.City,
            c.ContactName
        }).Skip(0).Take(5)
SELECT TOP (5) [t0].[City], [t0].[ContactName]
FROM [Customers] AS [t0]
ORDER BY [t0].[ContactName]

LINQ To Entities on the other hand forces you to specify an order by in a scenario like this. If you don’t you get the following error:

The method 'Skip' is only supported for sorted input in LINQ to Entities.
The method 'OrderBy' must be called before the method 'Skip'.

This issue seems to have been fixed in the .NET 4.0 framework where the SELECT TOP statement is no longer generated by LINQ TO SQL for the first page.

(from c in Customers
 orderby c.ContactName
        select new {
            c.City,
            c.ContactName
        }).Skip(0).Take(5)
DECLARE @p0 Int = 0
DECLARE @p1 Int = 5
 
SELECT [t1].[City], [t1].[ContactName]
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ContactName]) AS [ROW_NUMBER], [t0].[City], [t0].[ContactName]
    FROM [Customers] AS [t0]
    ) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
ORDER BY [t1].[ROW_NUMBER]

In addition, if you don’t specify an orderby clause or project your result, LINQ To SQL will use all the properties specified in the entity class in the order by clause and select statement leading to ugly and inefficient code:

(from c in Customers
        select c).Skip(10).Take(5)
SELECT [t1].[CustomerID], [t1].[CompanyName], [t1].[ContactName], [t1].[ContactTitle], [t1].[Address], 
[t1].[City], [t1].[Region], [t1].[PostalCode], [t1].[Country], [t1].[Phone], [t1].[Fax]
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], 
[t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], 
[t0].[Phone], [t0].[Fax]) AS [ROW_NUMBER], [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], 
[t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
    FROM [Customers] AS [t0]
    ) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
ORDER BY [t1].[ROW_NUMBER]



Special thanks to Joseph Albahari for creating LINQPad. 

*  In most cases we get lucky and get the records from SQL based on the PK for the first page (even though as mentioned before, order is not guaranteed) and since our LINQ Expression will most likely have the PK as the first item in the projection it results in the same order for both the first page and subsequent pages. Hence this obscure issue.

Posted by rajbk | 3 comment(s)
Filed under: , ,

Windows 7 Backup

The backup tool that comes with Vista does not allow users to select individual folders for backup. Instead the user is presented with a default list of locations for backup. Because of this limitation, I had to resort to other third party tools to do the job.

vista_backup

With Windows 7, you now have the option of selecting individual folders for backup. Nice!

win7_backup

Posted by rajbk | 1 comment(s)

Windows 7 – Start Bar and Task Bar

I Installed 7 RTM yesterday and I am really  impressed by the speed improvements compared to Windows Vista.

Even though I am still learning the new features, there are a couple of things I have seen that I really like so far.

You can now click on the network icon in the taskbar and easily connect or disconnect to any network you have configured including VPN connections.

vpn_connect

I also like how easy it is to get to your remote desktop connections. You can click on the start/windows icon and get a list of the recent connections made and even pin down your favorites.

 remotedesktop

You can even pin down your favorite programs to the taskbar.

image

You can also easily control which icons appear in the notification area and reduce clutter. For example you can turn off the ASP.net web server notification by clicking on the arrow in the taskbar and selecting customize :

image

notifications

Check out this post for lots more features

Looking awesome so far!

Posted by rajbk | 2 comment(s)

FormView Binding Gotcha

Version: ASP.NET 3.5 SP1

This post describes two gotchas with the FormView control when binding:
1) When performing two way databinding, Null values and Nullables get changed to string.Empty in the FormView.
2) Two way binding is not supported for nested controls.

When performing two way databinding, Null values and Nullables get changed to string.Empty in the FormView.
The way the FormView control handles null values has caused me some grief :-(

Consider a FormView bound to an ObjectDataSource like so:

<asp:FormView ID="FormView1" runat="server" DataSourceID="ObjectDataSource1" DefaultMode="Edit">
<EditItemTemplate>
FirstName:
<asp:TextBox ID="FirstNameTextBox" runat="server" Text='<%# Bind("FirstName") %>' />
<br />
LastName:
<asp:TextBox ID="LastNameTextBox" runat="server" Text='<%# Bind("LastName") %>' />
<br />
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update"
Text="Update" />
</EditItemTemplate>
</asp:FormView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DataObjectTypeName="Employee"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetEmployee" TypeName="EmployeeWrapper"
ConflictDetection="CompareAllValues" UpdateMethod="SetEmployee"></asp:ObjectDataSource>

The Employee object returned by the ObjectDataSource has LastName set to null like so:
[DataObjectMethod(DataObjectMethodType.Select)]
public Employee GetEmployee()
{
return new Employee()
{
FirstName = "Tom",
LastName = null
};
}
 
Click the Update button on the FormView without changing any properties. In the Form ItemUpdating event, we see that both the OldValues and NewValues have the LastName property set to string.Empty.
(OldValue according to FormView)
FirstName : Tom
LastName :

(NewValue according to FormView)
FirstName : Tom
LastName :
On the other hand, if we try the same thing with the DetailsView control, the LastName will still be “null” on update.

This FormView behavior can be problematic when we we need the original object and the modified object to perform an update with conflict detection (see LINQ to SQL example below). Note that ConflictDetection is set to CompareAllValues in the ObjectDataSource.
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" ConflictDetection="CompareAllValues"
DataObjectTypeName="Customer" OldValuesParameterFormatString="original_{0}" SelectMethod="GetCustomer"
TypeName="CustomerWrapper" UpdateMethod="SetCustomer">
<UpdateParameters>
<asp:Parameter Name="customer" Type="Object" />
<asp:Parameter Name="original_customer" Type="Object" />
</UpdateParameters>
</asp:ObjectDataSource>

public void SetCustomer(Customer customer, Customer original_customer)
{
DataClassesDataContext context = new DataClassesDataContext();
context.Customers.Attach(customer, original_customer);
context.SubmitChanges();
}

In brief, LINQ to SQL compares the original value and new value and generates SQL code to update the original object. Since the original object was modified by the FormView, it will never be found by SQL and no update will occur!

While there are other techniques you can use with Linq to SQL to avoid the issue above, the point of this post is to show how the FormView handles null values.

The workaround is to subscribe to the FormView ItemUpdating event and look for string.empty NewValues and set those to null instead.

protected void FormView2_ItemUpdating(object sender, FormViewUpdateEventArgs e)
{
if (e.NewValues["LastName"].Equals(string.Empty))
{
e.NewValues["LastName"] = null;

}
}

In addition, to keep the OldValues unchanged (if you need it for concurrency purposes), set the DataKeyNames property of the FormView to the properties of the object like so:
<asp:FormView ID="FormView2" runat="server" DataSourceID="ObjectDataSource1" OnItemUpdating="FormView2_ItemUpdating"
DefaultMode="Edit" DataKeyNames="LastName, FirstName">

When the Update button is clicked this time, the null values are retained.
(OldValue according to FormView)
FirstName : Tom
LastName : null

(NewValue according to FormView)
FirstName : Tom
LastName : null
 

Two way binding is not supported for nested controls – AFAIK, this is by design.
See an example below:
<EditItemTemplate>
<asp:UpdatePanel runat="server" ID="up1">
<ContentTemplate>
FirstName:
<asp:TextBox ID="FirstNameTextBox" runat="server" Text='<%# Bind("FirstName") %>' />
</ContentTemplate>
</asp:UpdatePanel>
LastName:
<asp:TextBox ID="LastNameTextBox" runat="server" Text='<%# Bind("LastName") %>' />
<br />
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update"
Text="Update" />
</EditItemTemplate>

Here we have a TextBox inside an UpdatePanel inside the EditItemTemplate. Since two way binding is not supported for the FirstNameTextBox, the special code for extracting values is not generated resulting in null being sent back for the FirstName property.

To work around this, you will need to subscribe to the ItemUpdating event and extract the values yourself:
protected void FormView2_ItemUpdating(object sender, FormViewUpdateEventArgs e)
{
TextBox FirstNameTextBox = (TextBox)FormView2.FindControl("FirstNameTextBox");
e.NewValues["FirstName"] = FirstNameTextBox.Text;
}

Visibility of controls in a FormView.
Setting Visibility of a control inside a FormView does not work - the TextBox control goes back to visible on update.
protected void Page_Load(object sender, EventArgs e)
{
FormView1.FindControl("FirstNameTextBox").Visible = false;
}

Do it in the DataBound event instead:

protected void FormView2_DataBound(object sender, EventArgs e)
{
FormView1.FindControl("FirstNameTextBox").Visible = false;
}

If you have better ideas on any of the workarounds above, please post a comment or link. Thanks.

Posted by rajbk | 2 comment(s)
Filed under: , ,

Altering Indexed Views - Gotcha

According to BOL, “ALTER VIEW can be applied to indexed views; however, ALTER VIEW unconditionally drops all indexes on the view.”

We can see this behavior by creating an indexed view using the Northwind database. The script is shown below:

CREATE VIEW [dbo].[MyView] WITH SCHEMABINDING
AS
SELECT ContactName, CompanyName
FROM dbo.Customers

GO

CREATE UNIQUE CLUSTERED INDEX [inx_MyIndex] ON [dbo].[MyView]
(
[ContactName] ASC
)
GO

Note that the indexed view must be created with the SCHEMABINDING option. SCHEMABINDING binds the view to the schema of the underlying base tables.

Now the fun part. We alter the index view by adding a new column “ContactTitle”, like so:

ALTER VIEW [dbo].[MyView] WITH SCHEMABINDING
AS
SELECT ContactName, CompanyName, ContactTitle
FROM dbo.Customers

GO

-- Output from Management Studio
-- Command(s) completed successfully.

By looking at the view in management studio, after refreshing the tree, we see that the index is no longer there! I expected to see a warning message when this occurred :-(
 
The easiest way to work around this is to make a copy of the index creation script before you alter the indexed view and run it afterwards.
Posted by rajbk | with no comments

Using the Modal Popup Extender to build a popup search interface

This post and sample code demonstrates how to use the Modal Popup Extender (MPE) to display a popup search box, select a record from the popup, hide the popup and display details for the selected record on the page using AJAX.

We will be using the Northwind database and displaying a “Find Customer” popup. Once a Customer is selected from the search result list, we hide the MPE and refresh UpdatePanels on the page with information related to the Customer that was picked. Sample source code is attached at the bottom of the page.

popuppicker 

The events that occur as as follows:

When we click on the “Show Customer Picker” button, we have a popup appear with the help of an MPE. This MP has a UserControl with textboxes, a search button and a GridView inside an UpdatePanel. Performing a “Search” will cause only the contents of this UpdatePanel to get refreshed. To avoid the search GridView from binding when the popup is hidden (when an async postback occurs by some other button on the page), we keep track of the MP visibility (The technique for keeping track of the MPE visibility is described here). If the MP is hidden, we use the ObjectDataSourceSelectingEventArgs.Cancel method in the ObjectDataSource Selecting event to cancel the SQL call.

When we select an employee by clicking on the “Select” link, the Selecting event of the GridView is raised. We get the primary key of the selected customer by subscribing to this event. The MP is then hidden and a custom CustomerSelected event is raised.

The Page is subscribed to the CustomerSelected event and saves the selected customer primary key to Session (You could use other techniques instead of this). It then forces the UpdatePanels of other UserControls on the page to refresh themselves. These UpdatePanels have databound controls in them that get bound by making SQL calls using the customer PK stored in Session. The page ends up showing information about the selected customer (Customer Details, Last 10 orders, To 10 Orders) on the page without a full page refresh.

The sample website project shows you how to achieve this UI in three stages (three pages). The demo in Stage1 shows how the page is laid out without using AJAX – all postbacks result in a full page refresh. In Stage2, we add the UpdatePanels to perform partial page rendering. In Stage3, we add the MP that displays the “Find Customer” popup.

Don’t forget to add a reference to the Ajax Control ToolKit before building the project.

Source Code
Mirror

Posted by rajbk | 6 comment(s)
More Posts Next page »