Archives

Archives / 2005 / August
  • Building Re-Usable ASP.NET User Control and Page Libraries with VS 2005

    One of the questions I’ve been asked a few times recently is whether it is still possible to build web projects that encapsulate common libraries of .ascx web user controls or .aspx pages with VS 2005 that can then be easily re-used across multiple other web projects (note: the quick answer is “yes").

     

    This blog post walks-through how to easily accomplish this with VS 2005, as well as some of the new features you can take advantage of to make this scenario even better than before.

     

    Quick Scenario Overview

     

    The scenario I’m going to use to illustrate building re-usable page/control libraries in the below post is one where a development team wants to build a re-usable “ecommerce” web UI library that they can then re-use across multiple web projects and applications (note: if they are an ISV they will also want to be able to package it up and sell it).

     

    The developers building this ecommerce web UI library want to provide two things:

     

    1) Pre-built store-front UI pages (.aspx files) that provide catalog listings, shopping cart management, customer billing, and more.  They want developers using the library to be able to add a \storefront directory into their web project, copy this library of pages into them, and have ecommerce functionality incorporated within their application.

     

    2) Pre-built strong-front UI user controls (.ascx files) that enable scenarios like current sales, current shopping cart items, and best selling product lists to be easily added to pages outside of the \storefront directory.  By encapsulating this functionality as user-controls, they want developers using this user control library to be able to easily add this functionality to any page on their site.

     

    One condition the developers have for this ecommerce UI library is that no code-behind or C#/VB source code is shipped with the library.  Instead, they want to be able to easily package it up and deploy all code as compiled .dll assemblies.

     

    For the purposes of the below walkthrough, I am going to assume that the development team building this web UI library wants to build-it as an isolated VS solution, separate from any web projects that might be consuming it (this seems to be the most common scenario I see when I talk with customers).  Note that you could also incorporate this library as part of a bigger solution that also contains web projects consuming it.

     

    Step 1: Define the Re-Usable Page/Control Web Solution and Directory Structure

     

    We want to cleanly encapsulate and maintain our ecommerce library solution.  To help with this I can use a straight-forward directory structure and VS solution architecture.

     

    Specifically, I’m going to define an “EcommerceUI” directory underneath a “libraries” sub-directory in my source tree.  Contained within this will then be 4 sub-directories: a “myclasslibraryproject” directory to encapsulate the non-code-behind pieces of my library within a class library project, a “mywebproject” directory to encapsulate the web UI pieces of my library using a web project, a “mytestproject” directory to encapsulate the functionality testing of my library using a new VSTS test project, and a “buildoutput” directory which I’ll use to build and ultimately publish this library into (more on this later).  In addition to these sub-directories, I will define and store a VS solution file called “EcommerceUI.sln” underneath the root EccomerceUI library directory that defines the solution structure and cross-project relationships.

     

    My resulting directory structure will look like this:

     

    C:\sources\libraries\EcommerceUI\

    C:\sources\libraries\EcommerceUI\EcommerceUI.sln

    C:\sources\libraries\EcommerceUI\myclasslibraryproject\

    C:\sources\libraries\EcommerceUI\mywebproject\

    C:\sources\libraries\EcommerceUI\mytestproject\

    C:\sources\libraries\EcommerceUI\buildoutput\

     

    Note that VS 2005 makes it much easier to manage and store web projects outside of your inetpub and wwwroot directories.  This makes it possible to easily store web projects side-by-side with companion projects as part of a solution (like above).  I can configure the above web project directory to run using either the built-in VS file-system based web-server or using IIS directly.  For this particular solution, because I am not using any sub-applications or vdirs, I am going to be using the built-in VS 2005 web-server – which will avoid me having to register anything with IIS.

     

    When I open up the solution defining the above projects using VS 2005, I will see a corresponding solution explorer view that looks like this:

     

     

    One last note: I obviously don’t recommend calling sub-directories “mywebproject” or “myclasslibraryproject” – I’m using those names here only to add clarity about what each directory does. 

     

    Step 2: Develop the Re-Usable Page/Control Web Solution

     

    Once the above library structure is in place, obviously the next thing to-do is write the code and build it.  For the web project, this typically involves building one or two top-level directories to encapsulate the pages and user-controls of the solution. 

     

    For our ecommerce solution I’m going to take the approach of defining a top-level directory called “storefront” that will encapsulate all of the content for our re-usable web project library.  Contained within the “storefront” directory will be the .aspx pages that make up our pre-built page functionality, as well as a “controls” sub-directory that will contain all of the .ascx user controls for the library.

     

     

    A couple of things to note in the above solution:

     

    1) In addition to the /storefront sub-directory above, I’ve added three test pages (testpage1.aspx, testpage2.aspx, testpage3.aspx) in the root of the web project.  I can use these for easily testing my library without having to first deploy it inside another web application.  I can also use these pages with the VSTS test project I have in my solution to host and then perform Web UI testing of the user-controls in the library (note: the VSTS edition of Visual Studio now includes a built-in web UI recorder that makes building ASP.NET UI unit testing easy).

     

    2) I have a “site.master” master page file defined in the root directory.  Master Pages are one of the big new features of ASP.NET, and allow developers to define a common layout across pages within their application.  I can structure my EcommerceUI library pages (underneath the /storefront directory) to use a master-page defined outside of /storefront – which would allow the web application that is taking advantage of the EcommerceUI library to integrate it within their overall web application look and feel without having to modify the .aspx pages contained within /storefront.  If I wanted to I could even compile away the HTML within these /storefront pages so that the application couldn’t modify these – and was limited to only changing the masterfile or using the new ASP.NET 2.0 themes feature to integrate it within the site (this can make versioning dramatically easier, and avoid messy merge-hell scenarios when upgrading or deploying a new version of the EccomerceUI library).  Because Master Pages can be specified both declaratively and programmatically, the EcommerceUI library could optionally allow developers using the library to configure the exact Master Page they should use and then dynamically select this one at runtime.

     

    3) I have a web.sitemap file defined underneath the /storefront directory.  Web.sitemap files are used by the new ASP.NET 2.0 Site Navigation system to define the logical scope and structure of a site layout.  Developers can then write code against the SiteMap API to get access to this structure and figure out where a visiting browser is within the site hierarchy at runtime, and/or can use some of the new built-in ASP.NET 2.0 UI controls like the Menu, Treeview and Breadcrumb Navigation controls to easily visualize it.  One of the cool things about the built-in XML Site Map Providers in ASP.NET 2.0 is that it allows you to partition the site definition across multiple files which can then be automatically merged into a single sitemap at runtime.  The web.sitemap file defined underneath the /storefront directory above would then contain only the site structure for the EcommerceUI library we are defining.  When added to a web application that had its own sitemap defined, the site structure we defined would be merged into that, and can show up in a menu defined on the Master Page of the entire site – without us having to-do a lot of extra work.

     

    4) One of the goals we tried to accomplish in ASP.NET V2.0 was to provide a much richer framework for building web applications, and to build-in “building-block application service APIs” that provide a common model and framework for accomplishing core things like Membership, Role Management, Profiles, Personalization, Health Monitoring, etc.  One of the nice things this provides is a consistent way for components, controls and libraries to integrate and work better together.  For example: in our EcommerceUI example we could have our library use the new ASP.NET 2.0 Membership, Role Management, and Profile APIs – and as a result have our /storefront section of the web app integrate nicely with the rest of the application if they are using the same APIs.  Because these APIs are pluggable via providers, it also means that we don’t loose flexibility as a result (read http://weblogs.asp.net/scottgu/archive/2005/08/25/423703.aspx for more on how providers work and how they can be configured).  The end-result should be much richer code-reuse and flexibility of libraries with ASP.NET 2.0.

     

    So what can’t I do within this web project library?

     

    You can pretty much use all the same designers, code-editors and features when building a re-usable web project library that you can with a normal standalone web application.  Because you’ll be shipping and re-using the library within other web applications, though, there are a couple of things you’ll need to avoid:

     

    -- Don’t define a global.asax file.  You are only allowed one of these per-application in ASP.NET, and so you don’t want to define one in your re-usable library.

     

    -- Don’t define classes under app_code or service proxies under app_webservices.  Like global.asax, there are one of these each per application.  Code-behind class files are obviously fine inside the web project library and typically live next to their .aspx/.ascx equivalents.  Non-UI and business classes for the web project library should be defined within a companion class library project in the solution (for example: the myclasslibraryproject above).

     

    -- Be careful about what you require in your root web.config file.  If possible, define applicationsettings and other configuration within the web.config file that lives underneath sub-directories (like /storefront above).  This will make re-using these web project libraries much easier and avoid having to write a setup program that does custom merge semantics.

     

    Step 3: Building and Deploying the Re-Usable Page/Control Web Solution

     

    Once you’ve built and tested your web project library, it is time to build and deploy it for re-use in other web projects.  There are a lot of new compilation and deployment options introduced by ASP.NET 2.0 and VS 2005.  In particular, there are two big new decisions that developers can now make:

     

    Decision #1) Whether to preserve the HTML + Server Control markup when deploying a web project (which is what VS 2003 does today), or whether this should be removed as part of the compilation process and compiled directly into the generated \bin assemblies.  The benefit with the first approach (preserving the html) is that it allows later modification of the markup without having to re-build the project (hence the reason we call this the “updatable” build option in dialogs you’ll see below).  The benefit with the later approach (compiling the mark-up out) is that it allows ASP.NET to avoid having to ever parse and compile the .aspx file at runtime – which can dramatically improve the first-load/first-request performance of the application.  It also allows ISVs to better protect their intellectual property and hide their HTML and server control definitions.

     

    Decision #2) How granular the deployed assemblies should be.  Specifically, VS 2005 + ASP.NET 2.0 now by default compiles your web project so that each separate directory of .aspx/.ascx content compiles into a separate assembly.  For even more flexibility, you can also optionally choose to compile each .aspx or .ascx file into its own separate assembly (this option is called the “fixed name” option because it also results in assemblies whose names are fixed across multiple compilations).  The benefit with this later approach is that you can now deploy individual updates on your system without having to re-build and update your entire site.  It can also sometimes make deploying web project libraries much easier – because it allows you to copy and deploy just those .ascx user controls and associated assemblies that you want out of the web project, without having to grab everything.

     

    Note: one request we’ve heard from several people since Beta2 has been to provide a new third compilation granularity option above which would allow you to merge the assembly output from multiple directories into a single assembly that has a well known name that you define (and which does not change across re-builds – which is one unfortunate side-affect of the per-directory build option today).  We are working on a tool right now that does this, and have a prototype up and running that seems to work great.  I’ll provide more details on this over the next week or two once we confirm that it fully works for all scenarios.

     

    There are two ways I can easily build and deploy my solution: a) from within the VS IDE, or b) from the command-line using MSBuild.

     

    Building and Deploying the Web Project Library from the VS IDE

     

    To build and publish/deploy my web library solution within the Visual Studio IDE, I can go to the “Build” menu and select the “Publish Web Site” option.  This will bring up the “Publish Web Site” build dialog which provides me with the various deployment/compilation options on how to build the site:

     

     

    For this walkthrough I am going to use the default “updatable” option (meaning the HTML + Server control markup is preserved), and select to have individual assemblies created for my .ascx and .aspx files.  The reason for selecting the individual assembly option is because I want to be able to remove the compiled code for the root test pages and master templates that I am currently using to test my store-front library, and want to have the flexibility to update these assemblies on a more granular level in the future. 

     

    Note: For simplicity sake in this walkthrough I’m going to only describe one deployment combination (specifically I’ll use updatable html + individual compiled assemblies).  I could have just as easily picked another (for example: fully compiled html + per-directory assemblies).  You as a developer are allowed to pick whatever you feel is most appropriate for your particular web library deployment scenario.

     

    When I click the “ok” button, VS 2005 will compile all three projects (myclasslibrary, mywebproject, mytestproject) and then deploy the classlibrary and webproject into the “BuildOutput” directory we defined earlier under our c:\sources\libraries\ecommerceUI\ directory.

     

     

    Note that the .aspx/.ascx files will remain (because they still have .html/server control content defined within them), but all code-behind files are now gone – since they have been compiled into assemblies underneath the \bin directory.

     

    Building and Deploying the Web Project Library from the VS IDE

     

    To build and publish/deploy my web library solution from the command-line (without having the VS IDE loaded or potentially even installed on my machine), I can take advantage of the new MSBuild support that ships with VS 2005 and .NET 2.0.  There is *a lot* of richness in MSBuild – easily 20+ blog entries worth.  I’m going to only show a super basic (but still pretty useful) way to use it below with web projects.  I’ll blog some more about it in the future to go into some of the more advanced ways you can use it with web projects.

     

    To configure basic MSBuild options with my web project library solution, I can right-click on my web project in the solution explorer and select the “Properties” menu item on the context menu.  This will bring up a configuration dialog for the web project, and allows me to configure lots of different things (start pages, references, accessibility compliance checker, etc).  If I click on the MSBuild tab I will see the below options:

     

     

    Once I have configured the MSBuild options this way, and hit “save all” to make sure the solution is up-to-date (note: I always forget to-do this), I can now perform command line builds on my solution.

     

    MSBuild.exe is installed underneath the framework redist directory (c:\windows\microsoft.net\framework\v2.0.xyz).  If this was on my command-line path, then I could simply type the below command to kick off a command-line build:

     

     

    This would then generate the below console output and produce the exact same bits we did before using the IDE:

     

     

    Obviously this is a very simple command line build scenario – but I could compose additional MSBuild rules to make this much richer (including adding additional steps to copy the appropriate files from the produced library into multiple projects).  MSBuild has a custom task called “AspNetCompiler” that can also be used to declaratively author custom MSBuild scripts from scratch.

     

    Step 4: Using the Page/Control Web Library within a Web Application

     

    To use the EcomerceUI library we just created inside a new web application in VS 2005, I need to-do two things:

     

    1) Copy the appropriate .aspx/.ascx files from the built EcommerceUI solution into my new web application project directory.

     

    2) Copy the appropriate .dll assemblies from the built EcommerceUI solution into my new web application project’s \bin directory (note: I could either copy these manually or as part of an automated build process, or have a CopyLocal reference setup to auto-refresh these assemblies when new versions get built and deployed under the EcommerceUI solution).

     

    Here is what my blank web-application will look like when I copy the above items into it:

     

     

    Note that because I’ve built using the option to generate separate assemblies for each control/page, I end up having several granular assemblies in my \bin directory.  Note also that this allowed me to remove all of the testpage assemblies I was using within the web project to verify things.

     

    I can then go ahead and build my web project and take advantage of the Ecommerce UI library.  I can add whatever pages I want into the project and integrate them around the /storefront subdirectory.  I can also use the user controls from /storefront/controls on any page within the site.

     

    Here are two screen-shots of this in action with VS 2005:

     

     

    Note in the above screen-shot how the catalog page we defined within the EcommerceUI library picks up and integrates within the custom Site.Master masterpage file we defined at the root level within this new web project.  It shows up both in WYSIWYG in VS 2005, and obviously also at runtime.

     

    Also note the treeview control on the left that is defined within the master page in our new web project as well as the bread-crumb control that is defined within the catalog.aspx page of the EcommerceUI library.  Both of these new ASP.NET 2.0 controls are binding against the new ASP.NET Site Navigation system – and are showing a consistent site hierarchy view of the overall web solution regardless of whether they were used inside the storefront or outside of it.  This view shows up consistently both at runtime and also at design-time in VS 2005.

     

     

    Note in the above screen-shot how the wishlist.ascx user-control from the /storefront/controls directory shows up in WYSIWYG on the default.aspx homepage defined at the web project root.  With previous versions of VS user-controls were rendered as grey-boxes – now developers using the ECommerceUI library will be able to see the actual representation of the user control content they’ll see at runtime.  VS 2005 also now provides strong-typing and intellisense against the usercontrols when writing code-behind code for default.aspx (previous versions of VS declared these controls by default as type-less usercontrols). 

     

    Note that as I’m building my new web project I can regularly run (just do a standard F5 or Ctrl-F5 to run the web project).  When I’m finished I can also then do a “Publish Web” or command-line build operation on this new web project and solution, and generate a completed web application with EcommerceUI library included that is ready to deploy.

     

    Hope this helps,

     

    Scott

  • Some techniques for better managing files in VS 2005 Web Projects

    I’ve seen several questions come up in the last few days regarding techniques for structuring project layouts with web projects in VS 2005.  In particular, I’ve received several good questions asking for ways to manage large image directories as well as temporary storage directories underneath web project roots.  One goal with both questions has been to find ways to avoid these files from showing up in the VS web project solution explorer and cluttering up the web project view, as well as to avoid having these files/directories be prompted to be added to source control during check-in (note: you can just unclick having these files added to source control – but having to-do so can be a pain). 

     

    This blog post covers some techniques for handling scenarios like these.  Prior to reading further, I’d strongly recommend you read my previous post on managing IIS web projects with VS 2005: http://weblogs.asp.net/scottgu/archive/2005/08/23/423409.aspx.  The section on virtual directory mappings and how they are treated will be particularly pertinent to some of the techniques below. 

     

    Note that the final release of VS 2005 will have “Exclude File from Build” support to allow you to exclude/include code from being part of a build or publishing operation.  The below techniques are about going one step deeper and having files disappear entirely from the solution explorer, as well as to discuss techniques for sharing common directories across multiple projects.

     

    Scenario #1: How to manage a 5,000 item /images directory in a web project

     

    A really good scenario that someone sent my way today was one where they currently have an ecommerce solution that has a 5,000 item product catalog.  As part of their solution they have an “images” subdirectory underneath their web root that stores an image for each of the 5,000 products on disk. 

     

    When they open up their web project using VS 2005 they are worried about having two problems:

     

    1) They will have a 5,000 picture sub-directory in their heavily developed web project which will add clutter and slow down open/copy operations.

     

    2) Managing this directory with source control will be a real pain – when you check-in or check-out of Visual Source Safe it will verify that these files haven’t changed or have been added to source control which can really take awhile.  Ideally there would be someway to manage these image files elsewhere.

     

    A technique to make this experience much better:

     

    For scenarios like these involving directory resources, one technique that you can easily use to better manage these items in web projects is to mark these directories as “virtual directories” in IIS.  This does not require any code-changes – it is purely a configuration setting you can manage via IIS.

     

    Making these directories “virtual directories” provides four big benefits:

     

    Benefit #1: Sub-directories marked as “virtual directories” in IIS will automatically be excluded from showing up in a VS 2005 web project.  A marker node will still remain in the solution tree to indicate that a virtual sub-directory is present, but no files or sub-directories will be added – and the virtual directory and all of its contents will be excluded from all source control and publish deployment operations.

     

    For example, the below images show the difference when the “images” subdirectory is marked as a normal directory:

     

     

    And here is the same web project again when the “images” directory is marked as a “virtual directory” in IIS.  Note that there is still an “images” node in the hierarchy to denote the presence of a virtual sub-directory – but no content is included underneath it:

     

     

    Note that the content of the virtual-directory will be automatically excluded from all deployment operations, and will not be included in the source control for the web project (even in cases where the "images" virtual directory is physically stored underneath the web project on disk).

     

    Benefit #2: You can now store these directories anywhere on disk.  If you want, you can continue to store them physically underneath the same web app or site directory.  You can also then optionally store them elsewhere on disk.  This can make some deployment scenarios much easier – since you can now manage these directory trees separately and update and deploy their roots independently.  Note that virtual directory views within the solution explorer will be the same regardless of whether the physical images subdirectory is under the project directory or stored elsewhere – it is completely transparent to the active project.

     

    Benefit #3: You can have multiple web projects share the same virtual directories.  This can be a very useful and powerful technique when you have shared images, CSS or script libraries that you want to re-use across multiple web sites or web applications (for example: www.site1.com, www.site2.com, www.site3.com, etc).  One of the cool new features in the VS 2005 WYSIWYG designer is that it will follow virtual directory paths and load images, CSS files and scripts correctly even when they are stored in virtual directories.

     

    For example: consider a scenario where you are building 3 different sites or applications where you want to share a common CSS design, and common corporate logo images.  You could lay out your application structure like this if you wanted to:

     

    C:\CommonVDir\Images

    C:\CommonVDir\CSS

    C:\CommonVDir\Javascript

     

    C:\Sites\www.site1.com

    C:\Sites\www.site2.com

    C:\Sites\www.site3.com

     

    You could then map a virtual directory underneath each site to point to the “CommonVDir” shared library directory.  Not only will this work at runtime, but when you create a new page underneath the www.site1.com web project and reference the “commonvdir/css/style.css” stylesheet – the VS 2005 web designer will automatically pick up the styles and show things correctly in design-view, even though the actual stylesheet is never checked in or managed in the www.site1.com web project.

     

    When you update a single CSS stylesheet under the c:\CommonVDir\CSS directory, it will immediately show updated in all 3 of the sites -- both at runtime and design-time.

     

    Benefit #4: You can optionally create additional web projects to manage your various virtual directories.  This allows you to manage these separate virtual folders using their own development/design team, web project and source control settings.  For example, the below screenshot shows one solution with both the web application open, as well as a second and third web project open to manage the “images” and “styles” virtual directories as separate isolated projects (which could be checked-in separately under source control):

     

     

    Scenario #2: How to dynamically generate and handle temp files in a web project

     

    Another scenario that a few people have asked about is one where they are dynamically generating XML files underneath their web project at runtime, and they want to avoid having these files appear in their solution explorer and source control, and avoid having them be deployed by Visual Studio’s “Publish Web” feature. 

     

    A technique to make this experience much better:

     

    For temporary file storage that is dynamically generated underneath a web-project or web-root, you might want to consider using hidden folders. 

     

    There are two benefits of this approach:

     

    Benefit #1: Hidden files and folders are automatically excluded from the web project view under solution explorer, and will be excluded from all source control operations. 

     

    For example, here is an example web project with a “tempstorage” directory containing XML files:

     

     

    Here is the same web project except that the “tempstorage” directory has now been marked with a “hidden” bit:

     

     

    Benefit #2: IIS will by default block requests for content stored in hidden folders.  This can be a useful security check to help prevent temporary files from accidentally getting downloaded by unauthorized users. 

     

    The below two lines of sample code demonstrate how to dynamically create a new temporary directory, and then mark it as hidden using the System.IO namespace:

     

            Directory.CreateDirectory("tempstorage");

            File.SetAttributes("tempstorage", FileAttributes.Hidden);

     

    You can also obviously just create the folder on the file-system yourself using Windows explorer, pull up its properties window, and click the "hidden" attribute too.

     

    Note that whether a folder is hidden or not will not change any code or logic when accessing/writing files underneath it. 

     

    Important Note: For maximum security, I would always recommend that you not grant any write access to the directory underneath a web project or application root.  If you need to store temporary files somewhere, it is far more secure to store them in a totally non-accessible location.  I’ve only included the above section on temporary storage because several people have asked about it.

     

    Scenario #3: How to store non-deployed files in web projects

     

    A final scenario a few people have asked me about is how they might be able to store files within web projects and under source control that can be used during development time (for example: design-docs written in word or visio, or adobe photoshop .psd files for layered images), but will be automatically excluded from any deployment or publishing steps. 

     

    A technique to make this experience much better:

     

    ASP.NET 2.0 supports a concept of “build providers”.  These are classes that implement the System.Web.Compilation.BuildProvider base class contract, and which can participate in build-operations both in VS 2005 at development-time and ASP.NET at runtime.  Developers are free to build and implement their own BuildProviders to add their own custom semantics to processing files within ASP.NET.  For example: you could create an .ORM file extension for files that contained XML to declaratively represent an OR mapping database relationship.  Your provider could then dynamically generate strongly-typed classes that were included in the web anytime one of these files was added to the project – and you would get both intellisense within VS 2005 at design-time as well as full runtime support.

     

    One of the built-in build providers in ASP.NET 2.0 is a provider called the “IgnoreFileBuildProvider”.  Its semantics are that it ignores whatever file extension is mapped to it, and that it will also automatically prevent that file from being deployed during a publish-web or compilation operation.

     

    Developers can then use this feature to add extensions to the web.config file in their local web projects and effectively block any file-type they want from being deployed by VS.  For example, if I wanted to prevent all .doc (word), .psd (photoshop) and .vsd (visio) files from ever being deployed, I would add the following section to my web.config file:

     

    <configuration>

      <system.web>

         <compilation>

          <buildProviders>
             <add extension=".doc" type="System.Web.Compilation.IgnoreFileBuildProvider" />
             <add extension=".psd" type="System.Web.Compilation.IgnoreFileBuildProvider" />

             <add extension=".vsd" type="System.Web.Compilation.IgnoreFileBuildProvider" />
          </buildProviders>

         </compilation>

       </system.web>

    </configuration>

     

    I am then free to add and check-in these file types anywhere in my project if I so wanted to – and they can be used/modified/accessed throughout the development lifecycle – but will be excluded anytime a build is produced.

     

    Hopefully this helps show some useful techniques you can leverage.

     

    - Scott

  • Configuring ASP.NET 2.0 Application Services to use SQL Server 2000 or SQL Server 2005

    One question I’ve seen asked a few times by people over the last few weeks is “how do I setup the new ASP.NET Membership, Role Management, and Personalization services to use a regular SQL Server instead of SQL Express?” This blog entry walks you though a few simple steps on how to-do this.

     

    Quick Review: What are the new ASP.NET 2.0 Application Services?

     

    ASP.NET 2.0 includes a number of built-in “building block” application services.  We call them “building blocks” because they are useful core frameworks for enabling super-common scenarios with web applications today – and as a result can provide significant productivity wins and time-savings for developers.

     

    They include: a membership API for managing usernames/passwords and secure credential management, a roles API that supports mapping users into logical groups, a profile API for storing arbitrary properties about both authenticated and anonymous users visiting a web site (for example: their zipcode, gender, theme preference, etc), a personalization API for storing control customization preferences (this is most often used with the WebPart features in ASP.NET 2.0), a health monitoring API that can track and collect information about the running state and any errors that occur within a web application, and a site navigation API for defining hierarchy within an application and constructing navigation UI (menus, treeviews, bread-crumbs) that can be context specific based on where the current incoming user is in the site.

     

    The ASP.NET Application Service APIs are designed to be pluggable and implementation agnostic, which means that the APIs do not hardcode the details of where data is stored with them.  Instead, the APIs call into “providers”, which are classes that implement a specific “provider contract” – which is defined as an abstract class with a defined set of methods/properties that the API expects to be implemented.

     

    ASP.NET 2.0 ships with a number of built-in providers including: a SQL Express provider for going against local SQL Express Databases, SQL 2000/2005 providers that work against full-blown SQL Servers, an Active Directory Provider that can go against AD or ADAM implementations, and in the case of site navigation an XML provider that can bind against XML files on the file-system.

     

    The beauty of the model is that if you don’t like the existing providers that ship in the box, or want to integrate these APIs against existing data-stores you are already using, then you can just implement a provider and plug it in.  For example: you might already have an existing database storing usernames/passwords, or an existing LDAP system you need to integrate with.  Just implement the MembershipProvider contract as a class and register it in your application’s web.config file (details below), and all calls to the Membership API in ASP.NET will delegate to your code.

     

    Default SQL Express Providers

     

    Out of the box, most of the ASP.NET 2.0 application services are configured to use the built-in SQL Express provider.  This provider will automatically create and provision a new database for you the first time you use one of these application services, and provides a pretty easy way to get started without a lot of setup hassles (just have SQL Express on the box and you are good to go).  Note that SQL Express databases can also be upgraded to run in the context of full-blown SQL Server instances – so apps built using SQL Express for development can easily be upgraded into a high-volume, clustered, fail-over secure 8P SQL box when your app becomes wildly successful.

     

    How do I change the providers to use SQL Server Instead of SQL Express?

     

    If you want to use a full-blown SQL Server 2000 or SQL Server 2005 database instance instead of SQL Express, you can follow the below steps:

     

    Step 1: Create or obtain a blank SQL database instance

     

    In this step you’ll want to create or obtain a connection string to a standard SQL database instance that is empty.

     

    Step 2: Provision your SQL database with the ASP.NET schemas

     

    Open a command-line window on your system and run the aspnet_regsql.exe utility that is installed with ASP.NET 2.0 in under your C:\WINDOWS\Microsoft.NET\Framework\v2.0.xyz directory. 

     

    Note that this utility can be run in either a GUI based mode or with command-line switches (just add a -? flag to see all switch options).

     

    Using this wizard you can walkthrough creating the schema, tables and sprocs for the built-in SQL providers that come with ASP.NET 2.0.  The below screens show the step-by-step walkthrough of this:

     











     

    Once you have finished walking through the wizard, all the database schema + sprocs to support the application services will have been installed and configured (note: if your DBA wants to see exactly what is going on behind the covers, we also ship the raw .sql files underneath the above framework directory, and your DBA can walkthrough them and/or run them manually to install the DB).

     

    Step 3: Point your web.config file at the new SQL Database

     

    ASP.NET 2.0 now supports a new section in your web.config file called “<connectionStrings>” which (not too surprisingly) are used to store connection strings.  One nice thing from an administration perspective is that the new ASP.NET Admin MMC Snap-in now provides a GUI based way to configure and manage these:





    ASP.NET 2.0 also now supports encrypting any section stored in web.config files -- so you can also now securely store private data like connectionstrings without having to write any encryption code of your own. 

     

    ASP.NET 2.0 ships with a built-in connection string called “LocalSqlServer” which by default is configured to use a SQL Express database, and which by default the Membership, Roles, Personalization, Profile and Health Monitoring services are configured to use.

     

    The easiest way to have your application automatically take advantage of your newly created SQL database is to just replace the connectionstring value of this “LocalSqlServer” setting in your app’s local web.config.

     

    For example, if I created my database on the local machine in an “appservicesdb” database instance and was connecting using Windows Integrated security, I would change my local web.config file to specify this:

     

    <configuration>

     

        <connectionStrings>

            <remove name=”LocalSqlServer”/>

            <add name="LocalSqlServer" connectionString="Data Source=localhost;Initial Catalog=appservicesdb;Integrated Security=True" providerName="System.Data.SqlClient"/>

        </connectionStrings>

     

    </configuration>

     

    Hit save, and all of the built-in application services are now using your newly created and defined SQL Server database.

     

    Note: The one downside with the above approach is that I’m re-using the “LocalSqlServer” connection string name – which will feel weird if/when I deploy my database on another machine.  If I wanted to name it with my own connection string name, I could do this simply by adding a completely new connection-string, and then pointing the existing providers to use the new connection-string name in place of the default LocalSqlServer one. 

     

    Hope this helps,

     

    Scott

     

    P.S. In some future blog post I’ll walkthrough actually using some of the above new APIs.

  • Using IIS with VS 2005 and the new Web Project system

    A number of people have asked me questions through my blog over the last few days about how VS 2005 uses and handles IIS (especially in cases of nested applications and virtual directories).  This blog entry provides more information on how this works, and hopefully clears up a few questions people might have.

     

    Quick Review: How does IIS map applications and sites?

     

    IIS supports hosting multiple “sites” on a server.  These sites are defined as a unique IP address, hostname, and/or port address combination.  For example: my site www.scottgu.com is a site with an IP address (192.197.157.24) a hostname “www.scottgu.com” and a port number of 80 (the default http port). Nikhil’s site (www.nikhilk.net) is also another site on the exact same web server machine.  It has the same IP address (192.197.157.24) and port number (80) as my site, but has a different hostname binding.  As long as one of these three things (IP address, hostname, port number) is different, each site can be differentiated and mapped separately on IIS.

     

    When you register a site with IIS, you specify a parent directory for the default site content to live under.  When IIS is installed the “default site” is typically mapped to the c:\inetpub\wwwroot\ directory.  If you place a test.htm file immediately underneath this directory and access http://localhost/test.htm you will retrieve the file from the web-server.  You can have any number of physical directories and sub-directories you want underneath a site root.

     

    IIS also supports the concept of “virtual directories” (commonly called "vdirs") under sites, which are logical directories from a url namespace perspective, but which do not have to be backed by a physical directory with the same name or location on disk.  For example, I could create a directory called “app1” that maps to c:\inetpub\app1 which contains a “test2.htm” file and create a “virtual directory” in IIS that mapped it underneath the default site. 

     

    When I do this and request the below urls, the web-server will fetch these files:

     

    http://localhost/test.htm -> c:\inetpub\wwwroot\test.htm

    http://localhost/app1/test2.htm -> c:\inetpub\app1\test2.htm

     

    Note that wwwroot and app1 are peer directories in this case.  Even though the logical url structure has “app1” underneath the root website, there is no requirement to physically structure the files this way (although I could if I wanted to).

     

    IIS also then supports the concept of “applications” on servers.  These are the same as virtual directories except that they have some extra metadata stored in the IIS metabase configuration store associated with them.  With IIS6 they also support the ability for administrators to map them to be handled in different application pools (which are our worker processes) for greater reliability and process isolation. 

     

    IIS “applications” can map to physical directories mapped underneath the site root, or to directories outside of the site root.  They can also be nested multiple layers deep. 

     

    For example:

     

    http://www.testsite.com/ -> c:\www.testsite.com\wwwroot (the “root site” app)

    http://www.testsite.com/app1 -> c:\www.testsite.com\app1

    http://www.testsite.com/app2 -> c:\www.testsite.com\app2

    http://www.testsite.com/app3 -> c:\www.testsite.com\wwwroot\app3

    http://www.testsite.com/app3/app4 -> c:\www.testsite.com\wwwroot\app3\app4

     

    Note in this sample the root application (http://www.testsite.com/) and app1 (http://www.testsite.com/app1) and app2 (http://www.testsite.com/app2) are peer directories in the physical file-system hierarchy.  App3 and App4 are then physically stored underneath the wwwroot directory (with app4 actually being nested under app3).  The key thing to remember is that it is the IIS bindings, and not the file-system, which determines application scopes and boundaries – an administrator can configure things however they want.

     

    In the IIS Admin Tool, the above mapping structure would look like this:

     

     

    Note: Just to confuse things, when you use the IIS admin tool and right-click and choose “Create Virtual Directory” underneath a site, you are actually really creating an “application” (specifically: a virtual directory that has the app meta-data set).  If you want it to really be a vanilla virtual directory with no app semantics, you should open up the property pages on the newly created application and click the “remove” button under the virtual directory tab.  This actually doesn’t delete the virtual directory – it just removes the app meta-data and de-promotes it to be a normal virtual directory.  And no – this isn’t very logical or intuitive…

     

    What does ASP.NET do with applications?

     

    ASP.NET uses the IIS application meta-data flag (stored in the IIS metabase configuration system) to identify application boundaries, and applies special semantics to content hosted within them.  Specifically, when a directory is marked as an application ASP.NET does a few things:

     

    1) It allows a \bin directory to be defined and used immediately underneath the application root directory to resolve assembly references. 

     

    2) It allows “application-level” settings like authentication to be configured and set in a web.config configuration file.

     

    3) It allows a “global.asax” file to be defined to handle global “application level” events (like application_start, and module specific events like session_start/end). 

     

    4) In ASP.NET V2.0 it also allows additional directories to be created underneath the app root to handle things like data providers, class library compilation, application resource files, etc.

     

    ASP.NET then creates a CLR app-domain for all code running in the context of an application.  This app-domain is where code-loading policy is set (and how the assembly loader is hooked up to a \bin directory), and how additional code-access security permissions can be applied. 

     

    Using the above www.testsite.com application bindings as an example, this would mean that the \bin directory locations with the above apps could live in these physical locations:

     

    c:\www.testsite.com\wwwroot\bin

    c:\www.testsite.com\app1\bin

    c:\www.testsite.com\app2\bin

    c:\www.testsite.com\wwwroot\app3\bin

    c:\www.testsite.com\wwwroot\app3\app4\bin

     

    Code living underneath the \app1 directory would use \app1\bin to load compiled assemblies. 

     

    Code living underneath the \wwwroot\app3 directory would use the \wwwroot\app3\bin directory to load compiled assemblies. 

     

    Code living underneath the \wwwroot directory – but not under the \wwwroot\app3 directory – would use the \wwwroot\bin directory to load compiled assemblies. 

     

    Note that these assembly loading semantics are identical with ASP.NET V1, V1.1 and V2.0.

     

    How Do You Open a Web Applications with VS 2005?

     

    VS 2005 supports multiple ways to open and edit ASP.NET Applications.  Out of the box its “Open Web Site” dialog (invoked when you create or open a new web project) has four tabs – one to open web projects directly off the file-system (just point to the app’s root directory and go), by browsing IIS directly, by entering FTP credentials to open a site remotely, and by using FrontPage Server Extensions (note: I've circled the 4 tabs in the screenshot below).

     

     

    The file-system tab option is great if you are working on a self-contained web project that requires no knowledge of the directory or URL structure of content outside its structure. 

     

    However, if you are using multiple nested IIS applications or special IIS virtual directory rules on your web server to coordinate multiple applications, then you should avoid opening up these projects using the file-system web option – and instead open them using the “Local IIS” or “Remote Site” tab options.  The reason for this is because these nesting and relationship rules are stored in the IIS metabase, and for your application to properly run you will want/need these IIS bindings and semantics to be handled both at runtime and inside VS 2005. 

     

    If you are coming from VS 2003 you are probably used to opening up web-sites with FrontPage Server Extensions and using a known URL.  To-do this with VS 2005, just follow the following steps:

     

    1) Select File->Open Website off the file menu

    2) Select the “Remote Site” tab on the “Open Web Site” dialog (see below)

    3) Enter the name of the app you want to open to edit (example: http://localhost/app1)

     

     

    Alternatively, you can also now browse, create and open web sites and applications configured on your local IIS server by using the “Local IIS” tab new in VS 2005.  This does not require FrontPage Server Extensions to be installed on the web-server (hooray), and also provides a much richer tree-view of what the sites, applications and virtual directories look like on your web-server.  To use this with VS 2005, just follow the following steps:

     

    1) Select File->Open Website off the file menu

    2) Select the “Local IIS” tab on the “Open Web Site” dialog (see below)

    3) Drill down and pick the appropriate sites/application to open

     

     

    Note that – just like today – you can absolutely use both a root web-site application (for example: in the above dialog just click on www.testsite.com) as well as nested sub-application (for example: in the above dialog just click on www.testsite.com/app1).

     

    Working with an IIS Web Application in VS 2005

     

    Several people have asked what happens when you open up a website that has multiple nested sub-applications underneath it.  For example: you open up www.testsite.com (the root application), which contains three immediate sub-applications (www.testsite.com/app1, www.testsite.com/app2, and www.testsite.com/app3).  One of the questions/concerns people have asked is whether VS 2005 now merges the directory structure of all of these apps together into a single directory structure model – which would obviously really screw up building applications and projects (since the \bin directory and application semantics should be different between all 4 of these apps).

     

    The good news is that VS 2005 does the right thing and preserves the application scoping correctly.  Specifically, when you open up the www.testsite.com application using the bindings we specified above, you will get a project view that looks like this:

     

     

    The only files and folders included in the solution explorer are those within the root www.testsite.com application, and any non-application sub-folders it contains (for example in the above case “subdirectory1” and “subdirectory2”).  When you perform a build or compile within VS 2005 only those files contained within the www.testsite.com application (and not any sub-applications) will get compiled.  When you build and deploy a web project using the “Publish” menu item, you will only deploy those files in the www.testsite.com root application (and not any sub-applications).  These are the same isolation semantics as used in VS 2003.

     

    One nice addition we have made to the solution explorer in VS 2005 is to have special icons for nested sub-applications show up in a root application’s web project view (you can see these in the screen-shot above with the app1, app2, and app3 special icons).  These are intended to let a developer know that there are sub-applications at this point in their logical web-space, but not get in the developer’s way.  These do not have any build semantics (they are completely excluded just like VS 2003 from compilation operations), and you can not expand them to get to their web-content.  They are simply designed to let you know a sub-application is there and to help you get context on the broader web structure.

     

    Note also that in the above example “app3” happens to be mapped to a physical directory (c:\www.testsite.com\wwwroot\app3) directly underneath the root www.testsite.com application (c:\www.testsite.com\wwwroot\).  However, because it is marked as an application in IIS, VS 2005 will automatically exclude it from the www.testsite.com project and all compilation (same semantics as VS 2003).  Subdirectory1 and Subdirectory2 are not marked as applications in IIS, which is why they show up as part of the www.testsite.com application (again – same semantics as VS 2003).

     

    One other nice workflow feature added in VS 2005 is that you can double-click on these sub-application icons.  When you do this you will get a dialog pop-up that will prompt you to either open this web application (and replace the current open solution) or to add this web application to your current opened solution:

     

     

    For example, if I choose “add the web site to the current solution” when I clicked the “app3” icon in the solution explorer, I would end up with two separate isolated web projects in my solution:

     

     

    Note app3 is physically underneath the wwwroot application’s directory on the physical disk – but like VS 2003 I get an isolated view of each application, and each application can be built and deployed separately.

     

    Strategies for Web Project Management with IIS and VS 2005

     

    You can use the same solution patterns you used with VS 2003 to manage sub applications with VS 2005.  Typically for nested sub-applications we see developers create a separate solution for each application – which typically contains a web project, as well as one or more class library projects.  For example, in the below sample I’ve added a data access layer (DAL) and business logic layer (BLL) into a solution that contains my www.testsite.com root application.

     

     

    I can then setup cross project references and build dependencies the same way I do today:

     

     

    I can then save out my solution file which encapsulates all of these cross-project relationships to disk (just like VS 2003 does today).  When I open it again in VS I will load the solution with the same settings as I left it before, and all three of my projects will open.

     

    When I use the “Publish Web” option inside the IDE, it will compile the DAL project, then the BLL project, then compile the web project – and deploy the resulting binaries from all three compilations in the deployment directory I specify.

     

    Versioning Applications using ASP.NET 2.0

     

    One last thing to mention on the topic of IIS and ASP.NET 2.0 is versioning.  Specifically, the .NET Framework and VS fully support side-by-side with the .NET 2.0 and VS 2005 releases.  This means you can have VS 2003 and VS 2005 installed together on the same machine, and use VS 2003 for some projects and VS 2005 for others. 

     

    It also means that you can choose to have some ASP.NET applications on your web-server use ASP.NET V1.1, and others run using ASP.NET V2.0.  This later support is particularly interesting – as it allows you to incrementally switch over your systems to use the new features on your schedule, and does not force an “all or nothing” move.  By default when you install ASP.NET 2.0 on a machine that has ASP.NET V1.1 already installed, we do not automatically upgrade these apps to use the new version.  Instead, administrators get to choose which app uses which version.  Note that this fully works with sub-application solutions -- where for example you could migrate the www.testsite.com/app1 application to V2 while keeping www.testsite.com/app2 on V1.1 and migrate it on a different schedule.

     

    One way we’ve tried to make version switching easier is by adding support for it to the IIS admin tool under the new “ASP.NET” tab that gets installed when ASP.NET 2.0 is on the box.  You can pull up this tab now on any IIS application, and choose which version of ASP.NET you want to run using a version drop-down that will list all versions of ASP.NET installed on the system.  Simply pick a version, hit the apply button, and you’ve configured that app to run using it. 

     

     

    No more messing around with ISAPI script-mappings required.

     

    Summary

     

    Hopefully this provides a quick summary of how you build and manage web applications using IIS with VS 2005.  If you are using VS 2003 you should find the steps pretty familiar – although hopefully the workflow is a little faster and easier that before.

     

    Let me know if this makes sense or if you have any questions.

     

    Thanks,

     

    Scott

     

     

  • VS 2005 Web Project System: What is it and why did we do it?

    There has been a lot of online discussion lately about the new web project system that is being introduced with VS 2005.  My goal with this post is to explain a little more about what it is, and provide some background as to the features it provides and the motivation we had in introducing it.

    What are Web Projects?

    Web Projects are used when building ASP.NET applications inside Visual Studio 2005.  They can be used either standalone where everything within an application lives inside a single project, or together with class library, data, web-service, unit-test and/or any other project supported by Visual Studio as part of a Solution.  They fully support references and project build-ordering within a VS solution -- you set these up and manage these cross-project relationships using a .sln solution file just like you to-do today with VS 2003 (for example: you might have 3-4 class library projects that build class library assemblies that are then consumed and used by the web project).

    When you are ready to “publish” a web-solution, you can use the new “Publish” option on the “Build” menu to compile and generate a deployable directory structure for a web-server.  This is logically equivalent to the user workflow steps taken with a WinForms client application project in VS2005 (except its Publish option generates a client “Click-Once” package instead of web site).  You can also automate web project build operations using the new MSBuild system (more on this later) for command-line and automated build server scenarios.

    So What Are The New Features with VS 2005 Web Projects?

    The new VS 2005 web project support provides a number of new feature enhancements over VS 2002 and VS 2003.  A few of the big improvements that we think developers will like:

    No More FrontPage Server Extension Requirement

    Unlike previous releases of Visual Studio, VS 2005 no longer requires developers to use or have FPSE (FrontPage Server Extensions) installed in order to create or build web projects.

    You can now browse, create, and open local IIS applications and vdirs without FPSE on the box (instead we now have support for VS 2005 to directly use the IIS Metabase configuration store to attach and identify sites/apps/vdirs and associated physical path bindings).  You can also edit and open web projects directly off of the file-system, or access them remotely over FTP.

    FPSE is still fully supported for those who want it.  But if you are in the camp that doesn’t want it (which based on feedback is 95%+ of you), your _vti_ directories will be a thing of the past.

    Built-in Development Web Server (No IIS Requirement &  Debug as Normal User)

    In addition to providing full support for developing and testing web projects on IIS, VS 2005 also includes a built-in development web-server that ships in the box.  This test web-server is ideal for doing development when IIS is either not installed, or your IT policy limits desktop deployment of it.

    This web-server only handles local requests for security reasons (so people can’t access your application remotely while you are developing it), and it automatically shuts down when you close your web-projects.  It also supports developers debugging applications running within it while running under a non-admin “normal user” account.  Once you’ve built your application using it, you can then upgrade the web to either run under IIS locally or deploy the application to a remote server to test and verify.  There is also now a new built-in “Copy Web” wizard that can help with copying your web to a remote server (it supports FTP and FPSE as copying protocols too).

    Obviously we also fully support building web projects against IIS directly (note: this is required when you are building a solution with nested vdirs and sub-applications).

    More Flexible File Management and Better Cross-Tool Collaboration Support

    Web projects have a few unique characteristics that often differentiate them from other types of application projects:

    1) Web projects are almost always built using a variety of very-different tools in parallel.  Images are worked on using tools like Photoshop, Illustrator, and FireWorks.  CSS and .ASPX/.HTM content layout is worked on using DreamWeaver or FrontPage.  Code is worked on using VS.  A tremendous amount of integration and collaboration goes on between these different types of resources.  Sometimes the same person performs all of these tasks, typically for larger projects they are split up across multiple people working together.

    One of the big complaints we hear with VS 2002/2003 is how hard it is to manage these cross-tool workflows – especially given that non-VS tools do not work with FPSE and do not integrate at all with VS project files.  For example: a designer might update a CSS file in a web project to use a new background image, and add the new image to an images directory under the web project using their image editing tool.  If the web developer using VS 2003 does not coordinate this change by updating his or her project file to remove the old image and add the new image to the project file manifest, then they will find that things work ok during development, but it will fail in production since the new image will not be copied/deployed when the web project is built to a new location.

    2) Web projects are also unique in that the file layout of pages, images, CSS stylesheets, Flash SWF files and other items within a web application are directly surfaced to end-users accessing the running web app with a browser.  File-layouts are almost always hierarchical, and a great deal of attention and work is done when coming up with this organization.  The number of files and project items within a typical web site can easily climb into the hundreds or thousands of items.  One of the complaints we hear with VS 2002/2003 is how hard it is to manage this within the IDE – especially when source control is used and it is necessary to check-out and then check-in a common project file every-time a file layout is changed or a file is added/renamed/deleted.

    To better support both of these scenarios, VS 2005 web projects no longer store a list of all files in a central web project manifest file.  Instead, the content and layout of the web project are directly inferred from the file-layout and file contents of the web-project folder.  Additions/deletions/movements of files and folders within the web-project do not require updating one central project file that is a single point of contention.  This means you can easily use any non-VS tool that directly works off the file-system with your web project, and that when running under source control you do not need to lock and update the project file anytime you move or make a file change.

    The project layout under the Solution Explorer for web projects has also been changed to show a file-system view of the web project.  This ensures that developers always see a 100% accurate view of what the exact file-layout and content of their web projects look like (something not true with VS 2003).  Note: we no longer show the “references” tree underneath the root web project node because it is not represented in the file-system – instead you pull up the references list for the project from the project’s property-page (right click on the project in the solution explorer to quickly go there), and you can add a new reference to a project directly using the “Add Reference” menu or context menu item.

    Web projects obviously fully support source control.  If you move or rename a file in a project under source-control, VS 2005 will move and rename the item appropriately with the source control depot (preserving history) without requiring you to exclusively check-out/check-in a project manifest to update it as well.

    Better support for building much larger web projects

    We’ve heard complaints from developers who work on large web projects with VS 2003 that the IDE and workflow environment doesn’t scale well to handle lots and lots of files and content.  Opening a large web-site can sometimes take minutes, and re-building and running it can often take a very long time when you make a change.

    With VS 2005 we’ve tried to significantly improve this scalability to handle hundreds and thousands of items within a web-project.  As an example, on my local desktop machine (a P4 3Ghz) I just tested opening up a local web project with VS 2005 that contains 9,000 files (5,000 .aspx pages and 4,000 images – distributed across 36 directories each containing 250 items).  It opened with VS 2005 in under 3 seconds.  I could then open up and immediately begin editing any of the .aspx pages in any directory without any pauses or delays.  This is several orders of magnitude faster than any previous version of VS (where it would take minutes for a project of this size to even open).

    Doing a first-time clean build of this 9,000 item web-site takes about 42 seconds on my machine (about the same time as VS 2003).  What is cool, though, is that after building the web project once I can now open any of the 5,000 pages, make a change to the code in the page, re-build it, and immediately run and test it in less than 2 seconds from the moment I hit Ctrl-F5.

    There were a couple of architectural changes that we made to facilitate this.  One of the biggest changes was that we’ve moved away from compiling everything in a web project into a single DLL (which is the only mode that VS 2002 and VS 2003 support).  Instead, we now partition the web project into multiple more granular assemblies.

    All non-code-behind classes, datasets, web-services and other non-UI code that live in the web project are by default now compiled into one common assembly.  Pages and User-Controls are then compiled into separate more-granular assemblies (by default each directory in the web project is compiled into a separate assembly).  Note that the web project can also obviously reference other class library projects as part of a solution too (these work just the same as today and would compile into their own project’s assembly).

    The big advantage of this more granular model is that the entire web-site does not need to be re-compiled on every change -- instead the scope of compilation can be easily calculated based on what changed, what the down-level build dependencies of the change were, and only the affected pieces need to be re-built.

    VS 2005 developers also now have more options in their “Build” menu -- they can force building the entire solution (including the current web project and all other projects in the solution), they can build/re-build just the web project, or they can now also choose to use the new “Build Page” option and build/re-build just the current page they are working on (and any dependent resources like user controls that it is using that have also changed) that they are editing.  This provides a great way you can quickly validate local changes you’ve made to a few files without having to-do a full build.  For C# developers who don’t have the background compile capability of VB, it also provides a super convenient way to update intellisense without having to-do a full re-build.

    The F5 and Ctrl-F5 “run” options can also be configured by the developer to choose what level of compilation error checking should occur when these keystrokes are used to launch a web app.  The default continues to be compile all changed pages in the web site – although a useful configuration option when dealing with large web apps is to compile just the pages/resources you are currently working on (this would allow me to open a 9,000 file web-app in 3 seconds, and then compile and run any page within it in about 2 seconds – and avoid the first time hit of compiling everything else).

    Deeper and More Accurate Error Checking and Validation at Built-time

    Errors found at compile/build time are infinitely easier to identify and fix than ones hit at runtime.  One of our goals with VS 2005 and ASP.NET 2.0 was to increase the depth of checking we provide at build-time in VS 2005, and provide a more accurate view of what will happen with the web app at runtime that with VS 2003 built apps.

    Today with VS 2003 and ASP.NET V1.1 developers actually use two different build environments (typically without realizing this). One of these is VS 2003 which compiles and builds the code-behind files within the web project using one set of settings (stored in a .proj file) and produces a .dll stored in the \bin directory.  The other build-system is ASP.NET V1.1 which at runtime will then use a different build system to parse and compile controls, markup and code within .aspx files that derive from the compiled code-behind classes, and which then saves the output of these compilations into a separate temporary folder on the server.  The build-settings of the ASP.NET compilation system, and the subsequent load-time behavior of the code-behind .dll that VS produces, are stored in the application’s root web.config file.

    The fact that these two systems are completely different today can be confusing, and can often lead to errors that are missed entirely by VS at compile time – but which cause web apps to blow up at runtime.  A few common issues we often hear complaints about:

    1) A developer renames the id of a control in the .aspx file, but doesn’t update the field reference in their code-behind.  When they build in VS 2003, they don’t see any compile time errors – but at runtime they get a null-reference exception (because there is a mismatch between the .aspx and code behind).

    2) A developer has a typo on a server-control definition in the .aspx (wrong attribute, incorrect attribute value, misclosed server control tag, data-binding expression error, template error, etc).  When they build in VS 2003, they don’t see any compile errors – but at runtime they get a parse time error.

    3) A developer has an error in their web.config file (either bad syntax or an illegal value).  When they build in VS 2003, they don’t see any compile errors – but at runtime they get a configuration error.

    4) A developer builds a web project.  After testing it and thinking it is done, they switch the project from debug->release mode and compile assuming that the deployed project is now running optimized.  They forget that the <compilation debug=”true”> section in their web.config is the true switch to control whether the app runs under debug mode, and that VS configures this to be true by default and never changes it.  Their app ends up running slowly, and has different behavior (error handling paths are different, .aspx compilation is much slower and inefficient, etc) than it should.

    5) Discrepancies between the values in the <assemblies> section in web.config and the references in VS can cause assemblies to be incorrectly loaded or not found.

    With VS 2005 and ASP.NET 2.0 we decided to merge the ASP.NET and VS web project build-systems into one common compilation architecture with one shared place to store compilation settings for a web project.  Among other benefits, this now means that all of the above 5 issues will now generate compile-time errors when building web projects in VS (both in the IDE and through the command-line with MSBuild) instead of only being caught by testing at runtime.

    It also means that we can do much deeper design-time integration inside VS itself – so that things like Master Pages, User Controls, Themes and other resources that have previously been “dynamically compiled” by ASP.NET only at runtime can now be compiled and used within VS as well (for example: this means you now get both WYSIWYG and intellisense support for user-controls, master pages and skin resources).  It also allows us to get full intellisense of code+content within .aspx pages – so <script runat=server> blocks, <%# %> databinding blocks, and other syntactical elements inside ASP.NET pages are now fully supported inside the VS editor.

    We choose to store the unified compilation and build settings (release/debug, assembly references, namespace imports, warning levels, etc) within the <compilation> section of the application’s web.config (where all of these settings already existed in ASP.NET and V1.1).  Because this file is relative to the web project root, it allows the web project to be easily included in multiple .sln solutions within VS. 

    In addition to providing richer compilation and runtime validation within web projects, we have also added new accessibility compliance validation in VS 2005 (to allow developers to check for Section 508 and WCAG compliance).  This accessibility checking can be run manually (there is a button in the toolbar and a menu item to configure and run it), or developers can also configure their web projects to automatically run the accessibility checker each time a web project build occurs.

    More Flexible and Iterative Web Development Experience

    We’ve tried to optimize the workflow behavior within VS 2005 to enable a more iterative and flexible web editing model.  Several of these optimizations are a direct result of the changes we’ve made in the web project system and include:

    1) The ability to make quick tactical changes to your web projects in VS 2005 and immediately “save and refresh” to see the changes.  With VS 2002 and VS 2003, developers were always required to re-compile and re-build their projects to see the affect of any changes within their web apps.  VS 2005 obviously fully supports this as well (as mentioned earlier you can “Build Solution”, “Build Web” and “Build Page” to compile and verify there are no errors at any granularity). 

    We also then support an “on demand” compilation workflow where a user can just save the code-behind or class file they are editing, and immediately hit refresh in the browser (no explicit re-compile or re-build required).  ASP.NET will then on-demand re-compile only the changed resources and apply it to that request – allowing you to immediately see the difference.  This is ideal for making quick surgical changes (one or two liners where you are confident you have it right and just want to immediately see the changes).  We think this feature merges the best features of dynamic languages/scripting (rapid development) with the best features of strongly-typed compiled languages (better error checking and performance).

    2) The ability to both edit and add code while the debugger is attached.  With VS 2002 and VS 2003, attaching and detaching the debugger can often be cumbersome and time consuming (especially when it nukes the process on detach).  When the debugger is attached, developers are not allowed to make any changes to the running web application or web project. 

    With VS 2005, we now allow a workflow where developers can launch a web project under the debugger, try out and step through a request to identify an issue, and then – without closing or detaching the debugger – add methods, classes, pages and change code in the project, hit save, and then hit refresh in the browser to immediately step through things in the debugger again.  This is supported for both VB and C#, and enables much richer editing support than the “edit and continue” support in client projects (where only code inside methods can be changed – and method, parameter, and class signatures can’t be changed).  I personally have found it useful to keep the debugger attached for 1-2 hours at a time, while I work on pages, classes and develop the entire web with the ability to step through things at anytime.

    Richer Web Deployment Options

    VS 2005 and ASP.NET 2.0 now support several additional deployment options for web projects not previously available with VS 2003.  These include:

    -- The optional ability to completely compile a web project, including compiling all .aspx, .ascx, and .master file content (allowing you to compile and then remove the HTML and ASP.NET server control markup code, and optionally even remove the .aspx and .ascx files themselves and just ship the .dll assemblies).  There are a couple of benefits with this feature: 1) It allows you to ship a totally “locked-down” deployment package for enterprise deployment environments. 2) It allows you to better protect your intellectual property from customers if you don’t want them to see or change your markup. 3) It eliminates all runtime ASP.NET compilation steps, avoiding the first-time performance hit when a page is first accessed and the .aspx markup is compiled, and enabling much better application startup time and working set usage.  This later benefit can be particularly noticeable with large applications, and provides a big performance improvement over VS 2003 built apps today.

    -- The ability to support “patching” of deployed assemblies within a site, and allowing you to overwrite some (but not all) of the compiled code-behind binaries on your deployment server without having to change all of the DLLs.  This is enabled using the “fixed names” option within the new web build-system, and is particularly useful with user control libraries where you might only want to re-issue a binary for one or two controls in a library and not have to update the code-behind dll used for all of them.

    Note that in addition to support complete compilation, we also obviously continue to support a model where only the code-behind is compiled and the .aspx markup is left for later customization.  We also now support a fully dynamic compilation model where everything (including code-behind and classes) is dynamically compiled on the production server (this is useful for small site and hobbyist scenarios).

    Web Project Build Automation Support

    VS 2005 and ASP.NET 2.0 now have richer support for command-line level build automation, and can also be integrated and automated using the new MSBuild system being introduced in VS 2005.

    ASP.NET 2.0 ships with a new command-line compiler (aspnet_compiler.exe) that provides full support for compiling and building ASP.NET projects (with or without VS installed).  It supports all of the new build and deployment options mentioned in web projects earlier (optional compilation of .aspx content, updatable assemblies, etc), and provides deep error warnings and detections when compiling web applications.

    The aspnet_compiler.exe utility can be invoked standalone, or used within the context of a MSBuild project file.  MSBuild provides a very rich framework for automating and constructing build and environment rules.  Some scenarios of how you could use this for web projects: support building and then copying user-control libraries from multiple web-projects into a web-site as a pre-build step, compiling your web projects, code-signing output, producing both release and debug builds in separate directories for each automated build you kick off, kick off automated unit tests, send out code-coverage reports, etc.

    MSBuild can be directly run from the command-line (it ships as part of the .NET Framework redist setup – so no VS is required on your build-server).  If you pass it a .sln file that has web projects contained within it, these can be built and deployed as part of the solution by MSBuild and provide basic build option support.

    Unfortunately we don’t have direct MSBuild IDE support to launch MSBuild workflows in the web project IDE – so you can’t add a MSBuild file into a solution with only a single web project and directly kick it off in the IDE (note: C++ projects also don’t support this either in VS 2005).

    What you can do though with VS 2005 web projects to get equivalent functionality is to add a “Build Helper Project” that lives next to your web project in the same VS solution.  This “Build Helper Project” is just an empty class library project, but can contain custom build/configured MSBuild scripts where you can specifically script custom build actions for both your web project and overall solution (for example: as part of a single script you could compile multiple user-control library projects, then merge them into a web application project, then compile and publish it, then run a post-grep utility over it to make sure only production deployment connection strings are being used in the web.config file, encrypt any necessary web.config files, etc, etc).  You can then kick-off these builds/actions by building the “Build Helper Project” either in the IDE or directly from the command-line.  This isn’t as elegant as attaching all of these build scripts to the web project directly, but it enables the same functionality – and provides a lot more power than what was available in VS 2003.

    Going forward we are looking to add more integration support with MSBuild in the next VS Orcas release – there is a lot of cool stuff we will be able to-do with it.  In the meantime, we are also planning to post some samples on the web of additional MSBuild tasks (w/ source code so you can see and tweak them) that show how to enable both common and advanced scenarios with web projects.

    Visual Studio Team System Integration

    One of the biggest things in VS 2005 is the introduction of the Visual Studio Team System products, and the advanced development support they provide.  These features are fully integrated with the web project system and allow developers building web projects to take advantage of lots of new capabilities.  A handful of a few of the big new features that touch a little on the web project system include:

    1) Ability to develop unit tests for both classes and web UI within a web project (allowing functional ASP.NET UI validation within test projects).  VSTS includes a built-in web replay tool that captures interactions between a browser and the server, and allows easy automation and validation of behavior.

    2) Ability to measure and precisely quantify the percentage of code exercised by tests (what we often call code coverage).  A web developer can build a web project, then build lots of tests to exercise its functionality, and can then run those tests and get a report detailing that “74% of the lines of code in the web project were executed during the tests”, as well as a precise breakdown of what parts of the code-base were not exercised because boundary and use cases weren’t good enough.

    3) Ability to load-test web projects to measure RPS (requests per second) throughput, average latency, memory usage and dozens of other metrics.

    4) Ability to profile code execution of web projects, and analyze the % of time spent where within a web project as well as memory allocations and usage.

    5) Ability to automate and kick-off regular or nightly builds using the new Build Server capabilities.  Tests can automatically be run as part of this to verify and report build quality. 

    And a whole lot more… 

    Visit: http://lab.msdn.microsoft.com/teamsystem/default.aspx for more details on Visual Studio Team System.

    Sharepoint Server Support

    We’ve done a lot of work to integrate ASP.NET 2.0 with the next release of Sharepoint that ships with Office 12 next year.  The new version is built entirely using the new feature of ASP.NET 2.0: WebParts, Master Pages, Themes, Site Navigation, Membership, Roles, Personalization, Localization, Data Controls, etc.

    One of our goals with Visual Studio is to enable great tool support for building Sharepoint solutions.  Today with VS 2003 this is fairly limited (you can pretty much only create a web-part control as a class library).  One of the design goals of the new VS 2005 web project system was to enable great Sharepoint support, and enable directly opening and debugging Sharepoint solutions.  Going forward we will support creating and editing new pages in running Sharepoint servers, support adding code-behind logic to pages, creating application logic, customizing workflow, building and adding new webpart controls, and debugging the finished solution.

    In closing (btw -- thanks for reading this far...)

    As the above sections hopefully spell out, there is a heck of a lot of new functionality provided with the VS 2005 web project system.  We think this functionality not only adds a lot of new features to take advantage of, but also addresses a lot of the key pain-points we’ve heard feedback from customers using VS 2003 today.

    So what are the downsides to it?  Well, we really hope there aren’t a lot….  Several people have expressed concerns about some important features missing from the project system in Beta1 and Beta2.  As I mentioned in my earlier blog post, though, these features will be in the final release.

    The only current VS 2003 feature I know of that is not directly supported in the VS 2005 web project system is the lack of pre/post build events defined directly in the web project itself.  As I mentioned above in the “Web Project Build Automation Support” section you can add a “build helper project” into your solution to get back this equivalent functionality, as well as to get much, much richer build customization support than VS 2003 provided using the new MSBuild capabilities.  This extra step is a little more inconvenient than embedding directly in the web project, even though it does provide much more power. We will be publishing a whitepaper before the final release that walks through the steps on how to set it up and take advantage of it to help make its usage and benefits more discoverable.

    Because there have been a number of changes to both the web project system, and lots of other parts of Visual Studio, it is also going to take a little time for current developers to learn all the new capabilities, how to take full advantage of them, and sometimes how to map and evaluate the new capabilities to existing solutions (and in some cases workarounds) they might be using today to achieve similar results.

    It would be great if people could post questions or suggestions here for additional blog entries or MSDN whitepapers that you’d like to see come out between now and the final release that cover either “how do I do [insert scenario]?” or “is there a better way now to handle [insert scenario]?”  I’ll then follow-up on these and either post new blog entries on them or get whitepapers written that go into more detail.

    Here are a few I’ve already been asked about that we are planning to cover:

    1) Best techniques for re-using user control libraries in multiple web apps with VS 2005

    2) Best techniques for building a single web-site that is partitioned up into multiple nested/isolated vdirs and applications with VS 2005

    3) Best techniques for using MSBuild and builder helper projects with web projects in VS 2005.

    4) Best techniques for upgrading from VS 2003 to VS 2005 and what project system considerations you should keep in mind.

    Hope this helps provide some more information about the new project system, as well as clear-up some confusion about what it is. 

    Again – let me know additional things you’d like more details or clarification on.

    Thanks,

    Scott

    Recent Update:

    I've posted several blog entries since then that discuss the web project system in more detail.  I'd recommend checking these out:

    Using IIS with VS 2005 and the new Web Project system

    Building Re-Usable ASP.NET User Control and Page Libraries with VS 2005

    Some techniques for better managing files in VS 2005 Web Projects

     

  • Quick Web Project System Post

    I've been on vacation the last few days in Mexico (and fly back Sunday night), so am just catching up on all the web project system threads that have been flying the last 48 hours (serves me right for finding an internet cafe to check my email when I'm not supposed to).

    I'm planning on posting a blog post on Monday or Tuesday when I get back that goes into the web project system in more detail and why we've made some of the changes we've made.  My sense in reading some of the recent comments is: 1) we haven't done a good job of explaining all the new capabilities that the new web project system provides (and there are a lot of good new features), and 2) we haven't done a good job of clarrifying people's concerns about the changes and what they might worry about loosing in terms of functionality as a result of them.

  • Obscure but cool feature in ASP.NET 2.0

    I learned about a neat little feature that I didn't know existed in ASP.NET 2.0 today that I thought I'd pass on.  It is a way to extend the attributes supported by the <%@ Page %> directive at the top of a .aspx page.  Previously the supported page directive attributes were hard-coded and the parser only supported the specific ones that ASP.NET knew about out of the box.  With ASP.NET 2.0, if you declare a base-class with a public property, you can now set it using a page directive attribute.