Archives

Archives / 2003 / October
  • ASP.NET v2.0: Miscellaneous Cool Features

    ASP.NET v2.0 makes it easy to set focus and defaul buttons, as well as maintain your scroll positions across postbacks.  Its easy to setup a site map so navigational menus, trees, and breadcrumbs are all based on this one store.  Client-side callbacks that allow you to minimize postbacks are really cool, as is the creation of a separate ControlState (from ViewState) for essential properties.  Of course, it goes without say that I like MasterPages, as well as Themes and Skins.  I also like the Code and Resources directories, and you can even specify additional code directories to automatically compile.  Finally, VS.NET actually does not alter your html, and it actually will even supply some more control of how it alters it if you want it to do so at all in the first place.

    Read more...

  • ASP.NET v2.0: Posting to Other Pages is too Limited

    I'm definitely excited about ASP.NET v2.0 and all the new features it brings, so its hard to criticize it in most cases.  However, one problem I have is with the current implementation of posting to other pages.  As most ASP.NET developers know, your server-form is limited to posting back to itself in ASP.NET v1.*.  This behavior will change in ASP.NET v2.0 with a feature called cross-page posting.  Basically, each button (and other relevant controls) have a postTargetUrl property.  This property allows you to specify where that control will cause the page to be posted to.  This is great in most cases since it allows the post target to be changed on a case-by-case basis, while keeping the rest of the form to still post back to itself.  The problem is that the  current implementation forces this url to be a page in the same application!

    I understand what the ASP.NET team is doing -- they are allowing you to actually code against the original page from the new page that was posted to.  This is a great feature, but there is little need for posting to another page of your own application!  On the other hand, there are very real and important needs to be able to post to other pages outside of your server, let alone your application.  These include all sorts of services that others have implemented, including some payment processing engines.  There are work-arounds to this right now in v1.* that will continue to work in v2.0, but I think they should address the real need here if they are going to address it at all.  In case you are wondering, the work-arounds are to (1) use non-server forms and no server controls, (2) emit client-side java-script to change the action attribute of the form, (3) or use a custom server form control like Andy Smith's from MetaBuilders or my WilsonWebForm.

    I don't expect them to change their overall approach and start allowing multiple server forms, which so far can only be done with my WilsonWebForm.  I don't like that they limit valid html which makes perfect sense in some cases just because its not the best practice in most cases, but I do appreciate their stance on this -- and it certainly helps me sell more subscriptions.  But this is different, they are going out of their way to admit there are cases that require something different, while still ruling out the only scenarios that really matter.  And so far it seems that this feature is getting received very well (although I doubt this huge limitation is understood by most of these people), so its actually kind of funny to me that they originally didn't even want to provide this feature at all when I and others first asked for it.  So write to Rob Howard or Scott Guthrie and complain now while there is still time to correct this oversight.

    Read more...

  • ASP.NET v2.0: New Web.Config Options in Whidbey

    There are lots of new options in the web.config file in ASP.NET v2.0.  I particularly like ability to globally define your RegisterTagPrefixes, as well as your Imports for all of your Pages.  Its also nice to see the cookieless attribute for Forms Authentication, with more options then just true or false so that different devices are handled appropriately.  Many of these others are very complicated, and they'll be discussed in articles about the specific features.  Here's the general layout:

    <configuration>
      <system.web>
        <authentication mode="Forms">
          <forms defaultUrl=""
              cookieless="UseCookies|UseUri|AutoDetect|UseDeviceProfile" />
        </authentication>
        <connectionStrings />
        <featurePermissions />
        <healthMonitoring />
        <membership />
        <pages master="">
          <imports>
            <add namespace="" />
          </imports>
          <registerTagPrefixes>
            <add tagPrefix="" namespace="" />
          </registerTagPrefixes>
        </pages>
        <personalization />
        <siteCounters />
        <siteMap />
        <SMTPMail serverName="" serverPort="" from="" />
      </system.web>
    </configuration>

    Read more...

  • ASP.NET v2.0: ObjectDataSource and ObjectSpaces

    ASP.NET v2.0 has several datasource controls that allow you to declare all of your database access code when using the new GridView and other controls.  One of the coolest versions of this is the ObjectDataSource control which lets you easily declare the name of a class and a method that will return a collection of bindable of objects -- not your usual DataSet or DataReader:

    <asp:gridview id="CategoriesGrid" runat="server"
        datasourceid="CategoriesDS" />
    <asp:objectdatasource id="CategoriesDS" runat="server"
        typename="BusObjects" selectmethod="GetCategories" />

    I've hooked this concept up to a class that uses ObjectSpaces against the Northwind database to have an ASP.NET page that not only has no code in it, but there is also no SQL or stored procedure!  Declarative GUI and declarative database, with just a few simple classes and trivial code to get ObjectSpaces to hook it all together.  You could also use generics with this control.

    Read more...

  • ADO.NET v2.0: ObjectSpaces Delivers an O/R Mapper

    ObjectSpaces is one of the most exciting parts of .NET v2.0 to me.  Yes, I'm well known for ASP.NET, but I'm a software architect, and I've really been intrigued by the potential of O/R mappers.  So read my article on ObjectSpaces and download my sample code that uses the Northwind database.  The front-end is ASP.NET, and there's no links between pages or any instructions, but the code works if you have Whidbey.

    Read more...

  • .NET v2.0: FTP Classes are now Provided

    There are now a couple of FTP-specific classes in System.Net: FtpWebRequest and FtpWebResponse.

    The FtpWebRequest class has a Method property that is set to a value from the FtpMethods structure:

    • AppendFile
    • DeleteFile
    • DownloadFile
    • GetFileSize
    • ListDirectory
    • UploadFile

    Read more...

  • VB.NET v2.0: Property Gets and Sets with Different Accessibility

    Once again there is mention of a new cool feature in C#:

    Properties can now have different accessibility for get {...} and set {...}.

    Well, once again this is also available in VB.NET v2.0:

    Private _myProperty As String

    Public Property MyProperty() As String
        Get
            Return _myProperty
        End Get
        Protected Set(ByVal value As String)
            _myProperty = value
        End Set
    End Property

    As much as I prefer C# myself, I'm starting to wonder what's not in VB?

    Read more...

  • .NET v2.0: Serial Port Communications Finally Arrives

    System.IO.Ports.SerialPort (derives from System.ComponentModel.Component) -- Whidbey's MSDN:

    Use this class to control a serial port file resource. It provides synchronous and event-driven IO, access to pin and break states, and access to serial driver properties. In addition, its functionality can be wrapped in an internal Stream object, accessible through the BaseStream property, and passed to classes that wrap or utilize streams.

    Public Constructors
          SerialPort Initializes a new instance of the SerialPort class.

    Public Events
          Disposed (inherited from Component)Adds an event handler to listen to the Disposed event on the component.
          ErrorEvent Represents the method that handles the error event of a SerialPort object.
          PinChangedEvent Represents the method that will handle the serial pin changed event of a SerialPort object.
          ReceivedEvent Represents the method that will handle the serial received event of a SerialPort object.

    Public Fields
          InfiniteTimeout Value indicates that no timeout should occur.

    Public Methods
          Close Closes the port connection, sets System.IO.Ports.IsOpen to false and disposes of the internal Stream object.
          CreateObjRef (inherited from MarshalByRefObject)Creates an object that contains all the relevant information required to generate a proxy used to communicate with a remote object.
          DiscardInBuffer Discards data from the serial driver's receive buffer.
          DiscardOutBuffer Discards data from the serial driver's transmit buffer.
          Dispose (inherited from Component)Releases the resources used by the Component.
          Equals (inherited from Object)Determines whether the specified Object is equal to the current Object.
          GetHashCode (inherited from Object)Serves as a hash function for a particular type, suitable for use in hashing algorithms and data structures like a hash table.
          GetLifetimeService (inherited from MarshalByRefObject)Retrieves the current lifetime service object that controls the lifetime policy for this instance.
          GetType (inherited from Object)Gets the Type of the current instance.
          InitializeLifetimeService (inherited from MarshalByRefObject)Obtains a lifetime service object to control the lifetime policy for this instance.
          Open Opens a new serial port connection.
          Read Reads from the SerialPort input buffer.
          ReadByte Synchronously reads one byte from the SerialPort input buffer.
          ReadChar Synchronously reads one character from the SerialPort input buffer.
          ReadExisting Reads all immediately available characters (based on the Encoding) in the stream and internal buffer of the SerialPort object.
          ReadLine Reads up to the NewLine value in the input buffer.
          ReadTo Reads up to the specified value in the input buffer.
          ToString (inherited from Component)Returns a String containing the name of the Component , if any. This method should not be overridden. For internal use only.
          Write Writes data to serial port output.
          WriteLine Writes the specified string and the NewLine value to the output buffer.

    Public Properties
          BaseStream Gets the internal Stream object, if it exists, for a SerialPort object .
          BaudRate Gets or sets the serial baud rate.
          BreakState Gets or sets the break signal state.
          BytesToRead Gets the number of bytes of data in the receive buffer.
          BytesToWrite
          CDHolding Gets the state of the carrier detect line for the port.
          Container (inherited from Component)Gets the IContainer that contains the Component.
          CtsHolding Gets the state of the clear-to-send line.
          DataBits Gets or sets the standard length of databits per byte.
          DiscardNull Gets or sets whether null characters are ignored when transmitted between the port and the receive buffer.
          DsrHolding Gets the state of the data set ready (DSR) signal.
          DtrEnable Gets or sets the enabling of DTR during serial communication.
          Encoding Gets or sets the character encoding for pre- and post-transmission conversion of text.
          Handshake Gets or sets the handshaking protocol for serial port transmission of data.
          IsOpen Gets the open or closed status of the SerialPort object.
          NewLine Gets or sets the value used to interpret the end of a call to the ReadLine and WriteLine methods.
          Parity Gets or sets the parity checking protocol.
          ParityReplace Gets or sets the 8-bit character that is used to replace invalid characters in a data stream when a parity error occurs.
          PortName Gets or sets the port for communications, including but not limited to all available com ports.
          ReadBufferSize
          ReadTimeout Gets or sets the number of milliseconds before a timeout occurs when a read operation does not finish.
          ReceivedBytes Threshold Gets or sets the number of bytes in the internal input buffer before a ReceivedEvent is fired.
          RtsEnable Gets or sets the enabling of RTS during serial communication.
          Site (inherited from Component)Gets or sets the ISite of the Component.
          StopBits Gets or sets the standard number of stopbits per byte.
          WriteBufferSize
          WriteTimeout Gets or sets the number of milliseconds before a timeout occurs when a write operation does not finish.

    Read more...

  • ASP.NET v2.0: Update on the Page Lifecycle

    I just posted a new article on the Page Lifecycle in ASP.NET v2.0 (Whidbey).  Its mostly just a brief update of my previous article on the Page Lifecycle in ASP.NET v1.*.  Keep in mind that the page lifecycle is probably the single most important thing for any ASP.NET developer to understand, and I can't begin to count the number of problems that I see in the Forums from those that don't get it.  I'll try to blog a few other experiences with .NET v2.0 today, and I'm going to work hard to get another article that will be really cool tomorrow, or as soon as possible.

    Read more...

  • VB.NET v2.0: Generics are Supported in VB Also

    Rob Chartier has created a really nice article titled Introducing .NET Generics.  Unfortunately, all of the sample code was written using C# -- just like every sneak peek on generics so far.  However, VB.NET will also fully support generics in .NET v2.0 (Whidbey), although not much has been stated about this.  Take a look at my VB.NET translations here -- you'll note that Of is the VB keyword used for generics, instead of using the <> syntax of C#. 

    Given Rob's C# first generic type:

    public class Col<T> {
      T t;
      public T Val {
        
    get {
          return t;
        }
        
    set {
          t =
    value;
        }
      }

    }

    Here's the equivalent VB generic type:

    Public Class Col(Of T)
      Dim _t As T
      Public Property Val() As T
        Get
          Return _t
        End Get
        Set(ByVal value As T)
          _t = value
        End Set
      End Property
    End Class

    Given Rob's C# first generic usage:

    Col<string> mystring = new Col<string>();

    Here's the equivalent VB generic usage:

    Dim mystring As New Col(Of String)

    Rob has a C# generic method also:

    public static T[] CreateArray<T>(int size) {
      return new T[size];
    }

    And here's the equivalent VB again:

    Public Shared Function CreateArray(Of T)(ByVal size As Integer) As T()
      Dim _t(size) As T
      Return _t
    End Function

    It looks like VB.NET also allows constraints on generics, although I haven't tested this yet.  I personally prefer C#, but I find many potential customers are interested in VB.NET, including my current employer.  So far C# is getting the headlines in v2.0, but it looks like VB.NET is doing just fine too.  By the way, the System.Collections.Generics namespace is full of pre-built generic collections, like Dictionary, List, Queue, Stack, and many others too.

    Read more...

  • VB.NET v2.0: Operators, Using, Unsigned Types, and More

    It seems I've “outed” several new VB.NET keywords so far today, so I might as well continue with that theme.

    • Continue -- This one's obvious, but from Whidbey's MSDN: Transfers control immediately to the next iteration of a loop.
    • Operator -- VB finally gets operator overloading, with plenty of binary and unary operators to redefine.  Whidbey's MSDN:

    Public Shared Operator Or(ByVal x As abc, ByVal y As abc) As abc
      Dim r As New abc
      Return r
    End Operator

    Public Shared Operator IsFalse(ByVal z As abc) As Boolean
      Dim b As Boolean
      Return b
    End Operator

    • Using -- Equivalent to the using keyword in C# that automatically calls the Dispose method when done.  My example:

    Using _myClass As New MyClass()
      _myClass.MyMethod()
    End Using

    • Expands -- See this post on Code-Beside for some discussion of Partial Types, where Expands is the VB keyword.
    • Of -- See this post on generics support in VB.NET, where Of is the VB keyword that is equivalent to <> syntax in C#.
    • SByte, UInteger, ULong, and UShort -- These should be obvious, each one is unsigned type, except signed SByte.
    • IsFalse, IsNot, IsTrue -- These are new operators that can be overridden with the new operator overloading above.

    Read more...

  • VB.NET v2.0: Generics are Supported in VB Also

    Rob Chartier has created a really nice article titled Introducing .NET Generics.  Unfortunately, all of the sample code was written using C# -- just like every sneak peek on generics so far.  However, VB.NET will also fully support generics in .NET v2.0 (Whidbey), although not much has been stated about this.  Take a look at my VB.NET translations here -- you'll note that Of is the VB keyword used for generics, instead of using the <> syntax of C#. 

    Given Rob's C# first generic type:

    public class Col<T> {
      T t;
      public T Val {
        
    get {
          return t;
        }
        
    set {
          t =
    value;
        }
      }

    }

    Here's the equivalent VB generic type:

    Public Class Col(Of T)
      Dim _t As T
      Public Property Val() As T
        Get
          Return _t
        End Get
        Set(ByVal value As T)
          _t = value
        End Set
      End Property
    End Class

    Given Rob's C# first generic usage:

    Col<string> mystring = new Col<string>();

    Here's the equivalent VB generic usage:

    Dim mystring As New Col(Of String)

    Rob has a C# generic method also:

    public static T[] CreateArray<T>(int size) {
      return new T[size];
    }

    And here's the equivalent VB again:

    Public Shared Function CreateArray(Of T)(ByVal size As Integer) As T()
      Dim _t(size) As T
      Return _t
    End Function

    It looks like VB.NET also allows constraints on generics, although I haven't tested this yet.  I personally prefer C#, but I find many potential customers are interested in VB.NET, including my current employer.  So far C# is getting the headlines in v2.0, but it looks like VB.NET is doing just fine too.  By the way, the System.Collections.Generics namespace is full of pre-built generic collections, like Dictionary, List, Queue, Stack, and many others too.

    Read more...

  • ASP.NET v2.0: Code-Beside Replaces Code-Behind

    I'm not at the PDC, but that can't stop me from talking about .NET v2.0 (Whidbey) as of today.  I'll try to do even better than the folks at the PDC and actually post some real details!  That's right, my goal this week is to post a brief article each day at ASPAlliance.com.  I'll also try to blog some other shorter details based on my experiences this last year.  So, here's the first article: ASP.NET v2.0: Code-Beside Replaces Code-Behind.  ASP.NET v2.0 replaces the Code-Behind code-separation technique with Code-Beside, which is designed to be an easier and less brittle method based on Partial Types.  (Note: I'm glad they did not call this Code-Behind v2.0, which was one of the early candidates.)

    The article is not really about Partial Types, as there isn't much to them in reality.  However, it does confirm that this is a feature of VB.NET as well as C#, although not well publicized.  I also have some syntax notes on using Code-Beside and Partial Types, which shows you that the VB.NET keyword for a Partial Type is Expands, instead of the partial keyword used in C#.  Also note that while C# requires you to put the partial keyword in all code files for that type, VB.NET expects one main code file without the Expands keyword.  For ASP.NET, this means that the ASPX Page is that main file, not the Code-Beside file, which has the odd side-effect that any inheritance for the class must be defined in the ASPX Page, not the Code-Beside file.

    Finally, I have grown to really like this easier version of Code-Behind over the last year, but it does have one aspect that I don't like in some cases.  You can no longer deploy and update ASPX Pages while separately compiling your code files, which is nice if you want to not make the source completely obvious, or even apply some obfuscation.  That's right, your choice is to deliver both the ASPX Page and Code-Beside source files, or you can pre-compile both, but that will make it impossible to update even the ASPX content on the fly.  Maybe another option will yet be delivered, as the ASP.NET team is just now starting their work on their last of three milestones, but that remains to be seen.

    Read more...

  • ASP.NET v2.0 (Whidbey) Articles on ASPNetPro.com

    I've been watching ASP.NET Pro Magazine start releasing articles on ASP.NET v2.0 (Whidbey) this week.  Technically they seem to be jumping the gun a little ahead of the PDC, but go ahead and read them if you subscribe.  So far they've released the following 3 articles, including mine on Master Pages:

    My article on Master Pages includes a working version of everything in ASP.NET v1.* also -- even nested and dynamic masters.  If you don't subscribe then you can at least get a copy of my custom version of Master Pages for v1.* with some basic examples, just not the best ones from the new article.

    Read more...

  • Sorting and Paging Recordsets in SQL Server

    Here's a stored procedure that I use for sorting and paging large recordsets in SQL Server, as opposed to using the more common and terribly inefficient entire dataset approach in .NET.  It certainly doesn't matter much in the little classroom examples of a few hundred, or even thousands, of records, but working with larger recordsets with datasets is just bad.  This is even more true with ASP.NET, since the entire dataset is usually saved in viewstate, and since the web server is doing the processing for many users.  This stored procedure is certainly not the only way to do sorting and paging in SQL Server, but it is probably the most efficient, although proper indexing is still required to avoid table scans.  Note that this does not use temporary tables, which are convenient but not as optimal -- this also means you could modify this to be dynamic SQL for Access or other databases!  The parameters are the name of the table, the name of the primary key (necessary for the little bit of optimization included), the name of the sort field (or sort fields, with or without ASC/DESC), and the page size (number of records).  It also allows optional parameters for the page index (defaults to 1st page) and a query filter (defaults to null) so you can sort and page through filtered records only!  Note that it returns two recordsets -- the first is the results you expect, and the second recordset is a scalar with the number of total pages so you can better define the GUI pager for a grid.  This is relatively easy to integrate with the ASP.NET datagrid if you use custom paging and sorting, and it will minimize both your load on the server and the amount of data sent to the client's browser!  By the way, this code is just modified from some I found on the net, and there are certainly some minor optimizations that can be done, like using different sql for the first page.

    CREATE PROCEDURE GetSortedPage(
      @TableName VARCHAR(50),
      @PrimaryKey VARCHAR(25),
      @SortField VARCHAR(100),
      @PageSize INT,
      @PageIndex INT = 1,
      @QueryFilter VARCHAR(100) = NULL
    ) AS
    SET NOCOUNT ON

    DECLARE @SizeString AS VARCHAR(5)
    DECLARE @PrevString AS VARCHAR(5)

    SET @SizeString = CONVERT(VARCHAR, @PageSize)
    SET @PrevString = CONVERT(VARCHAR, @PageSize * (@PageIndex - 1))

    IF @QueryFilter IS NULL OR @QueryFilter = ''
    BEGIN

      EXEC(
      'SELECT * FROM ' + @TableName + ' WHERE ' + @PrimaryKey + ' IN
        (SELECT TOP ' + @SizeString + ' ' + @PrimaryKey + ' FROM ' + @TableName + ' WHERE ' + @PrimaryKey + ' NOT IN
          (SELECT TOP ' + @PrevString + ' ' + @PrimaryKey + ' FROM ' + @TableName + ' ORDER BY ' + @SortField + ')
        ORDER BY ' + @SortField + ')
      ORDER BY ' + @SortField
      )
      EXEC('SELECT (COUNT(*) - 1)/' + @SizeString + ' + 1 AS PageCount FROM ' + @TableName)

    END
    ELSE
    BEGIN

      EXEC(
      'SELECT * FROM ' + @TableName + ' WHERE ' + @PrimaryKey + ' IN
        (SELECT TOP ' + @SizeString + ' ' + @PrimaryKey + ' FROM ' + @TableName + ' WHERE ' + @QueryFilter + ' AND ' + @PrimaryKey + ' NOT IN
          (SELECT TOP ' + @PrevString + ' ' + @PrimaryKey + ' FROM ' + @TableName + ' WHERE ' + @QueryFilter + ' ORDER BY ' + @SortField + ')
        ORDER BY ' + @SortField + ')
      ORDER BY ' + @SortField
      )
      EXEC('SELECT (COUNT(*) - 1)/' + @SizeString + ' + 1 AS PageCount FROM ' + @TableName + ' WHERE ' + @QueryFilter)

    END

    RETURN 0
    GO

    Read more...

  • Observations on my Google Search Rankings

    I've watched several others, usually with less common names, note their high rankings in Google, but I usually didn't stand out unless you included “ASP.NET“ in your search.  Until now -- a search on “Paul Wilson” on Google returns my blog as #5-6 now, as well as listing my WilsonDotNet.com site as #6-7 -- pretty good for a common name like “Paul Wilson”. Also, a search on “Wilson Blog” lists my blog as the #3-4, and a search on “Wilson .NET” (without the full “ASP.NET“) finally ranks me as #1 -- even ahead of Brad Wilson, aka DotNetGuy! The funny thing is that I have not been ranking quite as high lately on more specific searches, like page templates, master pages, and multiple forms, where I used to rank as high as #1. Another observation is that I don't see my articles on ASPAlliance.com show up as high in the searches anymore -- anyone else noticing poor rankings for their ASPAlliance articles? Finally, even though I've never really figured out what to do with MicrosoftArchitect.com, I also now have MasterPage.net, in honor of the upcoming ASP.NET v2.0 Master Pages.

    Read more...