Web Application Projects Officially released!
Monday, May 08, 2006 8:21 PM

Web Application Projects has been released!  It live at:

 

http://msdn.microsoft.com/asp.net/reference/infrastructure/wap/default.aspx

 

New since RC1:

 

  • Team Build Support with VSTS
  • Strongly-typed access to resources defined in App_GlobalResources
  • Edit and Continue Support (To Enabled check Project Properties Web Tab)
  • Numerous bug fixes…. 

Web Application Projects now provided a similar development style and compilation model as was used in Visual Studio 2003, but with full ASP.NET 2.0 support!

 

Hope this helps,
Brad.

by BradleyB | with no comments
How to share dynamic URLs across multiple Web Application Projects
Thursday, May 04, 2006 3:24 PM

I was recently asked how to configure a Dynamic URL so that it could be updated in machine.config and affect all Web Application Projects calling that Web Reference on that machine.  This is fairly straight forward in VS03 and in VS05 Web Site projects.

In both VS03 and in VS05 Web Site projects the Web Reference proxies are generated to lookup the dynamic url form the <appSettings> section of web.config

Web.config

  <appSettings>
     <add key="localhost.WebService" value="http://localhost/test/WebService.asmx"/>
</appSettings>

 

Proxy Generated:

 

        /// <remarks/>
        public WebService() 
           string urlSetting = System.Configuration.ConfigurationManager.AppSettings["localhost.WebService"];
                  if ((urlSetting != null)) {
                this.Url = urlSetting;
            }
            else {
                this.Url = "http://localhost/test/WebService.asmx";
            }
        }

 

 

Since the <appSettings> section rolls up from machine.config it's easy to put this setting in machine.config remove the entry from  web.config and you're all set.

However, in VS05 WinForm projects and Web Applicaiton Project the proxy is generated to use the  <applicationSettings> section.

 

Web.config

 

    <configSections>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="MainWeb.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
    </configSections>

    <
applicationSettings>
        <MainWeb.Properties.Settings>
            <setting name="MainWeb_localhost_WebService" serializeAs="String">
                <value>http://localhost/test/WebService.asmx</value>
            </setting>
        </MainWeb.Properties.Settings>
    </applicationSettings>

 

 

Proxy Generated:

 

        /// <remarks/>
        public WebService() {
            this.Url = global::MainWeb.Properties.Settings.Default.MainWeb_localhost_WebService;
            if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
                this.UseDefaultCredentials = true;
                this.useDefaultCredentialsSetExplicitly = false;
            }
            else {
                this.useDefaultCredentialsSetExplicitly = true;
            }
        }

As you can see the proxy generated is very different depending on the type of project you’re using.  If you want to specify a dynamic URL in machine.config that can be overridden in web.config.  It turns out that was very easy to do in VS03 and in Web Site projects because they simply used <appSettings>.  However with WinForm projects and WAP we now getting the settings from the System.Configuration.ClientSettingsSection. See the definition under <configSections> above. 

this.Url = global::MainWeb.Properties.Settings.Default.MainWeb_localhost_WebService; 

Because the generated proxy is assuming that the URL is coming from a configuration section named <MainWeb.Properties.Settings>, you’ll have to make sure you have one defined at the machine.config level. 

You’ll need to add these both to machine.config: 

    <configSections>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="MainWeb.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
    </configSections> 

    <applicationSettings>
        <MainWeb.Properties.Settings>
            <setting name="MainWeb_localhost_WebService" serializeAs="String">
                <value>http://localhost/test/WebService.asmx</value>
            </setting>
        </MainWeb.Properties.Settings>
    </applicationSettings>

Once this is done your proxy will always find the value from machine.config unless overridden in web.config. 

This get’s more complicated if you’re trying to share the Dynamic URL across multiple applications.  To share a Dynamic URL across applications you’ll want to make sure that the proxy in each WAP project is using the same <applicationSettings> entry.  

The best way to do this is to create a class library project will all the Web References that you want to share.  For example I created one named WebRefLibrary.  The config entries for this library project are as follows. 

    <configSections>
        <sectionGroup name="applicationSettings">
            <section name="WebRefLibrary.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
    </configSections>

    <applicationSettings>
        <WebRefLibrary.Properties.Settings>
            <setting name="WebRefLibrary_localhost_WebService" serializeAs="String">
                <value>http://localhost/test/WebService.asmx</value>
            </setting>
        </WebRefLibrary.Properties.Settings>
    </applicationSettings> 

