Archives

Archives / 2005 / November
  • VirtualPathProvider Extensibility in ASP.NET 2.0

    One of the really powerful things we did in ASP.NET 2.0 was to build a pluggable provider abstraction for a web app’s file activity, and to then re-plumb the ASP.NET parser, compiler, and other path/content/page related work to go through it.  What this ends up delivering is a lot of extensibility capabilities not possible in ASP.NET V1.1.

     

    Some examples of what you could do:

     

    1) Re-plumb the storage of a web-site from being the file-system to instead have all content stored in a database or some other store (btw -- the next version of SharePoint is using this mechanism to-do this).

     

    2) Hook and modify path information, and plug into the compilation process of the web-site.

     

    3) Perform richer validation analysis on content being parsed (for example: disallowing certain controls from being used if you want to lock down and only allow “safe” controls on a site).

     

    David Ebbo just started a blog to share some of the ideas of what you could do with this support.  His first post answers a question from someone in a forum who wanted to find a way to create multiple “virtual sites” within a single ASP.NET application and app-domain.  David shares how this can be done with only a few lines of code.

     

    Definitely a great blog to keep an eye on!

     

    - Scott

     

  • HTML Validation Checking in VS 2005 (and how to optionally turn it off if you want)

    I posted earlier about some of the cool new HTML source editor features in VS 2005 and Visual Web Developer.  One of the big new things is much richer html source validation.  Specifically you can now validate against different HTML schemas and standards (XHTML Transitional/Strict, HTML 4.01, and various browser types).

     

    In addition to validating against the HTML element schemas, VS 2005 and Visual Web Developer also by default now validates CSS inline styles, casing and termination of HTML tags (for example: to force lower case and close tags), and performs link and image reference validation.

     

    For example, if you have an html hyperlink anchor in your page that points to a local file that doesn’t exist, or an image element that points to a local image that doesn’t exist, you will now see red squiggles in your source editor:

     

     

    And if the html document is open you will also see relevant errors in your error list (if you click on any of the errors in the error list you will automatically jump to the issue in the source):

     

     

     

    Important: HTML validation errors do not block a web project from compiling or running.  As such they can optionally be ignored if you do not want to deal with them (although our recommendation would obviously be to review them closely and fix them). 

     

    The reason we are now surfacing HTML validation issues in the error list by default is that we are trying to promote more standards-based html with VS 2005 and ASP.NET 2.0, as well as to catch potential rendering and browser functionality errors earlier in the development process (so that you don’t have to run and carefully analyze every page in your app looking for these types of issues).  

     

    If you’d rather not have these types of HTML validation errors show up in your error-list, you can disable this functionality by selecting the Tools->Options menu item in VS or Visual Web Developer.  Select the TextEditor->Html->Validation tree option in the left-hand side of the options window, and uncheck the “Show Errors” checkbox:

     

     

    Note that another possible reason to turn this setting off might be if you are seeing performance problems when editing very large documents on your system (I personally find my laptop 1.4Ghz machine is able to edit 4000 line html files just fine with full validation on – but your mileage may vary depending on your exact hardware configuration).  The HTML validation occurs in the background on idle, so shouldn't get in the way -- but if you are tight on cycles turning it off can probably spare you a few timeslices on your CPU.

     

    Hope this helps,

     

    Scott

  • A few of my favorite new HTML source editor features in Visual Web Developer & VS 2005

    We spent a lot of time in Visual Web Developer and VS 2005 focusing on delivering a really great HTML source editing experience (we also did a lot in design-view – but this blog post is just about the HTML source editor).  Below are a few of the cool new features it enables (none of these were in VS 2003).  All but one of the features are in the free Visual Web Developer Express version that you can download.

     

    Intellisense Everywhere:

     

    We now support intellisense everywhere within the HTML editor.  For example:

     

    We now support it for ASP.NET directives:

     

     

    We now support it for <script runat=”server”> code blocks and <% %> nuggets:

     

     

    We now support it for CSS style blocks (in additional to external CSS files):

     

     

    We also obviously support intellisense client-side script (more on that next), as well as any XML file with a DTD or XML Schema.  We also support intellisense now within web.config files.

     

    Standards and Browser Based HTML/Script Intellisense:

     

    You can now automatically vary the HTML + client-script intellisense you receive in the editor based on either a standards based schema (html 4.01, xhtml transitional, xhtml strict, etc) or for a specific browser device (IE 6.0, etc).

     

    There is now a device drop-down list in the toolbar that allows you to easily toggle between the different schemas:

     

     

    This will then update all HTML/client intellisense settings (so you only see those elements/attribute/script object model values legal for the particular schema target you have picked):

     

     

    Note that the default schema validation value for new web projects is now XHTML Transitional.  You can also easily add your own schemas to VS if you want to modify any of the built-in ones or publish your own.

     

    Intellisense for User Controls and Custom Controls (no special work required):

     

    We now (automatically) support HTML editor based intellisense for any control or user-control used within the project.  For example, the below screen-shot shows the intellisense I get when consuming an .ascx user-control on a page that has a custom “Foo” property:

     

     

    The new web project system will dynamically compile and use reflection to figure out what properties are exposed on the user-control.

     

    Custom compiled controls no longer need to jump through schema registration hoops to get intellisense either.  Simply register the control using a standard <%@ Register %> directive at the top of the page, and VS will also use reflection to provide intellisense within the html editor.  (note: this was a real pain with VS 2003).

     

    Tag-Navigator:

     

    At the bottom of an html or asp.net source-view document is a new control called the “tag-navigator”.  It updates as you move around a document, and always shows the complete parent chain of html tags from the root <html> element to the location where the cursor currently is.  If any of these tags has an ID value, it will also include that value as well (for example: div#myidvalue).

     

    This makes it much easier to figure out “where am I in a document”, and figure out the nesting relationships of elements quickly (“am I in this div/table or a deeper nested one?”).  This can be super-useful with large html documents.

     

    For example: here is a screenshot of what it looks like when I copy/pasted in some html from the my.yahoo.com website (which has a lot of html):

     

     

    What is then cool is that when you click on any of the elements in the navigator it will highlight them (and optionally allow you to highlight the inner contents).

     

    Collapse/Expand HTML:

     

    Container elements in HTML are now collapsible (and expandable) using +/- gestures in the left hand side of the editor.  For example, the GridView in the below screen-shot is collapsed to hide all of its inner content:

     

     

    Note that you can have multiple levels of collapsing – so you could expand the above GridView to see more of its contents, but still have one of its templates inside collapsed.  Makes dealing with lots of content much cleaner.

     

    HTML Tag Bolding:

     

    If you click on (or navigate onto) any element within the html editor, we will now bold both it and its end tag:

     

     

    This also makes it much easier to navigate around deeply nested HTML documents and figure out where elements start and end.

     

    Per Tag Formatting Rules:

     

    You can now specify and control precisely how your HTML will look when you add it to a page.  You can set both the defaults for capitalization rules, indentations, whitespace, etc for elements:

     

     

    As well as customize default formatting settings on a per-element or control basis:

     

     

    This will control what the html source will look like when you add it in the designer (for example: drag/drop from a toolbox). 

     

    You can also then within the html source editor select any HTML you want, right-click, and choose to “Format Selection”.  This will modify the selected HTML to follow your coding guideline rules (very useful when you are given ugly HTML to use).

     

    Per HTML Element/Control Colorization:

     

    Someone in the Beta1 timeframe told us that he absolutely loved the new HTML editor capabilities, and that the only feature he was missing that would prevent him from switching from HomeSite was the ability to perform per-tag colorization in the source editor.

     

     

    Whoever you are out there – we hope you are happy now (it is supported in the final release, complete with a 32-bit color palate to choose from). ;-)

     

    Section 508 and WCAG Accessibility Checker:

     

    You can now automatically validate your HTML markup against Section 508 and WCAG accessibility standards (just select the accessibility icon in the toolbar):

     

     

    The HTML editor will highlight violations in the source document, as well as list errors/warnings in the error list:

     

     

    Property Grid and Toolbox work in Source View:

     

    You can now cursor onto any HTML element or ASP.NET Server Control tag in the IDE and then use the property grid to see and edit its properties (no longer a need to switch into design-view to-do this).

     

    You can also now drag/drop ASP.NET server controls from the toolbox in source-view and automatically position them within the html source (saves you having to type them).

     

    No HTML Reformatting:

     

    The HTML designer no longer modifies your HTML when you switch between designer and source view, and preserves your existing whitespace and formatting settings.  This isn’t really an HTML source editor feature, but I thought I’d mention in anyway since it always makes people happy.

     

    Location/Selection Preservation between Source and Design View:

     

    One subtle but cool feature we added was the ability to preserve your cursor/selection when you switch to/from design/source view.

     

    For example, say you select a control or some text in HTML source view:

     

     

    When you switch to design-view, the same element/control will be selected in WYSIWYG mode:

     

     

    Note that this also happens the reverse way – select something in the designer and switch to source view, and the cursor and/or selection will be at the right place.

     

    Makes switching back and forth pretty easy.

     

    Summary

     

    There are a lot of additional new things I could call out – but hopefully this gives you a taste of some of the cool new features you can take advantage of.

     

    Hope you enjoy them,

     

    Scott

     

    P.S. All of the features above except the accessibility checker are in the free Visual Web Developer Express Edition of the product. 

     

     

  • How to Run a Root “/” Site with the VS/VWD 2005 Local Web Server

    Update: This blog post is now old and out of date.  Please read this newer post of mine instead. 

     

     

    One of the questions I’ve been asked a few times is whether it is possible to build and run an ASP.NET web-app as a top-level “root” site using the VS 2005 local, built-in, web-server (which is the default web-server used when you open a web-site as a file-system based web).

    By default, when you open a web-site as a file-system based web and run the project, VS will launch and run the built-in web-server using a virtual app path that equals the project’s root directory name.  For example: if you have a project named “Foo”, it will launch and run in the built-in web-server as http://localhost:1234/Foo/Default.aspx.

    One downside to this is that it makes it hard to fully qualify things like static CSS and image files within your site (for example: using root qualified paths like /images/myphoto.jpg or /css/mycss.css).  Note that you can use the “~” app path trick for dynamic resources – but static resources still end up being a pain.

    One way to solve this is to configure VS 2005 to run your site using IIS instead (and configure the app to be the root site on your IIS web-server).  You can then open and edit it just fine using VS 2005 (for details on this read: http://weblogs.asp.net/scottgu/archive/2005/08/23/423409.aspx).

    Alternatively, you can use the tip/trick below to accomplish the same task with the built-in file-based web-server:

    Step 1: Select the “Tools->External Tools” menu option in VS or Visual Web Developer.  This will allow you to configure and add new menu items to your Tools menu.

    Step 2: Click the “Add” button to add a new external tool menu item.  Name it “WebServer on Port 8080” (or anything else you want).

    Step 3: For the “Command” textbox setting enter this value: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\WebDev.WebServer.EXE (note: this points to the web-server that VS usually automatically runs).

    Step 4: For the “Arguments” textbox setting enter this value: /port:8080 /path:$(ProjectDir)

    Step 5: Select the “Use Output Window” checkbox (this will prevent the command-shell window from popping up.

    Once you hit apply and ok you will now have a new menu item in your “Tools” menu called “WebServer on Port 8080”.  You can now select any web project in your solution and then choose this menu option to launch a web-server that has a root site on port 8080 (or whatever other port you want) for the project.

    You can then connect to this site in a browser by simply saying http://localhost:8080/.  All root based references will work fine.

    Step 6: The last step is to configure your web project to automatically reference this web-server when you run or debug a site instead of launching the built-in web-server itself.  To-do this, select your web-project in the solution explorer, right click and select “property pages”.  Select the “start options” setting on the left, and under server change the radio button value from the default (which is use built-in webserver) to instead be “Use custom server”.  Then set the Base URL value to be: http://localhost:8080/

    Now, when you click on any page in the app and then hit F5 or Ctrl-F5, the IDE will use the custom web-server you launched to connect instead of popping up its own.   It will resolve all paths correctly (for example: if you select a page "Foo.aspx" under a directory "Bar" -- it will launch the browser at http://localhost:8080/Bar/Foo.aspx when you hit F5).

    The good news is that you only need to follow the above steps once.  If you restart the IDE, just select your web-project and choose your web-server option from external tools to launch the web-server instance, and then hit ctrl-f5 or f5 to launch your app and you’ll be good to go.

    Hope this is a helpful tip/trick,

    Scott

    P.S. Yes – we should have made the root web-site the default (but hopefully this tip will tide you over until we can change that)…

    P.P.S. Robert also posted a cool related tip to launching the web-server from a file-system folder here: http://weblogs.asp.net/rmclaws/archive/2005/10/26/428600.aspx

  • ASP.NET 2.0 Site Navigation Features

    Feb 2006 Update: Please also check out this new blog posting I did on Site Navigation.

     

    The new Site Navigation features in ASP.NET 2.0 can make building navigation structures across a web-site much easier.

     

    Scott Mitchell has published a good quick overview of the new ASP.NET 2.0 Site Navigation features if you aren’t familiar with them yet and want to come up to speed quickly.  There is also a ton of information on it on MSDN, and Danny Chen from the ASP.NET team has some extra great information on his blog. 

     

    At a high-level, the new Site Navigation features allow you to define (outside of code or pages) the “site map” structure of how your site is laid out.  Specifically, it allows you to define the relationships between pages on the site – what is the “home” entry-point, what are the sub-sections of it, and how individual pages fit within it.  This information is cached by ASP.NET, and you can then get access to this sitemap structure at runtime. 

     

    ASP.NET includes a basic built-in XML based SiteMap provider that allows you to define this site structure within an XML file whose default name is “web.sitemap” (note: you can change the name if you want).  For example, the below web.sitemap XML file example defines a sitemap with several levels of hierarchy (a homepage root, then three sub-nodes, and under the products node three additional sub-nodes):

     

    <?xml version="1.0" encoding="utf-8" ?>

    <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >

     

        <siteMapNode url="default.aspx" title="Home"  description="The WebSite's Home Page">

         

          <siteMapNode url="Products.aspx" title="Products"  description="Product Listing Section of Site">

            <siteMapNode url="Software.aspx" title="Software"  description="Software Products" />

            <siteMapNode url="Hardware.aspx" title="Hardware"  description="Hardware Products" />

            <siteMapNode url="Services.aspx" title="Services"  description="Service Products" />

          </siteMapNode>

     

          <siteMapNode url="Documentation.aspx" title="Documentation"  description="Documentation about something"/>

          <siteMapNode url="About.aspx" title="About"  description="About the Company"/>

         

        </siteMapNode>

     

    </siteMap>

     

    The simplest way as a page developer to access the site-map at runtime (and figure out where the current page is within it) is by using the new “SiteMap” property on pages.

     

    For example, the below code snippet shows a pretty simple scenario of how you could use the SiteMap system to dynamically build a “bread-crumb” UI on your page to provide a way for users visiting the site to see what page or section of the site they were within, and allow them to quickly navigate up the hierarchy chain:

     

            SiteMapNode node = SiteMap.CurrentNode;

     

            do

            {

                HyperLink link = new HyperLink();

                link.NavigateUrl = node.Url;

                link.Text = node.Title;

                SiteHierarchy.Controls.AddAt(0, link);

     

                Label label = new Label();

                label.Text = " >> ";

                SiteHierarchy.Controls.AddAt(0, label);

     

                node = node.ParentNode;

     

            }

            while (node != null);

     

    By adding a placeholder or label control called “SiteHierarchy” in your .aspx page, then the above code will dynamically generate a hierarchy with this UI when the Software.aspx page is accessed:

     

    >> Home >> Products >> Software

     

    An even simpler way to achieve this is to use the new <asp:sitemappath> server control – which encapsulates and provides the breadcrumb UI logic for you (the control is also templated – so you can override the rendering using templates defined either inline or in an external skin file):

     

    <asp:SiteMapPath ID="SiteMapPath1" runat="server">

     

    You can also then use the new <asp:SiteMapDataSource> control to data-bind any control to the SiteMap (for example: you can databind a GridView, or DataList to one).  Two new controls in ASP.NET 2.0 are the <asp:treeview> and <asp:menu> that will probably be the most popular way to databind to the SiteMap and provide a hierarchical UI navigation structure. 

     

    What is great about ASP.NET 2.0 is that you can do all these navigation things in conjunction with the new Master Pages feature – so that you could define a breadcrumb or menu in one .master file, and then have every page on the site pick it up and include it (and the navigation shown will be relative to the .aspx page using the master page – not the master page itself). 

     

    The combination lets you whip up navigation structure and UI in only a few minutes, and provides the flexibility for you to dive down and customize things even further if necessary.

     

    Answers to a couple of common questions about Site Navigation

     

    I’ve seen a few common questions about the Site Navigation feature from folks at conferences and in blogs that I thought would be worth quickly answering:

     

    >>> Question: With the default XML File Provider can you use a filename other than web.sitemap to store your site map information?

     

    Answer: Yes.  The filename used with the XML File Provider can be specified in your web.config file (the default name we configure is web.sitemap).  This MSDN article shows how to-do this (among other things).

     

    >>> Question: With the default XML File Provider can you partition your site map definition across multiple files (for example: have a site map file stored in a sub-directory of the site that defines the sitemap makeup of just that sub-directory)?

     

    Answer: Yes – that is pretty easy to-do.  This MSDN article shows how to-do this.

     

    >>> Question: Is it possible to filter what nodes are visible in the site-map based on the security role permissions of the current user visiting the site (for example: hide those nodes that they don’t have access to)?

     

    Answer: Yes. This MSDN article show how to-do this.

     

    >>> Question: Is it possible to dynamically add nodes into a site-map (for example: for forum or blog post listings underneath a leaf node) without having to write a custom SiteMapProvider?

     

    Answer: Yes.  This MSDN Article and this blog post discuss how to-do this.

     

    >>> Question: Can you localize site-maps (for example: have German and English content).

     

    Answer: Yes.  This MSDN article shows how to-do this.

     

    >>> Question: Can you define a site map definition in something other than an XML file (for example: instead use a database?).

     

    Answer: Yes.  The Site Navigation system is provider based, which means that you can use any custom provider implementation to define the site-map hierarchy.  What is even cooler, is that you can optionally use multiple providers together – for example: use the XML provider for the overall structure, but maybe a blog specific provider that goes against a blog database to populate the nodes dynamically underneath a portion of the site.

     

    Jeff Prosise also has a cool sample that he talks about here on how to build a SiteMapProvider that retrieves the sitemap structure from a database rather than the default XML file provider.  This MSDN article also links to a bunch of content on building your own SiteMap provider.

     

    The next version of SharePoint (which is heavily integrated on top of ASP.NET 2.0) will also include a SharePoint specific Site Navigation provider that dynamically populates the site-map with the content contained within a SharePoint site.

     

    Hope this helps,

     

    Scott

  • ASP.NET 2.0 Security Best Practices (and the declarative PrincipalPermission attribute)

    This is a great MSDN whitepaper about ASP.NET 2.0 Security Best Practices.  I’d definitely recommend setting aside some time to read it.  At the bottom of the whitepaper there are then links to another 28 additional ASP.NET HowTo security whitepapers.  Most of the articles were rated a perfect 9 out of 9 from people who have read them – always a good sign of great content.

     

    One tip that the papers cover that I’ve been meaning to blog about is the ability to add declarative permission attributes to classes and methods.  These allow you to limit the ability to instantiate a type or invoke a class member based on the identity of the browser user for the request, and provide a clean defense-in-depth mechanism that you can use to add additional security to your business logic, data logic, and even UI logic within your page.

     

    For example, the below code will prevent the “Authors” class from being instantiated during a request unless the incoming user is authenticated:

     [PrincipalPermission(SecurityAction.Demand, Authenticated=true)]
     public class Authors
     {
         // Methods
     }

    And the below code will prevent the "Authors" class from being instantiated during a request unless the incoming user is in the “Admin” role:

     

    [PrincipalPermission(SecurityAction.Demand, Role="Admin")]
    public class Authors
    {
        // Methods
    }

     

    Note that enabling role-based security with ASP.NET 2.0 is now trivially easy with the new ASP.NET 2.0 role management service.  Here is one of those how-to articles on how to use the new role-manager capabilities.

     

    Hope this helps,

     

    Scott

  • Url Mapper w/ Regex Support

    Several people have asked why the built-in URL Mapper in ASP.NET 2.0 doesn't support regular expressions.  There were actually a few reasons for this -- one of the big ones being that just about the time we were about to consider adding it my team started also working on IIS7.  We realized that a full-featured version would want/need to take advantage of some of the new features in IIS7 as well as the support all content types (in particular -- images and directories).  So we postponed making it feature rich until a future version.

  • Tips for Nested Master Pages and VS 2005 Design-Time

    One of the cool advanced features of the new Master Pages feature in ASP.NET 2.0 is the ability to nest them.  For example, you could define a top-level master-page called “MainMaster.master” that defines a common logo header and footer, and defines a content-placeholder for the page called “content”.  You could then define two sub-masters beneath it – one that provides a two-column layout model for the content (“TwoColumnMaster.master”), and one that provides a three-column layout model (“ThreeColumnMaster.master”).  These two nested-master pages could then use the MainMaster.master file as the root master, and only adjust the layout within its content section (each would fill in the "content" placeholder and in turn add their own content-placeholders for sub-pages within it).  The benefit of this approach is that if a designer ever changed the logo or top-level design of the site, they only have to update one file (MainMaster.master) and then have every page on the site automatically pick it up regardless of what master file they were based on.

     

    This nested model is pretty cool and powerful, and allows arbitrary levels of nesting.  The only downside is that VS 2005 only supports nested master page editing in source-view, and doesn’t support it in the WYWSIWYG designer (note: obviously it does support editing them when the master-pages are not nested). 

     

    There is a cool tip/trick, though, that will allow you to load a design-surface for a page that uses nested master-pages.  This will allow you to use all of the control-designers and smart-tasks in design-view for the page (for example: to perform data-binding, auto-format things, and use any of the control wizards), and not have to change any-code to test it at runtime.

     

    The tip/trick works by adding a base-page class to your project or solution that defines a new property called “RuntimeMasterPageFile” of type string.  The base-class then overrides the page’s “OnPreInit” method and uses this property to set the Page object’s MasterPageFile at runtime:

     

    public class BasePage : System.Web.UI.Page {

     

        private string runtimeMasterPageFile;

     

        public string RuntimeMasterPageFile {

            get {

                return runtimeMasterPageFile;

            }

            set {

                runtimeMasterPageFile = value;

            }

        }

     

        protected override void OnPreInit(EventArgs e) {

            if (runtimeMasterPageFile != null) {

                this.MasterPageFile = runtimeMasterPageFile;

            }

       

            base.OnPreInit(e);

        }

    }

     

    Once a code-behind class derives from this base class, it becomes possible for a developer to set this “RuntimeMasterPageFile” property in the .aspx file’s <%@ Page %> directive (note: the CodeFileBaseClass also needs to be set to the base class to enable this):

     

    <%@ Page Language="C#"

    MasterPageFile="~/Test.master" RuntimeMasterPageFile="SubMaster.master" CodeFileBaseClass="BasePage"

    AutoEventWireup="true"

    CodeFile="Default.aspx.cs"

    Inherits="_Default"

    Title="My Page Title" %>

     

    You’ll notice that the above page now has two master-page file directives – the usual “MasterPageFile” directive that VS will use at design-time, and then the custom RuntimeMasterPageFile directive that will override this at runtime.  What this allows you to do is point the page at a “test.master” file at design-time that is a single-nested page with contentplaceholder controls that match the names in your nested master.  You can then switch to design-view and edit the content and all controls on your page.  When you run the page, though, it will use the nested “submaster.master” (or any other master page you specify) to run.

     

    Update: Brian also pointed out to me that you can leave the MasterPageFile attribute value as "" and the designer will then automatically render a test master page that just lists all of the content-placeholder controls in editable regions.  This might allow you to avoid having to define a test master page for your site.

     

    Here is a simple sample that shows all this working (you can switch the default.aspx page to use either the submaster.master or submaster2.master page that is based on mainmaster.master).

     

    Hope this helps and is useful,

     

    Scott

     

    P.S. The new Microsoft Expression “Quartz” Web Designer tool *will* also support editing pages based on nested master-pages in design-time, and this will also show up in the next release of Visual Studio (code-name Orcas).

  • Forms Authentication timeout default in ASP.NET 2.0

    One thing to be aware of when upgrading from ASP.NET V1.1 to V2.0 is that the forms authentication timeout value has changed to be 30 minutes by default.  This means that after 30 minutes of inactivity, a user will be prompted to login again (note: everytime they hit the site the 30 minute window clock gets reset -- so it is only if they are idle that it will timeout). 

  • VS 2005 Web Deployment Projects

    Update: This shiped a few days ago.  More details here: http://weblogs.asp.net/scottgu/archive/2005/11/10/430283.aspx

     

    Later this week Microsoft is shipping on the web a new free add-on to Visual Studio that enables what we call “Visual Studio 2005 Web Deployment Projects”.  This add-on provides a lot of additional deployment features and capabilities that complement the built-in web project support in the product.  The below blog post provides a quick overview of some of the new things coming.  There are also some MSDN whitepapers that will document it more exhaustively over the next week as well.

     

    Some background

     

    The web project model changed in a number of ways between VS 2003 and VS 2005.  There was a lot of discussion this August over missing features that weren’t supported or were broken by it in Beta2 (examples: exclude file from project support, file-based assembly refreshes, the ability to not check-in \bin assemblies in source control, etc).  These specific issues were fixed in the final release of VS 2005, and a number of folks who previously had a lot of concerns have posted positive impressions of the new model lately.

     

    One of the things we on the team still weren’t happy with, though, was the level of support in the vanilla product for more advanced deployment configurations/options beyond the core "Publish Web" scenarios built-into VS 2005 – specifically around assembly naming/output, advanced MSBuild customization, and other common scenarios that we’ve heard requests for over the years (for example: the ability to modify connection string settings depending on the build configuration, etc).

     

    A couple of guys on my team have cranked over the last 2 months adding richer support for these scenarios that integrate nicely in the shipping product.  We’ve packaged up this work in a new free download we call “VS 2005 Web Deployment Projects” and which we worked to make sure was available for download this week (which is the week of VS 2005 launch -- so basically immediately when the product releases).  This download does not touch any shipping binaries within VS 2005, but instead uses the extensibility support within the IDE and ASP.NET to integrate in a fairly cool way. 

     

    We think the resulting feature-set offers the best of both worlds – specifically the productivity benefits of rapid development brought with the new dynamic web project model, as well as the richness of a highly customized build/deployment system.

     

    VS 2005 Web Deployment Project Feature-Set

     

    The VS 2005 Web Deployment Project download adds a number of features that integrate nicely inside VS 2005 including:

     

    1) More control over the number of assemblies generated by a pre-compiled web project, as well as control over their naming.  Specifically, you can now generate a single named assembly for all pages + classes in your web project (for example: MyCompany.MyWebApp.dll).  Alternatively, you can also now optionally generate a separate named assembly for each directory of pages/controls in your project (for example: MyCompany.MyWebApp.SubFolder1.dll and MyCompany.MyWebApp.SubFolder2.dll).  This later option is particularly useful for large content web-apps where you would like the ability to incrementally patch code updates.

     

    2) The ability to utilize the full power of MSBuild to customize your build process.  You can now use MSBuild to define pre and post build rules, exclude folders from building, automatically create IIS vdirs and site mappings, add custom assembly versioning information, and add any custom MSBuild task you want to your build process.

     

    A VS 2005 Web Deployment Project stores all of its settings inside an MSBuild based project-file.  It also adds support for opening and editing the web deployment MSbuild project file directly in the IDE (w/ full intellisense support for it) – something that actually isn’t supported by any other project type in VS.

     

    3) The ability to define and use custom build-configurations inside Visual Studio, and define per-build configuration options.  In addition to using the built-in “debug” and “release” configurations, for example, you could define custom build configurations like “staging”.  You can then vary your web deployment MSBuild tasks and actions based on these.

     

    4) The ability to customize and modify a web application’s web.config file at deployment.  There is now IDE support for changing values likes connectionstrings or app-settings as part of the build process.  You can also vary these values based on the VS build configuration – so for example you could have one set of connectionstrings that you use for development (when you have the build configuration set to “debug”), and then have them modified as part of the build-process to your test/staging or production databases when you choose a “staging” or “release” build configuration in the IDE.

     

    There are also a host of other features to take advantage of.  The upcoming whitepapers on MSDN will go into more detail on these, as well as the 40+ new web deployment related MSBuild tasks that it ships with that you can use to customize things even further.

     

    Example Walkthrough of using a VS 2005 Web Deployment Project

     

    Below is a simple example that walks-through using the VS 2005 Web Deployment Project download to customize the deployment of a VS 2005 based web site project.

     

    Step 1: Development my web project

     

    Below is a screen-shot of a common web application solution structure – where I have 1 or more class library projects and then a web-project containing my web app.

     

     

    I can build the application using the standard web project model that ships with VS 2005, and take advantage of the productivity enhancements it provides.

     

    Step 2: Adding a VS 2005 Web Deployment Project

     

    As my web app progresses, I’ll need to think more about deployment.  To take advantage of the new deployment features the web deployment add-in provides, I can right-click on any of my web projects in the solution and add a Web Deployment Project (note: it is the 3rd item in the context menu below):

     

     

    This will prompt me for what I want to name the project and where to store its project file:

     

     

    The web deployment project will then show up as part of my solution:

     

     

    Associated in the e:\WebSiteDeployment directory is a new MSbuild based project file that contains deployment and build settings for my web-project.

     

    Note that a single web-site project can optionally have multiple deployment projects associated with it.  You can also have multiple web-site projects in a solution, each with a separate web deployment project (for example: a user control library project that you pre-compiled and then copied into another web app project that used it).

     

    Step 3: Setting Build and Deployment Options

     

    To customize build and deployment settings I can either use the built-in GUI property pages for the deployment project, or edit the MSBuild file directly.  I’ll show this second more advanced option later – for right now I can just right-click and pull up the property pages for the project, or double click on the WebSiteDeployment node (which is a short-cut for the same thing) to customize its properties.

     

    There are several screens of information (the MSDN whitepaper will go into them all – for here I’ll just show a few highlights).  One thing to note is that the settings are configured per-VS build configuration – so you can have one set of options for “debug”, one set of options for “release” and optionally define your own build configurations like “staging” and configure custom options for that build configuration as well.  I’m going to change the settings below to apply for the “release” build configuration.

     

    Here are a few of the more common things developers will want to control:

     

    1) Developers can control whether to pre-compile the web entirely, or to support html source updates.  Only the later option was supported in VS 2003 – and meant that you always had to deploy your .aspx source files on your production server (these were in turn dynamically compiled by ASP.NET at runtime the first time the app was run).  ASP.NET 2.0 still supports this compile option (we call it the “allow updates” option in VS 2005).  ASP.NET 2.0 also now supports a mode where you can optionally compile everything inside VS – including the .aspx/.ascx control definitions and html source.  This produces a more efficient version of the app, and eliminates the need for a first-time dynamic compile performance hit when your app is run.  It also allows you to protect more of the IP of your site, and enables you better compile-time checking of your application.  The first property page in the web deployment project allows you to choose either this new compile mode, or the preserve .aspx source mode that VS 2003 used.

     

    2) Developers can control what granularity of assembly output they want the website compiled down to, as well as what names to use for the assemblies (this is controlled on the output assemblies tab):

     

     

    The default option is to merge the entire web-site into a single assembly that you can name however you want.  This merges the output of all page/control compilation, app_code, and web-services into a single assembly (leaving one file to deploy). 

     

    There are other options you can choose as well for more granular control over the assembly generation.  For example, the second option above lets you compile each folder in your website into a separate named assembly (for example: MyCompany.MyWebApp.Folder1, MyCompany.MyWebApp.Folder2).  This is useful for patching large applications where you want to make a tactical update to just a portion of the site.

     

    If you have an AssemblyInfo.cs/.vb class in your app_code directory, the deployment project will use the meta-data it contains to version the produced assemblies.  Alternatively, you can also set the version information specifically in the IDE.  This in turn saves it as an MSBuild variable in your project file.  You could optionally use a custom MSbuild task to set this variable dynamically at build-time (for example: to use a policy like we do at Microsoft where the build number is based on the current date).

     

    3) The developer can then optionally use the deployment tab for other common deployment scenarios:

     

     

    One of these is the ability to replace the application’s web.config settings at build-time.  This can be done on a configuration section by section basis.  Simply list the name of the section to replace, and an XML file containing the replacement settings.  You can choose to have them replaced either in-line within the web.config file (the default), or to use the new configSource attribute option in ASP.NET 2.0 to dynamically point the web.config file at external configuration files that contain the values.

     

    Because all values in the settings dialog can be configured on a per-VS build configuration basis, this means that you can have one set of configuration file replacement settings per build configuration (for example: one connectionstring setting for “debug”, one connectionstring setting for “staging” and one connectionstring setting for “release”). 

     

    The other options included on this dialog is the ability to dynamically create and map an IIS vroot to the output directory as part of the build process, as well as the ability to delete the app_data directory as a post-build step (useful in cases where you want to delete the SQL Express database you’ve been using for development, and instead map your Membership, Roles, Profile, Personalization and HealthMon providers to a full SQL Server production database).

     

    Step 4: Adding Optional Advanced MSBuild File Customization Rules

     

    The above GUI property pages provide support for the most common build configuration settings.  One neat thing about the Web Deployment Projects, though, is that there is easy IDE support for dropping down into the MSBuild file directly and customizing things further.

     

    To-do this in the IDE, simply right click on the web deployment project and select “Open Project File”:

     

     

    This will bring up an XML editor with intellisense support for the project file:

     

     

    You can make changes, and then hit save to update things dynamically.

     

    The web deployment project adds support for pre and post build events that you can use to customize things.  For example, if you wanted to make sure a custom directory was created in your generated app after building, you could use the built-in MSbuild <MakeDir> task in the AfterBuild event:

     

      <Target Name="AfterBuild">

        <MakeDir Directories="$(TargetDir)\Upload" />

      </Target>

     

    If you want to exclude a “Test” directory that contains some sample test pages from building in your release configuration you could add something like this:

     

      <ItemGroup>

        <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Test\**\*.*"/>

      </ItemGroup>

     

    Note that you can use wild-card extensions when excluding things (above it is using *.* to exclude everything under the test directory) – so you can get quite fancy with your exclude rules.  MSBuild itself ships with tons and tons of built-in build tasks (like MakeDir).  The Web Deployment Project download adds support for another 40+ custom tasks specific to web application development/deployment.  The really cool thing is that it is also easy to build your own MSBuild tasks and add them to projects as well.

     

    Once you’ve made any custom tweaks, just hit save on the project file and close the window.  Note that you can still use the property page dialogs above even after customizing the project file – it will preserve your settings and not blow them away.

     

    Step 5: Building the Web Deployment Project

     

    Now that I have my deployment project all setup, I can simply do a “Build Solution” to build all the projects in my solution – including my new web deployment project.  This will then generate an output folder for my website.  Contained within it is a \bin directory that has two assemblies (one for my data class library, and one for my web project):

     

     

    The web.config file for my application has also been updated to have my production connectionstring settings.

     

    One typical optimization that we’ll recommend would be to only build the web deployment project when your application is ready to be deployed – and not during actual development (instead when actively developing just work with the web project directly as normal).  You can easily configure this in the VS build configuration manager:

     

     

    For example: with the above settings we are configuring the WebSiteDeployment project to not build when the “debug” release configuration is set – and only do so when in “release” mode.

     

    You can then use the build configuration drop-down on the toolbar to quickly switch between debug and release modes depending on where you are with the project:

     

     

    Step 6: Optional Setup Project

     

    One last bonus step that is also possible is adding a “Web Setup” project into our above solution.  This is a standard VS 2005 project type that supports packaging a .msi file along with logic to create a vroot and deploy an application when executed:

     

     

    I can easily configure the WebSetup project to pipe in the output from my WebSiteDeployment project into the MSI. 

     

    Then, while I select “Build Solution” again I’ll build my web deployment project, pipe it into the setup project, and I’ll be left with a .MSI setup program for my web application that will walk me through creating an IIS vroot and deploy my production app on a web-server when run:

     

     

    Next Steps

     

    Our plan is to post the first release of the VS 2005 Web Deployment Project for free download on MSDN this week.  We'll then gather and incorporate feedback and release an updated version later this year. 

     

    We hope you find it useful.  Let us know what you think and what additional features and MSBuild tasks you’d like to see added to it.

     

    Thanks,

     

    Scott

     

  • Behind the Scenes Video and some Interesting ASP.NET 2.0 Stress Stats

    I’m doing the keynote Monday night at the ASP.NET/VS Connections conference in Las Vegas.  It is a great conference and one I’ve presented at for years now.

     

    This year I decided to-do something a little special and include a short “behind the scenes” video in my presentation that walks through how we developed ASP.NET 2.0 and Visual Web Developer.  I spent most of Friday running around with a video camera filming various people on my team and having them walkthrough a design spec, some of the code, an automated test, our test execution environment, our stress lab, and performance profiling.  I then spent all day yesterday editing it down to about 8 minutes (someone once told me that you spend an average of 1 hour editing for each minute of final video -- which turned out to be roughly accurate).  

     

    A few interesting stats that the stress team shared while I was filming them:

     

    -- We run a total of 118 stress variations in the lab.  Some do normal things like data access, standard page rendering, etc.  Others simulate memory leaks, repeated app-domain restarts, crashes, and deadlocks (where the goal is to make sure the worker process recovers and the server stays up).

     

    -- We put an average of 7,380 hours of stress testing on each build of ASP.NET 2.0 that we produced this year (note: we have a heck of a lot of stress servers).

     

    -- Our lab throws 15 billion HTTP requests per day at ASP.NET servers in our lab.

     

    -- All stress variations passed at 100% for the final build we released.

     

    If you are coming to the conference, you’ll get a chance to see the blinking server lights of all this activity in the video (along with hopefully a few other interesting things).

     

    Scott