-
|
|
My book on MSBuild and Team Build
| Archives and Categories
Friday, June 15, 2012
I have written a few posts recently describing out updated web publish experience. These new experience is available for both Visual Studio 2010 as well as Visual Studio 2012 RC. You can use the links below to download these updates in the Azure SDK download. Below are links for both versions.
The Web Publish experience is chained into VS 2012 RC so if you have installed VS 2012 RC with the Web features then you already have these features.
Thanks,
Sayed Ibrahim Hashimi @SayedIHashimi
Friday, February 25, 2011
Today I saw a post on stackoverflow.com asking Using Microsoft AJAX Minifier with Visual Studio 2010 1-click publish. This is a response to that question. The Web Publishing Pipeline is pretty extensive so it is easy for us to hook in to it in order to perform operation such as these. One of those extension points, as we’ve blogged about before, is creating a .wpp.targets file. If you create a file in the same directory of your project with the name {ProjectName}.wpp.targets then that file will automatically be imported and included in the build/publish process. This makes it easy to edit your build/publish process without always having to edit the project file itself. I will use this technique to demonstrate how to compress the CSS & JavaScript files a project contains before it is published/packaged.
Eventhough the question specifically states Microsoft AJAX Minifier I decided to use the compressor contained in Packer.NET (link in resources section). I did this because when I looked at the MSBuild task for the AJAX Minifier it didn’t look like I could control the output location of the compressed files. Instead it would simply write to the same folder with an extension like .min.cs or .min.js. In any case, when you publish/package your Web Application Project (WAP) the files are copied to a temporary location before the publish/package occurs. The default value for this location is obj\{Configuration}\Package\PackageTmp\ where {Configuration} is the build configuration that you are currently using for your WAP. So what we need to do is to allow the WPP to copy all the files to that location and then after that we can compress the CSS and JavaScript that goes in that folder. The target which copies the files to that location is CopyAllFilesToSingleFolderForPackage. (To learn more about these targets take a look at the file %Program Files (x86)%\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets.) To make our target run after this target we can use the MSBuild AfterTargets attribute. The project that I created to demonstrate this is called CompressBeforePublish, because of that I create a new file named CompressBeforePublish.wpp.targets to contain my changes.
<_JavaScriptFiles Include="$(_PackageTempDir)\Scripts\**\*.js" />
<_CssFiles Include="$(_PackageTempDir)\Content\**\*.css" />
Here I’ve created one target, CompressJsAndCss, and I have included AfterTargets=”CopyAllFilesToSingleFolderForPackage” which causes it to be executed after CopyAllFilesToSingleFolderForPackage. Inside this target I do two things, gather the files which need to be compressed and then I compress them.
1. Gather files to be compressed
<_JavaScriptFiles Include="$(_PackageTempDir)\Scripts\**\*.js" />
<_CssFiles Include="$(_PackageTempDir)\Content\**\*.css" />
Here I use an item list for both JavaScript files as well as CSS files. Notice that I am using the _PackageTempDir property to pickup .js & .css files inside the temporary folder where the files are written to be packaged. The reason that I’m doing that instead of picking up source files is because my build may be outputting other .js & .css files and which are going to be published. Note: since the property _PackageTempDir starts with an underscore it is not guaranteed to behave (or even exist) in future versions.
2. Compress files
I use the Packer task to compress the .js and .css files. For both sets of files the usage is pretty similar so I will only look at the first usage.
Here the task is fed all the .js files for compression. Take a note how I passed the files into the task using, %(_JavaScriptFiles.Identity), in this case what that does is to cause this task to be executed once per .js file. The %(abc.def) syntax invokes batching, if you are not familiar with batching please see below. For the value of the output file I use the _PackageTempDir property again. In this case since the item already resides there I could have simplified that to be @(_JavaScriptFiles->’%(FullPath)’) but I thought you might find that expression helpful in the case that you are compressing files which do not already exist in the _PackageTempDir folder.
Now that we have added this target to the .wpp.targets file we can publish/package our web project and it the contained .js & .css files will be compressed. Note: Whenever you modify the .wpp.targets file you will have to unload/reload the web project so that the changes are picked up, Visual Studio caches your projects.
In the image below you can see the difference that compressing these files made.