The next step is to add these entries to machine.config.  Once that is done I can add a reference to WebRefLibrary to each of my WAP Projects.  Even with out adding anything to the web.config of those WAP they will get the dynamic URL from machine.config. 

However I can now update the web.config in any of my WAP projects to override the dynamic URL. 

    <applicationSettings>
        <WebRefLibrary.Properties.Settings>
            <setting name="WebRefLibrary_localhost_WebService" serializeAs="String">
                <value>http://localhost/Production/NewWebService.asmx</value>
            </setting>
        </WebRefLibrary.Properties.Settings>
    </applicationSettings> 

By using a Class Library project containing my Web References I’m able to share a dynamic URL across Web Application Projects and update with the URL by a single change to machine.config.

Hope this helps,
Brad.

How to open a website in Visual Studio 2005 from the command line
Friday, December 09, 2005 5:54 PM

I’ve seen several queries asking how to launch Visual Studio 2005 opening a specific folder as a website from the command line.  Unfortunately Visual Studio 2005 does not support this by default but you can enable the scenario by writing a macro.

 

To do this, create a new macro either in an existing module or in a new module.  For this example I’m going to add a module call Website to the MyMacros project.

 

If you’re new to macros in Visual Studio 2005, select menu Tools/Macros/Macros IDE, then select the MyMacros project and add a module.

 

Before you can use the new Website extensibility objects within VS you’ll need to add a reference to VsWebSite.Interop.dll. 

 

Once added you can add the following code:

 

Public Module Website

    Sub OpenWebsite(Optional ByVal path As String = "")

        If (String.Compare(path, String.Empty) = 0) Then

            MsgBox("Must supply a folder path to the OpenWebsite macro", MsgBoxStyle.OkOnly)

        Else

            Dim webPkg As VsWebSite.VSWebPackage

            webPkg = DTE.GetObject("WebPackage")

            webPkg.OpenWebSite(path, VsWebSite.OpenWebsiteOptions.OpenWebsiteOption_None, False)

        End If

    End Sub

End Module

 

 

After this code is added you’ll be able to run the macro.  You can test it out in the command window.

 

From the Command Window in VS:

 

>Macros.MyMacros.Website.OpenWebsite C:\MyProjects\MyCompany\CompanySite

 

From the Command Line:

 

devenv /command "Macros.MyMacros.Website.OpenWebsite C:\MyProjects\MyCompany\CompanySite"

 

After its working you can register a shell command enabling an “Open as Visual Studio Website” command on any folder in windows explorer.

 

To do this copy the following into a OpenWebsite.reg file and run it.

 

Windows Registry Editor Version 5.00

 

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\OpenVSWeb]

@="Open as Visual Studio Website"

 

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\OpenVSWeb\command]

@="devenv.exe /command \\\"Macros.MyMacros.Website.OpenWebsite %1\\\""

 

 

Now you should be able to right click on a folder in Windows Explorer and select “Open as Website”.

 

Hope this helps,

Brad.

Tips to optimize design-time build performance for Web Sites in Visual Studio 2005
Tuesday, December 06, 2005 1:03 AM
There have been a number of posts with tips to improve build performance within Visual Studio 2005.  I've consolidate these posts and other tips into a single post of techniques for common problems.

Do not disable batch compilation
Make sure web.config does not have <compilation batch="false" />
The default is “true” so unless it’s explicitly set to “false” you’re ok.

Some post have recommended disabling batch compilation to address a migration issue with circular references.  Unfortunately this dramatically impacts build performance.  You're much better off addressing the circular references than to disabling batch compilation.

Leverage Server-side Compilation
Visual Studio 2005 is leveraging ASP.Net 2.0 server-side compilation.  The IDE is primarily validating that the site will compile.  For most edit/run iterations it's not really necessary to validate/build the entire site on every F5 or solution build.

Change Build options for the web site project:  (Property pages <shift>F4 -> Build)
    “Start Action (F5)” should be either "build page" or "no build".  -  Improves F5 performance
    “Build Solution Action” uncheck “Build Web as part of solution.”  -  Makes <ctrl><shift>b very fast.

