Blog Home  Home Feed your aggregator (RSS 2.0)  
Programming Microsoft ASP.NET 2.0 Advanced Topics has shipped! - Manuel Abadia's ASP.NET stuff
 
# Thursday, March 23, 2006

I got a confirmation email from amazon telling me that the book[1] finally shipped.

Cool! I can’t wait to read it as Programming Microsoft ASP.NET 2.0 Core Reference[2] was a bit basic (IMHO) and reused a lot of material from Introducing ASP.NET 2.0[3] and Programming Microsoft ASP.NET[4]. Don't get me wrong, the book is very good but if you have read [3] and [4] it doesn't add too much. Also the book had quite a few errors. I sent Microsoft Press an email with some errors and comments but they haven’t updated the errata page:

http://support.microsoft.com/kb/905045

As a friend was reading the book and some errors confused him a bit, I sent him the error list I found. I’m posting here the most important ones as somebody may find this useful:

* Page 72: The path in the page is wrong. The correct one is:
       %WINDOWS%\Microsoft.NET\Framework\[version]

* Page 94: When you talk about AutoEventWireUp you say: "Pages developed with Visual Studio .NET have this attribute set to false". This is true for VB.NET but not for C#. If you create a new WebSite using c#, AutoEventWireUp is true

* Page 104: You say: "In an ASP.NET page, no control can be placed outside a <form> tag with the runat attribute set to server." This isn't correct. For example, you can use a PlaceHolder anywhere in the page.

* Page 124: Near the end of the page, when you explain a little bit about the ControlCollection you say: "When a control is added, its view state is resotred if needed and view-state tracking is turned on." This is not true. When a control is added to a ControlCollection, the control advances as many stages of the lifecycle as the parent has advanced. For example, if the control is added before the ViewState has been restored, the control executes the Init stage only. If the control is added in the PreRender stage, the control goes through all
stages up to the PreRender stage.

* Page 125: Under table 4-4 you say: "All server controls are rendered to HTML using the RenderControl method and, when this happens, the PreRender event is fired." This sentence is plain wrong. PreRenders is fired before any rendering takes place.

* Page 127: In the note you list the controls that could not validate against XHTML. However the list is not complete. You're missing ImageMap and MenuItem. Also when you say that "Controls such as HyperLink, BulletedList, and AdRotator generato non-XHTML markup regardless of the settings you choose" it sounds like you can't make anything to generate XHTML compliant pages with that controls. However, if you avoid using the Target property those controls will render valid XHTML.

* Page 135: In the code at the top you use the LinkedStylesheets property of the header that doesn't exists in the RTM version.

* Page 171: The list of conditions to consider a browser as uplevel includes supporting the Microsoft Document Object Model, but that's not correct. The code really checks if the browser supports the World Wide Web Consortium (W3C) XML Document Object Model (DOM) 1.0 or higher using W3CDomVersion.MajorVersion  property

* Page 183: When you explain how the cross-page posting works, you say: "When the previous page contains a control that does cross-page posting, anew hidden field is also created: __PREVIOUSPAGE. This field contains the view state information to be used to serve the request. This view state information is transparently used in lieu of the original view state of the page being posted to". This is not completely accurate. I was very curious to understand the internal behaviour so after inspecting the Page class you can see that when the page is processing the request, the __PREVIOUSPAGE is decrypted to find out the path of the previous page:

VirtualPath path1 = null;

        if (this._requestValueCollection["__PREVIOUSPAGE"] != null) {

            try {

                path1 = VirtualPath.CreateNonRelativeAllowNull(Page.DecryptString(this._requestValueCollection["__PREVIOUSPAGE"]));

            } catch (CryptographicException) {

                this._pageFlags[8] = true;

            }

            if ((path1 != null) && (path1 != this.Request.CurrentExecutionFilePathObject)) {

                this._pageFlags[8] = true;

                this._previousPagePath = path1;

            }

        }

Later, when LoadPageStateFromPersistenceMedium is called, the page is trying to load the view state and gets an exception because the viewstate that was posted wasn't hashed by this page. However, if the page was cross-posted the page ignores the error:

