Improvements in Internet Explorer 8 Beta 2

I was just checking out the improvements the team has made in beta 2 of Internet Explorer 8. While I haven’t had time to mess with all of the improvements, I see lots of opportunities to create enhancements for my sites to allow visitors to get what they are looking for faster. Be sure to check out the full list of improvements at http://blogs.msdn.com/ie/archive/2008/08/28/part-i-better-everyday-browsing.aspx. You can download IE8 Beta 2 at http://www.microsoft.com/ie8.

How to Override Cassini’s Virtual Path in Visual Studio

On one of the email lists that I’m on, someone had posted a question about running a website using the root path "/" or a different virtual path than the project name that is populated by default. James Crowley pointed out a blog entry from Scott Guthrie where Scott walks through this process in 4 easy steps. To check it out, visit http://weblogs.asp.net/scottgu/archive/2006/12/19/tip-trick-how-to-run-a-root-site-with-the-local-web-server-using-vs-2005-sp1.aspx.

Known Issues with Service Pack 1 in ASP.NET 3.5

Scott Galloway from the Microsoft DevDiv team has posted a couple of known issues with Service Pack 1 in ASP.NET 3.5 on the ASP.NET forums at http://forums.asp.net/t/1305800.aspx. The issues he currently has on the post are:

Issue:  The HtmlForm action attribute is now honored when defined in declarative markup.
Reason:
3.5 SP1 added a settable Action property to the HtmlForm type.  This new feature makes it much easier for developers to explicitly set the form’s action attribute for scenarios where a developer wants to use a different Url than the normal postback-generated Url.  However this change also means that if the action attribute has been set in an .aspx page’s declarative markup, ASP.NET will use the setting from the markup when rendering a <form /> element. 
Workaround:
Previous versions of ASP.NET always ignored the action attribute if it was present in the declarative markup for a <form /> element.  Developers should remove the action attribute from their declarative markup to return to the original behavior where ASP.NET renders the postback Url.
Example:
Before (the action attribute was ignored by ASP.NET as dead code):  <form name="form1" method="post" runat="server" action="test.aspx"></form>
3.5 SP1 (remove the action attribute to have ASP.NET render the postback Url):  <form name="form1" method="post" runat="server" ></form>


Issue: After installing .NET 3.5 SP1, a web site using pageBaseType now encounters the following compilation error: “Make sure that the class defined in this code file matches the ‘inherits’ attribute.”
Reason:
The behavior you are seeing is the original behavior of ASP.NET 2.0. When .NET 3.5 / VS 2008 was introduced a bug occurred that affected certain pageBaseType scenarios, unfortunately inadvertently enabling scenarios which were not intended. It seems like you might have run into one of the latter scenarios. In FX3.5 SP1, these unintended scenarios were removed so that pageBaseType works the same as in ASP.NET 2.0 (RTM), following requests by customers.  Unfortunately, this means customers who have relied upon these unintended scenarios for their applications to work between 3.5 RTM and 3.5 SP1 would now encounter problems running their applications. We are now evaluating a HotFix for these particular scenarios and providing workarounds for customers to help with this issue. 
In retrospect, it was a mistake to disable these unintended scenarios in FX3.5 SP1 and we apologize for the inconvenience this has caused.
Here are some more details about the issue: –
The mismatch is caused by the class in the code-file not being assignable to the pageBaseType defined in web.config.
- During code generation for a page (foo.aspx), in a Web Site model ASP.NET creates a separate class from the class defined in the CodeFile source (foo.aspx.cs). The Web.config’s pageBaseType value can be used in cases where you want all pages to have certain properties. It applies to all pages, not just pages that do not have code-files.- If foo.aspx has a CodeFile attribute and therefore inherits from a class defined in foo.aspx.cs, the class defined in foo.aspx.cs must extend the pageBaseType.
Workarounds:
1. If the pageBaseType (MyBasePage) is not needed for all pages, you could remove it from web.config
2. Where pages do require the pageBaseType, modify the classes in the code-files to extend the base type. In the <filename>.aspx.cs code-file, make sure the class inherits from the pageBaseType specified in web.config e.g. “public partial class CodeFileClass : MyBasePage”, instead of “public partial class CodeFileClass : System.Web.UI.Page”
3. Add the following to your page directive: CodeFileBaseClass="System.Web.UI.Page"