While this does improve build performance because ASP.Net is only compiling the files needed for the request on F5, it doesn't help the developer identify all the compilation issues within the IDE before running.  There are a couple of techniques you an use to help with this.
  1. Move App_Code files into a separate class library project and reference it form the web site project.  This will improve build performance and provide all compilation errors for these class files within the IDE.
  2. Add a Web Deployment Project to the solution.  Configure the Web Deployment project so that it only builds for the release configuration.  This will allow you to completely validate the site before deployment without compromising the performance of the edit/run iterations under the debug configuration.

Move App_Code files into a separate class library project
I'm repeating this tip because even if you don't change the default build options you can improve build performance by moving the files from App_Code into a separate class library project.

Check for conflicting dependencies
If you do have conflicting dependencies, the web site project will do a full clean rebuild on every build even if only a page changes.  The problem is when you add a file based references that have a common dependency but to different versions of that dependency.   A file based references have a .dll.refresh file in the bin folder.  The .refresh file has the path to the original assembly.  These paths are checked on every build.

In this example we have two assemblies, A.dll and B.dll both dependent on Foo.dll.

    A.dll -> dependent on Foo.dll
    B.dll -> dependent on Foo.dll

When A.dll is refreshed the project system will discover the dependency on Foo.dll and copy it into bin. Likewise when B.dll is refreshed Foo.dll will be copied if different than the one already in bin. The problem is that when a class library is built by a class library project in VS it caches the dependencies. So as you can see here Class Libraries A and B both have a private copy of Foo.

ClassLibraryA
    A\bin\debug\A.dll
    A\bin\debug\Foo.dll

ClassLibraryB
    B\bin\debug\B.dll
    B\bin\debug\Foo.dll

ClassLibraryFoo
    Foo\bin\debug\Foo.dll

If ClassLibraryFoo is updated and only ClassLibraryB is recompiled then ClassLibraryB has a updated copy for Foo.dll but ClassLibraryA does not. When the web project is built, the refresh of A is copying in it's copy of Foo and the refresh of B is copying in it's copy. Each time Foo is copied because it's different than the one already in bin.

Because the bin is changing with every VS build the ASP.Net compilation cache is invalidated forcing a full build.  Thus every build is a full build.

To fix this problem do one of the following:

  1. Add class libraries A,B and Foo to the same solution as the web site and replace the file base references with project references.
  2. Always build all consumers of a dependency when the dependency changes.
  3. Remove the .refresh files and manually update as needed.

Turn off AutoToolboxPopulate in the Windows Forms Designer options. 
Some user have reported a hang during build.  This was resolve by turning off AutoToolboxPopulate.
http://forums.asp.net/1108115/ShowPost.aspx

    Tools/Options/Windows Forms Designer/General/AutoToolboxPopulate = False

Disable validation for HTML editing
By default the HTML/ASPX editor performs html validation in the background while the file is open.  This does not normally impact performance unless there are numerous error to report.  So if you're already compliant, turning it off won't save you much but if you do have errors and don’t' need to fix them, turning if off can make a difference. 
http://msdn2.microsoft.com/en-us/library/0byxkfet.aspx


You'll be surprised at the performance improvement these changes will make for the edit/run iterations of your daily workflow.  My sample solution with 2 class libraries and 1 web site went from 17 seconds to build to less than a second.  While these techniques may not be right for every project, the improvements are significant enough that you should try them out and evaluate them for yourself.

Hope this helps,
Brad.

How to auto-increment assembly version using a custom MSBuild task
Friday, December 02, 2005 12:31 PM

The assembly version string has the format “major.minor.build.revision”, such as 2.0.50727.42.  Here is a sample on how to create a custom MSBuild task for Web Deployment Projects  to auto-increment the build and revision portion of your version strings with each build.

 

Web Deployment Projects provide a way to pre-compile a Visual Studio 2005 Web Site project into a single assembly.  It also allows you to specify the AssemblyFileVersion and AssemblyVersion for this assembly.

 

These values can be set in the Project Properties dialog of the Web Deployment Project.  Once set the following will be added to the Web Deployment Project file.

 

  <ItemGroup>

    <AssemblyAttributes Include="AssemblyFileVersion">

      <Value>2.0.0.0</Value>

    </AssemblyAttributes>

    <AssemblyAttributes Include="AssemblyVersion">

      <Value>2.0.0.0</Value>

      <AutoIncrement>true</AutoIncrement>

    </AssemblyAttributes>

  </ItemGroup>

 