PageStatePersister persister1 = this.PageStatePersister;

        try {

            persister1.Load();

        } catch (HttpException exception1) {

            if (this._pageFlags[8]) {

                return null;

            }

            exception1.WebEventCode = 0xbba;

            throw;

        }

        return new Pair(persister1.ControlState, persister1.ViewState);

 

The PreviousPage property is what forces execution of the previous page using the _previousPagePath that was decrypted from the __PREVIOUSPAGE hidden field:

public Page get_PreviousPage()

    {

        if ((this._previousPage == null) && (this._previousPagePath != null))

        {

            if (!Util.IsUserAllowedToPath(this.Context, this._previousPagePath))

            {

                throw new InvalidOperationException(SR.GetString("Previous_Page_Not_Authorized"));

            }

 

            ITypedWebObjectFactory factory1 = (ITypedWebObjectFactory)BuildManager.GetVPathBuildResult(this.Context, this._previousPagePath);

            if (typeof(Page).IsAssignableFrom(factory1.InstantiatedType))

            {

                this._previousPage = (Page)factory1.CreateInstance();

                this._previousPage._isCrossPagePostBack = true;

                this.Server.Execute(this._previousPage, TextWriter.Null, true, false);

            }

        }

        return this._previousPage;

    }

So if the PreviousPage property is never accesed from the cross posted page the previous page never executes the code.

* Page 186: You say that "Debugging this sample page reveals that posting to another page is a two-step operation. First, a classic postback is made to run any server-side code registered with the original page [...]. Next, the cross-page call is made to reach the desired page:". As I have explained before this is not what really happens.

* Page 187: The important note at the end of the page is not correct as explained in the previous points.

* Page 251: DisplaySideBar: Toggles the visibility of the sidebar. The default value is false. This is wrong. The default value is true (MSDN documentation is wrong too).

* Page 255: The text in the note says: "[...] the push buttons in the navigation bar might look better if they are made the same size. You do this by setting the Width and the Height properties on the NavigationButtonStyle object". However the Width and the Height should be set on the SideBarButtonStyle property, not in the NavigationButtonStyle.

* Page 343: You say: "The compute method has two possible overloads". However there is only a single Compute method in the DataTable.

* Page 343: You say: "This means you can directly compute the sum on two columns, as in the following pseudocode:". However this is a mistake. What you wanted to say is: "This means you can't...".

* Page 357: In the class diagram, there are two boxes labeled as "DataBoundControl". However the top right one should be labeled as "BaseDataList".

* Page 395: In the code for the Employees class there is a method:
       public static void Load(int employeeID)
that should be:
       public static Employee Load(int employeeID)

* Page 399-400: You explain how to set up paging for the ObjectDataSource but you don't tell anything about the SelectCountMethod.

* Page 503: In table 12-2, RoleManager description is wrong (it seems to be a copy paste error from SessionState).

* Page 545: In figure 13-1, there are 4 boxes at the bottom of the figure. The third and fourth (from left to right) should be named: SqlServer session store and Custom session store respectively.

* Page 581: Below the tip you say: "Disabling the view state can also pose subtler problems that are difficult to diagnose and fix, especially if you're working with third-pary controls or, in general, controls for which you have source-code access". I think you wanted to say: "or, in general, controls for which you don't have source-code
access".

* Page 613: In the code at the bottom of the page, the _timer member is marked as static so you can't have two XmlDataCacheDependency at the same time.


 

[1] Programming Microsoft ASP.NET 2.0 Applications. Advanced Topics - Dino Esposito
[2] Programming Microsoft ASP.NET 2.0. Core Reference - Dino Esposito
[3] Introducting ASP.NET 2.0 - Dino Esposito
[4] Programming Microsoft ASP.NET - Dino Esposito
Thursday, March 23, 2006 11:16:01 AM (Romance Standard Time, UTC+01:00)  #    Comments [1]   ASP.NET  | 
Tuesday, November 28, 2006 2:27:44 AM (Romance Standard Time, UTC+01:00)
Thanks!
Shen126
All comments require the approval of the site owner before being displayed.
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

[Captcha]Enter the code shown (prevents robots):

Live Comment Preview
Copyright © 2020 Manuel Abadia. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.