You can download the entire project below, as well as take a look at some other resources that I have that you might be interested in.
Sayed Ibrahim Hashimi
Resources
Thursday, November 11, 2010
Today I just saw a question posted on stackoverflow.com asking Why are some Web.config transforms tokenised into SetParameters.xml and others are not? Let me give some background on this topic for those who are not aware of what the question is.
With Visual Studio 2010 when you package your application using the Build Deployment Package context menu option, see image below.

When build the package by default the package will be created in obj\{Configuration}\Package\{ProjectName}.zip where {Configuration} is the current build configuration, and {ProjectName} is the name of the project. So in this case I since I’m building with Debug and the project name is MvcApplication1 the package will be placed at obj\Debug\Package\MvcApplication1.zip. If you take this package and then import into IIS 7 with the “Import Application” option shown below. Note: The machine must have the Web Deployment Tool (aka MSDeploy) installed.

Once you click on Import Application then browse out to the package you will be shown a screen which prompts your for parameters. Its shown below.

On this screen you can see that we are prompting for a couple parameter values here. One is an IIS setting, Application Path, and the other is a connection string which will be placed inside the web.config file. If your Web Application Project (WAP) had 5 different connection strings then they would automatically show up here on this page. Since connection strings are replaced so often we create parameters for all connection strings by default. You can define new parameters on your own, quite easily actually, but that is the topic for another blog post.
Now back to the question. He is asking why do we “tokenize” the connection strings in web.config. To clarify take a look at my web.config file below.
<configuration>
<appSettings>
<add key="setting01" value="value01"/>
</appSettings>
<connectionStrings>
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
After I perform a package this will get changed. Take a look @ the web.config file which resides in the package (you can get to the file at obj\{CofigurationName}\Package\PackageTmp\web.config). You will see what is shown below.
<configuration>
<appSettings>
<add key="setting01" value="value01"/>
</appSettings>
<connectionStrings>
<add name="ApplicationServices"
connectionString="$(ReplacableToken_ApplicationServices-Web.config Connection String_0)"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
So his question is why is the connection string replaced with $(ReplacableToken_ApplicationServices-Web.config Connection String_0) and nothing else is? We do this because we do not want you to accidently copy your web to a location and have it executing SQL statements against a SQL server which you did not intend. The idea is that you will create a package that you can deploy to many different environments. So the value that was in your web.config (or web.debug.config/web.release.config if you are using a web.config transformation) will not be placed inside the web.config in the package. Instead those values will be used as defaults in the package itself. We also create a SetParameters.xml file for you so that you can tweak the values. For my app see the MvcApplication1.SetParameters.xml file below.
<?xml version="1.0" encoding="utf-8"?>
<parameters>
<setParameter name="IIS Web Application Name"
value="Default Web Site/MvcApplication1_deploy" />
<setParameter name="ApplicationServices-Web.config Connection String"
value="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" />
</parameters>
The idea is that you can deploy your package in 2 ways. Through the IIS Manager which will prompt you for the parameters or you can deploy using msdeploy.exe with the –setParamFile switch to specify the path to the SetParameters.xml file. In this case I could create a QA01.SetParameters.xml file along with a QA02.SetParameters.xml file to deploy my web to my two QA servers. How do we do this?
How connection strings are tokenized
You might be wondering how the connection strings are tokenized to begin with. With Visual Studio 2010 we released web.config transformations, which all you to write terse web.config transformations inside of files like web.debug.config/web.release.config. When you package/publish your web these transform files are used to transform your web.config based on what you expressed in the appropriate transform file. We have an MSBuild task TransformXml which performs the transformation. We use that same task to tokenize the connection strings. If you are interested in the details take a look at %ProgramFiles32%\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets in the AutoParameterizationWebConfigConnectionStringsCore target.
Now what if you do not want the connection string tokenized?
Prevent tokenizing connection strings
If you want to prevent your web.config connection strings from being tokenized it’s pretty easy. All we need to do is the add a property to the build/package/publish process. We can do that in 2 ways. Edit the project file itself or create a file with the name {ProjectName}.wpp.targets where {ProjectName} is the name of your project. The second approach is easier so I use that. In my case it would be MvcApplication1.wpp.targets. The contents of the file are shown below.
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AutoParameterizationWebConfigConnectionStrings>false</AutoParameterizationWebConfigConnectionStrings>
</PropertyGroup>
</Project>
Note: You may need to reload the project in Visual Studio for this to take effect.
Inside of this file I have declared the property, AutoParameterizationWebConfigConnectionStrings, to be false. This is telling the Web Publishing Pipeline (WPP) that it should not replace replace the connection strings with tokens, instead leave them as they are.
Questions/Comments???
Other Resources
Sunday, August 15, 2010
A while back I posted an entry on How to build a package including extra files or exclude files a reader posted a question to StackOverflow.com asking how to exclude files from the created package based on the configuration for the project. He asked me to take a look at it so I figured it would be a good blog post.
From the previous post we can see that the way to exclude files from packaging is by declaring an item as follows.
<ItemGroup>
<ExcludeFromPackageFiles Include="Sample.Debug.xml">
<FromTarget>Project</FromTarget>
</ExcludeFromPackageFiles>
</ItemGroup>
So we need to extend this to only exclude files if the config is a certain value. Since MSBuild supports conditions on almost every element this is going to be a breeze. As an example I have created a sample web project with a scripts directory that has the following files.
In that folder there I there are two files which have ‘debug’ in the name of the file. We only want those to be included if the configuration is set to Debug, or another way of putting it is we want to exclude those files if the configuration is not Debug. So we need to create to add files to the ExcludeFromPackageFiles and guard it with the condition that the configuration is not debug. Here is that.
<Target Name="CustomExlucdeFiles" BeforeTargets="ExcludeFilesFromPackage">
<ItemGroup Condition=" '$(Configuration)'!='Debug' ">
<ExcludeFromPackageFiles Include="scripts\**\*debug*" />
</ItemGroup>
<Message Text="Configuration: $(Configuration)" />
<Message Text="ExcludeFromPackageFiles: @(ExcludeFromPackageFiles)" Importance="high" />
</Target>
You can see the item group defined above which does what we want. Please note that I put this inside of a target, CustomExcludeFiles, I will discuss why in a bit but let’s stay on topic now. So this is pretty straight forward when the item group is evaluated all files under scripts which have debug in the file name will be excluded if the configuration is not set to Debug. Let’s see if it works, I will build the deployment package once in both debug & release then examine the contents of the Package folder.
So we can see that the files were excluded from the Release package. Now back to why I declared the item group in a target instead of directly in the project file itself. I noticed that if I declare that item in the project file there are some visual issues with the representation in the Solution Explorer. To be specific the files show up as dups, see image below.
I have reported this to the right people, but for now this is a harmless issue with an easy workaround.
Sayed Ibrahim Hashimi
Monday, June 7, 2010
If you are doing any kind of web development and you are not familiar with the Web Platform Installer(WPI) then you need to take a look at it. I just installed WordPress on IIS 7 with just a few clicks and filled in a few text boxes. When you install WordPress there are some prerequisites like mySql and php. The WPI was smart enough to realize that I had neither installed, downloaded those, installed them and configured them. I was prompted for some info for those tools of course. I’ve also installed a few other apps using the WPI like, MSDeploy and dasBlog and I didn’t have any issues what so ever.
When using the WPI there are two main categories that can be installed, Web Platform and Web Applications. The Web Platform category includes items like frameworks (i.e. ASP.NET, PHP), Database (i.e. mySql) and other high level shared components. The Web Applications includes various web applications. Some others that I didn’t list previously include; DotNetNuke, nopCommerce, and umbarco just to name a few. I’m not sure how many apps are available but it looks like at least 50.
If you are an app creator and would like to share your app then you can visit the WPI Developer page for a starting point.
Wednesday, March 10, 2010
I just received a message from a reader asking about how he can extend the package process in Visual Studio 2010 RC to include files that his web project doesn't contain or reference. If you are not familiar with this Visual Studio 2010 has support for creating Web Packages now. These packages can be used with the Web Deployment Tool to simply deployments. The Web Deployment Tool is also known as MSDeploy.
He was actually asking about including external dependencies, but in this post I will show how to include some text files which are already written to disk. To extend this to use those dependencies should be pretty easy. Here is what I did:
- Created a new ASP.NET MVC 2 Project (because he stated this is what he has)
- Added a folder named Extra Files one folder above where the .csproj file is located and put a few files there
- In Visual Studio right clicked on the project selected “Unload Project”
- In Visual Studio right clicked on the project selected “Edit project”
Then at the bottom of the project file (right above the </Project> statement). I inserted the following XML fragments.
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="..\Extra Files\**\*">
<DestinationRelativePath>%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</_CustomFiles>
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>Extra Files\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
Here I do a few things. First I extend the CopyAllFilesToSingleFolderForPackage target by extending its DependsOn property to include my target CustomCollectFiles. This will inject my target at the right time into the Web Publishing Pipeline. Inside that target I need to add my files into the FilesForPackagingFromProject item group, but I must do so in a particular manner. Specifically I have to define the relative path to where it should be written. This captured inside the DestinationRelativePath metadata item. This is required because sometimes you may have a file which is named, or in a different folder, than it was originally. After you do that you will see that the web package that is created when you create a web package from Visual Studio (or from the command line using msbuild.exe for that matter) contains your custom files.
I just posted a blog about my upcoming talk discussing Web Deployments and ASP.NET MVC, once again check it out :)
Sayed Ibrahim Hashimi
Friday, October 9, 2009
I will be giving an online LiveMeeting Session hosted by Microsoft next week on Wednesday October 14, 2009 at 4 PDT (Redmond Time). The title is Simplifying Deployment with the Web Deployment Tool (MSDeploy). If you are not aware of MSDeploy it is a newly released tool to ease the pain of deploying ASP.NET sites. If you are doing any type of deployment of ASP.NET sites (Manual or Automated) then you must check out MSDeploy, it will change how you look at deployment of ASP.NET sites all together. Right now there is not an abundant amount of knowledge or material available on this tool, but I think that will change soon. Hopefully I can contribute to some of that. In any case, if you are available I would love to have you check out my session. There will be some guys from Microsoft on the line including the Program Manager of the Web Deployment Tool Vishal Joshi. I'm sure he will chime in when I try to mislead you guys by feeding your mis-information.
Here is the info about the presentation.
Simplifying Deployment with the Web Deployment Tool (MSDeploy)
You are invited to join the talk which is scheduled for
Wednesday, October 14th, 2009 | 4:00pm – 5:00pm (PDT, Redmond time)
Abstract
Deploying ASP.NET Websites has always been a challenge and different teams have used different approaches to overcoming those challenges. Microsoft has offered some support for making deployment easier in the past. For instance they first introduced Web Deployment Projects for Visual Studio 2005, and also have a version for 2008. Web Deployment Projects do greatly simplify the process of calling the aspnet_compiler and aspnet_merge tool but even though their title states "Deployment" they had no support for physically deploying the site. Now Microsoft has introduced the Web Deployment Tool, also known as MSDeploy. MSDeploy will bridge the gap between taking a web site and physically deploying it to its destination. With MSDeploy you can easily and very effectively perform tasks such as pushing an ASP.NET site (Web site, Web Application Project, ASP.NET, etc) from one machine to several other machines. This is achieved by the target machines having the MSDeploy Remote Agent Service installed and running. You can sync two different Web Sites that are hosted in IIS, you can create a web package (simply a .zip file) and use that as your source, you can sync two different folders, and many other options. Another compelling feature of MSDeploy is that it will be integrated into Visual Studio 2010. From Visual Studio 2010 you can compile your ASP.NET Web Application Project and then create the Web Package which contains all your content files plus IIS settings. This one file will full describe your web.
Live Meeting Information
Join the meeting.
Audio Information
Computer Audio
To use computer audio, you need speakers and microphone, or a headset.
Telephone conferencing
Use the information below to connect:
Toll-free: +1 (866) 500-6738
Toll: +1 (203) 480-8000
Participant code: 5460396
Please join 10 minutes prior to the start time.
First Time Users:
To save time before the meeting, check your system to make sure it is ready to use Microsoft Office Live Meeting.
Notes
Troubleshooting
Unable to join the meeting? Follow these steps:
1. Copy this address and paste it into your web browser:
https://www.livemeeting.com/cc/mvp/join
2. Copy and paste the required information:
Meeting ID: PR7D6Z
Entry Code: A5128ML0Y0D
Location: https://www.livemeeting.com/cc/mvp
If you still cannot enter the meeting, contact support
Note
Microsoft Office Live Meeting can be used to record meetings. By participating in this meeting, you agree that your communications may be monitored or recorded at any time during the meeting.
Sayed Ibrahim Hashimi
Wednesday, August 26, 2009
On Friday August 28 and Saturday August 29 there will be a conference in St. Louis called St. Louis Day of .NET that I will be speaking at. Here is the outline
Simplify build and deployment of ASP.NET sites with Web Deployment Projects
When you are creating ASP.NET sites, (either ASP.NET web site / ASP.NET Web Project / ASP.NET MVC Project / etc) you will need to deploy the site to machines which will host them. Classically there were two options; xcopy the actual source to the live server and let them be compiled on demand or you could use the aspnet_compiler.exe and aspnet_merge.exe tools to pre-compile the website for you. The little known, yet extremely useful, Web Deployment Projects (an add on for Visual Studio) can greatly simplify the process of build and deployment. Web Deployment Projects will take care of the complexities of the aspnet_compiler.exe and the aspnet_merge.exe tool for you by way of a tight UI integration into Visual Studio itself. Aslo Web Deployment Projects are MSBuild files so you can extend and customize the process to suit your exact needs. In this session we will introduce Web Deployment Project, show that you can perform very powerful actions without writing a single line of code (or even text)! We will also dive into the MSBuild file that is the Web Deployment Project and show how to customize the process.
This session talks about Web Deployment Projects (2005 version) and how they can help in the build and deployment process. If you are going to be attending and interested in build and deployment of ASP.NET web sites and projects then you don't want to miss this session.
Sayed Ibrahim Hashimi
On this page |
Archives |
Categories |
|
February, 2015 (1) |
January, 2015 (1) |
December, 2014 (1) |
August, 2014 (1) |
July, 2014 (2) |
May, 2014 (1) |
October, 2013 (1) |
September, 2013 (1) |
June, 2013 (4) |
May, 2013 (2) |
March, 2013 (3) |
February, 2013 (3) |
January, 2013 (3) |
December, 2012 (3) |
November, 2012 (1) |
October, 2012 (3) |
August, 2012 (6) |
July, 2012 (2) |
June, 2012 (5) |
May, 2012 (6) |
April, 2012 (3) |
March, 2012 (1) |
February, 2012 (3) |
January, 2012 (1) |
December, 2011 (3) |
November, 2011 (3) |
August, 2011 (1) |
March, 2011 (1) |
February, 2011 (1) |
January, 2011 (1) |
December, 2010 (2) |
November, 2010 (3) |
October, 2010 (3) |
September, 2010 (2) |
August, 2010 (2) |
July, 2010 (2) |
June, 2010 (3) |
May, 2010 (3) |
April, 2010 (5) |
March, 2010 (8) |
February, 2010 (2) |
January, 2010 (2) |
December, 2009 (2) |
November, 2009 (4) |
October, 2009 (3) |
September, 2009 (2) |
August, 2009 (5) |
July, 2009 (2) |
June, 2009 (7) |
May, 2009 (4) |
April, 2009 (5) |
March, 2009 (1) |
February, 2009 (2) |
January, 2009 (2) |
December, 2008 (2) |
November, 2008 (1) |
October, 2008 (1) |
September, 2008 (1) |
July, 2008 (1) |
June, 2008 (5) |
May, 2008 (2) |
April, 2008 (2) |
March, 2008 (1) |
February, 2008 (5) |
January, 2008 (2) |
November, 2007 (2) |
October, 2007 (1) |
September, 2007 (1) |
June, 2007 (1) |
April, 2007 (1) |
February, 2007 (1) |
January, 2007 (1) |
November, 2006 (2) |
August, 2006 (3) |
July, 2006 (2) |
June, 2006 (5) |
May, 2006 (2) |
April, 2006 (2) |
March, 2006 (6) |
February, 2006 (2) |
January, 2006 (8) |
December, 2005 (4) |
|
|