The Microsoft.WebDeployment.targets file includes a target named GenerateAssemblyInfo that will use the @(AssemblyAttributes) item collection defined above to dynamically create an AssemblyInof.cs file.  This file is compiled into an assembly and passed to aspnet_merge.exe using its –copyattrs argument.

 

This is great if you want to fix the version to a specific value, but what if you want to generate a new build number with every build.  After all the format of version string is “major.minor.build.revision”.

 

To do this we’ll need to dynamically generate the AssemblyAttributes item collection at build time instead of statically declaring their values in the Web Deployment Project file.

 

First create a custom MSBuild task.  MSBuild tasks are classes derived from Microsoft.Build.Utilities.Task that override the Execute() method.  You can learn more about writing MSBuild tasks from How To: Write a Task

 

Here is a sample MSBuild task that will increment build and revision numbers. 

 

Contents of file IncrementBuildNumber.cs:

 

using System;

using System.IO;

using Microsoft.Build.Utilities;

using Microsoft.Build.Framework;

 

namespace MyTasks

{

    public class IncrementBuildNumber : Task

    {

        string m_fileName;      // Text file containing previous build number

        long m_buildNumber;     // Build number based on current date. 12/2/2005 would be 51202

        long m_revisionNumber;  // Revision number, increments within a day with each new day starting at 0

 

        /// <summary>

        /// MSBuild entry point into this task.

        /// </summary>

        public override bool Execute()

        {

            bool bSuccess = true;

            try

            {

                IncrementNumbers();

                Log.LogMessage(MessageImportance.Normal, "Build {0}.{1}", m_buildNumber, m_revisionNumber);

            }

            catch (Exception ex)

            {

                // Log Failure

                Log.LogErrorFromException(ex);

                Log.LogMessage(MessageImportance.High, "Failed to increment Build Number!");

                bSuccess = false;

            }

            return bSuccess;

        }

 

        /// <summary>

        /// Task argument set MSBuild project file

        /// </summary>

        [Required]

        public string File

        {

            get { return m_fileName; }

            set { m_fileName = value; }

        }

 

        /// <summary>

        /// Task output available to MSBuild

        /// </summary>

        [Output]

        public long BuildNumber

        {

            get { return m_buildNumber; }

            set { m_buildNumber = value; }

        }

 

        /// <summary>

        /// Task output available to MSBuild

        /// </summary>

        [Output]

        public long RevisionNumber

        {

            get { return m_revisionNumber; }

            set { m_revisionNumber = value; }

        }

 

        /// <summary>

        /// Increments Build Number and Build Revision

        /// based on the numbers saved in a text file.

        /// </summary>

        private void IncrementNumbers()

        {

            // Set build number to current date, 12/02/2005 == 51202

            DateTime dDate = DateTime.Now;

            m_buildNumber = dDate.Year % 2000 * 10000;

            m_buildNumber += dDate.Month * 100;

            m_buildNumber += dDate.Day;

 

            // Defualt build revision to 0

            m_revisionNumber = 0;

 

            // Check for a previous build and revision number

            if (System.IO.File.Exists(m_fileName))

            {

                StreamReader sr = new StreamReader(m_fileName);

                string previousBuild = sr.ReadLine();

                sr.Close();

 

                string[] previousNumbers = previousBuild.Split('.');

 

                if (m_buildNumber == long.Parse(previousNumbers[0]))

                    m_revisionNumber = long.Parse(previousNumbers[1]) + 1;

            }

 

            // Write the current build numbers to the file

            StreamWriter sw = new StreamWriter(m_fileName);

            sw.WriteLine(string.Format("{0}.{1}", m_buildNumber, m_revisionNumber));

            sw.Flush();

            sw.Close();

        }

    }

}

 

Compile file IncrementBuildNumber.cs into the assembly MyTasks.dll

 

csc /t:library /r:Microsoft.Build.Utilities.dll;Microsoft.Build.Framework.dll /out:MyTasks.dll IncrementBuildNumber.cs

 

Copy the MyTasks.dll into the same directory as the Web Deployment Project.

 

Now that we’ve got our custom MSBuild task we need to modify the Web Deployment Project file to use our new custom task.

 

You can edit the project file by right clicking on the Web Deployment Project in the solution explorer and selecting “Open Project File” from the shortcut menu.

 

Once opened add a <UsingTask> between the <Project> and the first <PropertyGroup> to register the new custom IncrementBuildNumber task with MSBuild.

 