If you have any others, feel free to post them here and I’ll pass them onto ScottGa and the rest of the team.

Use LINQ to XML to Generate Excel Documents

I was looking for a quick and easy solution to export data from SQL into an Excel format from within my ASP.NET application. I came across a great video posted by Beth Massi on the asp.net website (Video #7 at the bottom at http://www.asp.net/learn/linq-videos/). Beth steps through creating the LINQ to XML and how you can populate your Excel document. When I used this in an ASP.NET application, I added the XML declaration to the Response.Write so that Excel could understand the document. In ASP.NET, the XMLDocument type has a tendency to drop the XML declaration when writing out the document using .ToString.

It’s quite easy to get this to work. Imagine thatweI have a simple result set of products that contains column ID, Product, and Price. We’d create an Excel document that would look like the following:

LinqToExcel-01

Save this document as XML Spreadsheet 2003 (in Office 2007) or XML Spreadsheet (in Office 2003). This will save our sample spreadsheet with the proper XML markup. If you open the newly created XML file in Notepad, you’d see the XML that makes up this spreadsheet.

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:o="urn:schemas-microsoft-com:office:office"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:html="http://www.w3.org/TR/REC-html40">
    <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
        <Author>Jason N. Gaylord</Author>
        <LastAuthor>Jason N. Gaylord</LastAuthor>
        <Created>2008-08-11T18:01:35Z</Created>
        <Company>Jason N. Gaylord</Company>
        <Version>12.00</Version>
    </DocumentProperties>
    <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
        <WindowHeight>12240</WindowHeight>
        <WindowWidth>24855</WindowWidth>
        <WindowTopX>240</WindowTopX>
        <WindowTopY>105</WindowTopY>
        <ProtectStructure>False</ProtectStructure>
        <ProtectWindows>False</ProtectWindows>
    </ExcelWorkbook>
    <Styles>
        <Style ss:ID="Default" ss:Name="Normal">
            <Alignment ss:Vertical="Bottom"/>
            <Borders/>
            <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/>
            <Interior/>
            <NumberFormat/>
            <Protection/>
        </Style>
        <Style ss:ID="s18" ss:Name="Currency">
            <NumberFormat
             ss:Format="_(&quot;$&quot;* #,##0.00_);_(&quot;$&quot;* \(#,##0.00\);_(&quot;$&quot;* &quot;-&quot;??_);_(@_)"/>
        </Style>
        <Style ss:ID="s66">
            <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/>
        </Style>
        <Style ss:ID="s68" ss:Parent="s18">
            <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/>
        </Style>
        <Style ss:ID="s69">
            <Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
            <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"
             ss:Bold="1"/>
        </Style>
        <Style ss:ID="s70" ss:Parent="s18">
            <Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
            <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"
             ss:Bold="1"/>
        </Style>
        <Style ss:ID="s73">
            <Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
            <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/>
        </Style>
    </Styles>
    <Worksheet ss:Name="Sheet1">
        <Table ss:ExpandedColumnCount="3" ss:ExpandedRowCount="3" x:FullColumns="1"
         x:FullRows="1" ss:StyleID="s66" ss:DefaultRowHeight="15">
            <Column ss:StyleID="s73" ss:AutoFitWidth="0" ss:Width="35.25"/>
            <Column ss:StyleID="s66" ss:AutoFitWidth="0" ss:Width="135"/>
            <Column ss:StyleID="s68" ss:AutoFitWidth="0" ss:Width="82.5"/>
            <Row ss:StyleID="s69">
                <Cell>
                    <Data ss:Type="String">ID</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Product</Data>
                </Cell>
                <Cell ss:StyleID="s70">
                    <Data ss:Type="String">Price</Data>
                </Cell>
            </Row>
            <Row>
                <Cell>
                    <Data ss:Type="Number">1</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Apple</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="Number">0.79</Data>
                </Cell>
            </Row>
            <Row>
                <Cell>
                    <Data ss:Type="Number">2</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="String">Banana</Data>
                </Cell>
                <Cell>
                    <Data ss:Type="Number">0.99</Data>
                </Cell>
            </Row>
        </Table>
        <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
            <PageSetup>
                <Header x:Margin="0.3"/>
                <Footer x:Margin="0.3"/>
                <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
            </PageSetup>
            <Print>
                <ValidPrinterInfo/>
                <HorizontalResolution>600</HorizontalResolution>
                <VerticalResolution>0</VerticalResolution>
            </Print>
            <Selected/>
            <ProtectObjects>False</ProtectObjects>
            <ProtectScenarios>False</ProtectScenarios>
        </WorksheetOptions>
    </Worksheet>
    <Worksheet ss:Name="Sheet2">
        <Table ss:ExpandedColumnCount="1" ss:ExpandedRowCount="1" x:FullColumns="1"
         x:FullRows="1" ss:DefaultRowHeight="15">
        </Table>
        <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
            <PageSetup>
                <Header x:Margin="0.3"/>
                <Footer x:Margin="0.3"/>
                <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
            </PageSetup>
            <ProtectObjects>False</ProtectObjects>
            <ProtectScenarios>False</ProtectScenarios>
        </WorksheetOptions>
    </Worksheet>
    <Worksheet ss:Name="Sheet3">
        <Table ss:ExpandedColumnCount="1" ss:ExpandedRowCount="1" x:FullColumns="1"
         x:FullRows="1" ss:DefaultRowHeight="15">
        </Table>
        <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
            <PageSetup>
                <Header x:Margin="0.3"/>
                <Footer x:Margin="0.3"/>
                <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
            </PageSetup>
            <ProtectObjects>False</ProtectObjects>
            <ProtectScenarios>False</ProtectScenarios>
        </WorksheetOptions>
    </Worksheet>
</Workbook>



Copy this XML and go into your ASP.NET application. For my application, I created an HttpHandler to generate my output. Note that you must use a class file (or code-behind) as the XML will not work within an .aspx page. We’ll create a few variables to populate our XML spreadseet. I created a new variable called OutputSpreadsheet and set the value of this variable to the entire XML document just copied from Notepad.



LinqToExcel-02



Next, copy the namespace declarations (with the exception of the HTML reference) and add these namespaces as imports to the top of the class. This allows the special Excel row and column attributes to be valid.



LinqToExcel-03



Above the OutputSpreadsheet variable, create a new variable called SpreadsheetData. Scroll down to find the Worksheet named Sheet1 in the XML. Cut the second row section and past it into Spreadsheet Data.



LinqToExcel-04



We can then populate the XML by using a LINQ query with embedded expressions.



LinqToExcel-05



Now that the query can populate the rows, we must modify the XML in the OutputSpreadsheet variable to handle the rows. Be sure that in the row elements, that only the header row element remains. If other row elements exist, delete them. Add the expression



<%= SpreadsheetData %>


right below the header row element. This will add the populated rows to the spreadsheet. We must also tell Excel how many rows to expect. To do this, we need to modify the XML attribute ss:ExpandedRowCount on the Table element and add in <%= SpreadsheetData.Count + 1 %>. We are adding 1 to accommodate our header row.



LinqToExcel-06



Finally, we can output our response to the browser.



LinqToExcel-07



As you can see, it’s pretty easy to generate the Excel XML output. Thanks for all your help Beth!

ASP.NET 3.5 SP1 (Formerly "ASP.NET 3.5 Extensions") Released

ASP.NET 3.5 Service Pack 1, which was formerly called the ASP.NET 3.5 extensions, has been released. The NetFX update was available as part of the SQL Server 2008 download available on Friday. Now it is available as a separate download. There are quite a few enhancements in 3.5 including Dynamic Data, the Entity Framework, the AJAX History control, better Silverlight support and more! Be sure to download it today at http://www.asp.net/downloads/3.5-sp1/.

Known Postback Issue with AJAX Controls

I came across a postback issue while using the CascadingDropDown AJAX control. I had a web page with 3 DropDownList controls. The data for these controls was populated from the CascadingDropDown which would bind the data at runtime. The issue with this is that when data is being bound at runtime, it cannot be validated during postback unless each value is registered with the page.  In most cases, this wouldn’t make sense. So, we have to fall back to turning off EventValidation at an application level in the web.config (attribute is found on the pages element) or at the page level (attribute is added to the page directive). It’s best to turn off the EventValidation at the page level. There is no way to turn this off at the control level unless you are building your own control that does not contain the SupportsEventValidation attribute.