<!--

  Microsoft Visual Studio 2005 Web Deployment Project

  http://go.microsoft.com/fwlink/?LinkId=55111

-->

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <UsingTask TaskName="MyTasks.IncrementBuildNumber" AssemblyFile="MyTasks.dll" />

  <PropertyGroup>

     

  </PropertyGroup>

 

Next override the BeforeBuild target with the code below.

 

 

  <Target Name="BeforeBuild">

    <IncrementBuildNumber

      File = "$(MSBuildProjectDirectory)\BuildNumbers.txt">

      <Output TaskParameter="BuildNumber" PropertyName="BuildNumber"/>

      <Output TaskParameter="RevisionNumber" PropertyName="RevisionNumber"/>

    </IncrementBuildNumber>

 

    <CreateItem Include="AssemblyFileVersion" AdditionalMetadata="Value=2.0.$(BuildNumber).$(RevisionNumber)">

      <Output ItemName="AssemblyAttributes" TaskParameter="Include" />

    </CreateItem>

 

    <CreateItem Include="AssemblyVersion" AdditionalMetadata="Value=2.0.$(BuildNumber).$(RevisionNumber)">

      <Output ItemName="AssemblyAttributes" TaskParameter="Include" />

    </CreateItem>

 

  </Target>

 

 

In this sample we’re using a BuildNumbers.txt file to store the build numbers from each build.  It is passed to the IncrementBuildNumber task through the File property.  The $(MSBuildProjectDirectory) property is a built in property provided by MSBuild that specifies the directory containing the project file.

 

The BuildNumber and BuildRevision values are then copied from our custom MSBuild task IncrementBuildNumbers as MSBuild properties using the <Output> tags.

      <Output TaskParameter="BuildNumber" PropertyName="BuildNumber"/>

      <Output TaskParameter="RevisionNumber" PropertyName="RevisionNumber"/>

 

At this point there are now 2 new MSBuild properties $(BuildNumber) and $(RevisionNumber).  The next step is to dynamically create the AssemblyAttributes version strings using these properties.

 

    <CreateItem Include="AssemblyFileVersion" AdditionalMetadata="Value=2.0.$(BuildNumber).$(RevisionNumber)">

      <Output ItemName="AssemblyAttributes" TaskParameter="Include" />

    </CreateItem>

 

    <CreateItem Include="AssemblyVersion" AdditionalMetadata="Value=2.0.$(BuildNumber).$(RevisionNumber)">

      <Output ItemName="AssemblyAttributes" TaskParameter="Include" />

    </CreateItem>

 

Once created they will be automatically picked up the GenerateAssemblyInfo target provided in the Web Deployment Project.

 

Be sure to delete the statically declared AssemblyAttributes Items for AssemblyFileVersion and AssemblyVersion.

 

Delete any of these entries from your project file.

    <AssemblyAttributes Include="AssemblyFileVersion">

      <Value>2.0.0.0</Value>

    </AssemblyAttributes>

    <AssemblyAttributes Include="AssemblyVersion">

      <Value>2.0.0.0</Value>

      <AutoIncrement>true</AutoIncrement>

    </AssemblyAttributes>

 

You will get a build error if forget to delete these statically declared values.

 

Now let’s build and see what happens.

 

 

Microsoft (R) Build Engine Version 2.0.50727.42

[Microsoft .NET Framework, Version 2.0.50727.42]

Copyright (C) Microsoft Corporation 2005. All rights reserved.

 

Build started 12/2/2005 8:46:42 AM.

__________________________________________________

Project "C:\MyProjects\MyWeb\MyWeb_deploy\MyWeb_deploy.wdproj" (default targets):

 

Target BeforeBuild:

    Build 51202.0

Target AspNetCompiler:

    C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v /MyWeb -p C:\MyProjects\MyWeb\MyWeb -u -f -d C:\MyProjects\MyWeb\MyWeb_deploy\Debug\

    Updateing web.config compilation debug = 'True' ...

    Successfully updated web.config compilation debug = 'True' ...

Target GenerateAssemblyInfo:

    Generating AssemblyInfo ...

    Setting [assembly: AssemblyFileVersion("2.0.51202.0")]

    Setting [assembly: AssemblyVersion("2.0.51202.0")]

    Successfully Generated AssebmlyInfo ...

    C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Csc.exe /out:C:\MyProjects\MyWeb\MyWeb_deploy\AssemblyInfo\Debug\AssemblyInfo.dll /target:library C:\MyProjects\MyWeb\MyWeb_deploy\AssemblyInfo\Debug\AssemblyInfo.cs

Target AspNetMerge:

    Running aspnet_merge.exe ...

    C:\Program Files\MSBuild\Microsoft\WebDeployment\v8.0\aspnet_merge.exe C:\MyProjects\MyWeb\MyWeb_deploy\Debug -o MyWeb -copyattrs C:\MyProjects\MyWeb\MyWeb_deploy\AssemblyInfo\Debug\AssemblyInfo.dll -debug

    Successfully merged 'C:\MyProjects\MyWeb\MyWeb_deploy\Debug'.

 

Build succeeded.

    0 Warning(s)

    0 Error(s)

 

Time Elapsed 00:00:10.29

 

 

Since this is the first build today it’s getting a build number based on the current date 51202 and the revision is 0.  What happens if we build again?

 

 

Microsoft (R) Build Engine Version 2.0.50727.42

[Microsoft .NET Framework, Version 2.0.50727.42]

Copyright (C) Microsoft Corporation 2005. All rights reserved.

 

Build started 12/2/2005 8:46:56 AM.

__________________________________________________

Project "C:\MyProjects\MyWeb\MyWeb_deploy\MyWeb_deploy.wdproj" (default targets):

 

Target BeforeBuild:

    Build 51202.1

Target AspNetCompiler:

    C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v /MyWeb -p C:\MyProjects\MyWeb\MyWeb -u -f -d C:\MyProjects\MyWeb\MyWeb_deploy\Debug\

    Updateing web.config compilation debug = 'True' ...

    Successfully updated web.config compilation debug = 'True' ...

Target GenerateAssemblyInfo:

    Generating AssemblyInfo ...

    Setting [assembly: AssemblyFileVersion("2.0.51202.1")]

    Setting [assembly: AssemblyVersion("2.0.51202.1")]

    Successfully Generated AssebmlyInfo ...

    C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Csc.exe /out:C:\MyProjects\MyWeb\MyWeb_deploy\AssemblyInfo\Debug\AssemblyInfo.dll /target:library C:\MyProjects\MyWeb\MyWeb_deploy\AssemblyInfo\Debug\AssemblyInfo.cs

Target AspNetMerge:

    Running aspnet_merge.exe ...

    C:\Program Files\MSBuild\Microsoft\WebDeployment\v8.0\aspnet_merge.exe C:\MyProjects\MyWeb\MyWeb_deploy\Debug -o MyWeb -copyattrs C:\MyProjects\MyWeb\MyWeb_deploy\AssemblyInfo\Debug\AssemblyInfo.dll -debug

    Successfully merged 'C:\MyProjects\MyWeb\MyWeb_deploy\Debug'.

 

Build succeeded.

    0 Warning(s)

    0 Error(s)

 

Time Elapsed 00:00:13.26

 

 

The build number stays as 51202 but the revision number has incremented to 1.  The revision number will continue to increment for each build during the day then starting tomorrow the build number will change to 51203 and the revision will reset to 0.

 

This is just one example of how to increment build numbers during a build.  In this case the build numbers are coming from a text file and being auto incremented by a custom MSBuild task.

 

There are other techniques that you could use.  For example MSBuild also exposes all environment variables from the command shell.  So if you primarily build from a command line or batch build environment you could simply set an environment variable for BuildNumber and RevisionNumber.

 

c:\set BuildNumber=51202

c:\set RevisionNumber=2

 

Using this technique you can go back to statically defining your AssemblyAttributes and simply reference the environment variables.

 

  <ItemGroup>

    <AssemblyAttributes Include="AssemblyFileVersion">

      <Value>2.0.$(BuildNumber).$(RevisionNumber)</Value>

    </AssemblyAttributes>

    <AssemblyAttributes Include="AssemblyVersion">

      <Value>2.0.$(BuildNumber).$(RevisionNumber)</Value>

    </AssemblyAttributes>

  </ItemGroup>

 

While simpler to implement it is not auto-incrementing the revision with each build, instead it’s relying on an external build process to set these values.  MSBuild is an extremely powerful build tool exposing many capabilities.  The techniques you use will vary depending on your needs.

 

Hope this helps,

Brad

More Posts « Previous page