I have had a number of request to get SlowCheetah working for Azure Worker Roles. I think I have it working now. I have not yet released the support to the download page yet but after the support is verified I will update the release.
If you would like to try out a build which has support to transform app.config, as well as other XML files, for Azure Worker Roles you can find the VSIX at https://dl.dropbox.com/u/40134810/SlowCheetah/issue-44/SlowCheetah-issue-44.zip. After installing for worker role projects you can create XML transforms for app.config, and any other XML file. When you publish to azure, or create a package your files should be transformed.
I wanted to let everyone know that William Bartholomew and I are working to update our MSbuild book. This will be the third edition. We are going at this a bit different than our second edition. Instead of doing a complete rewrite of the previous book, we have decided that we will release a small book to supplement the existing book. We did this for a number of reasons but it boiled down to the fact that most of the existing content is still accurate. So it would be better to release a small update just covering new stuff. This is going to be really great for everyone who already owns the second edition. You can quickly learn all the new material, and it will be much cheaper than a full sized book. I’m not sure of the cost yet but I will keep you all posted.
For more info on the book please checkout out my new site msbuildbook.com. At that site you can get info on the second edition as well as the third. You can get info on downloading samples for both versions of the book as well. FYI the source for the msbuildbook.com site is available at https://github.com/msbuild-book/msbuildbook.com.
A while back I blogged about how to setup SlowCheetah on a Build server. The solution was good but it was a bit unwieldy and error prone, especially those who are not comfortable with MSBuild (this solution still works and is still a good approach for some scenarios). I’ve made this much easier, but wasn’t able to make it as easy as what I wanted. The solution that I choose is using NuGet. Ideally you’d be able to install the SlowCheetah NuGet package into a project, enable package restore and the check in your code. Unfortunately due to how NuGet package restore is implemented this flow is not currently possible. Hopefully in the near future Nuget will better support these scenarios. For now we will have to work with the solution below.
Background
The transformations are executed when your project is built. The way that this works is that when you use the SlowCheetah VS add-in to enable transformations, your project file is modified to import an additional MSBuild .targets file which knows how to do the transformations. This .targets file is placed in your %localappdata% folder. When you add the SlowCheetah NuGet package to your project, the .targets file (and supporting files) are downloaded to the packages folder. Your project is also modified to look at the packages folder for the .targets file which is imported.
For build server scenarios, when using NuGet for this it’s a bit of a chicken and egg problem. Let me clarify, we are using NuGet to update the build process for your project. If a solution is using NuGet, you will need to enable NuGet Package Restore. This is what will enable your NuGet packages to be download duringbuild.
Package Restore is implemented to restore NuGet packages for each project whenever it is built. This is accomplished by adding an Import into your project to NuGet.targets. This works beautiful for the majority of cases, but fails completely if you are trying to update the build process for a given project with NuGet. When the build for a project starts if the the imported .targets file do not exist on disk they are not imported. You can visualize this flow as.
We need to find a way to get the packages restored, before your project is built. We can achieve this by executing a build which will be used to simply restore our packages. Now let’s see how we can workaround this issue.
Solution
We need to find a way to restore the packages before the project is built. The easiest way to do this is to add a dummy solution to be built before your actual solution/project. Follow these steps.
1. Install the SlowCheetah NuGet package into the project using SlowCheetah.
You can do this by using the Package Manager Console, and executing the command Install-Package SlowCheetah –pre. Note: after the package is released you can remove the –pre.
2. Enable Package Restore for the solution
You can do this by right clicking on the solution and selecting Enable NuGet Package Restore.
3. Configure build server to build restorePackage.proj before your solution
As described we need a new solution that can be used to restore the required packages. When you install SlowCheetah it will automatically create a packageRestore.proj file in the root of your project. You can use this to easily restore your NuGet packages. All you need to do is to build this file before you build your solution or build script. If you are using Team Build this is pretty easy. Edit the build definition and then add packageRestore.proj to the Items to Build list. You can find this on the Process tab.
Make sure that packageRestore.proj is above (built before) your solution.
With these changes when the empty solution is built, it will restore the SlowCheetah .targets file. Then the target solution will be built, the .targets file will already be downloaded and your transforms will execute as needed.
I will work with the NuGet team to see if there is something better that can be done here. I will keep you all posted if there is any update.I would love if you tried out this new support and let me know if you have any issues with it.
I received a customer email and one of the things that he wants to be able to do is sync multiple folders. I thought I’d share with you what I wrote to him.
From: Sayed Hashimi Sent: Tuesday, December 18, 2012 11:28 PM
You actually can do this, but it’s not based on skips, it’s an opt-in approach. What I mean is that you would have to specify all the folders that you wanted to sync.
MSDeploy is a provider based model. There is an composite provider, manifest, which can be used when multiple providers are required. In your case the actual provider that you want to use is contentPath. This is the provider that knows how to sync folders. If you want to sync multiple folders you can create a source manifest which has the source folders and a dest manifest which has all the target folders.
In my example I have the following folders.
c:\temp\publish\souce\01
c:\temp\publish\souce\02
c:\temp\publish\souce\03
I only want to sync 01 and 03 so I create the manifest with the following content.
You can see that I use the manifest provider for both the source and the dest. A few things to note.
-enableRule:DoNotDelete - Pass this to ensure that other content in the dest is not deleted
-useCheckSum – Pass this to ensure that only the minimal set of files is synced
-disableRule:BackupRule – When using MSDeploy v3 I was getting errors relating to the auto backup feature, just pass this to avoid that (this could be an issue with my machine setup)
Drawbacks from this approach
You must use full paths in the source/dest manifests.
Your source/dest manifests must have matching contentPath elements
This approach requires two files; source manifest & dest manifest
How you can make this even better
The real issue I have with this approach is that it requires both a source & dest manifest. If you can easily auto generate these files from a list of shares that would be great. If you are maintaining these files “by hand” you should be careful to make sure both files are updated.
With a bit of more work you can boil it down to a single source manifest if you have a common root folder, and you want the files to be reflected in the same relative structure underneath that. They way that you would do this is to use the MSDeploy auto provider trick. With MSDeploy you can pass –dest:auto and MSDeploy will essentially reflect the source settings to the destination. You can then create an MSDeploy parameter which will be used to update the path of that common root folder.
If you want to go down this option it will be a bit more complex. I’d be willing to walk you through it if you’d be willing to blog about it afterwards J
When you are building a .sln file or a .csproj/.vbproj/etc you need to be careful how you set the Configuration property. Once this property is set you do not want to change the value of it. Because of this it is best to specify this as a global property. To do that you can pass it in on the command line. If you are using the MSBuild task then you can pass it in via Properties or AdditionalProperties. What you do not want to do is to set this value inside your .csproj/.vbproj or any imported file. The only time when this is OK if there is a condition which will not set the property if it’s already been set. This is exactly how the default .csproj/.vbproj files are authored:
If you do set this property w/o the conditional not to overwrite an existing value you may experience really strange behavior during your builds. And it may be difficult to diagnose the issue as well.
Now let me explain why you cannot do this. When you build a .csproj/.vbproj MSBuild will start creating an in-memory representation of the entire project. It will start with the .csproj/.vbproj file itself. It will read the file from top to bottom. When a property is encountered it is evaluated. If a property is encountered that relies on another one, for example
The properties inside the expression will be evaluated on whatever values exist for the properties at the time. In this case ItermediateOutputPath will be the value of BaseIntermediateOutputPath and Configuration.
If a property is encountered which specifies a value for a property which has been previously declared, the previous value will be discarded.
The implications of this are subtle but very simple; once a property has been set which has dependent properties you must not overwrite that property. This is because when a dependent property is encountered it is evaluated immediately. You cannot re-evaluate that property. So if you set a property during your build, some existing dependent properties which were evaluated before the value change will continue to use the old value. There is no way to re-evaluate those properties.
Now lets see how this relates to the Configuration property specifically.
The contents of the .csproj/.vbproj are properties/items along with an import to Microsoft.csharp.targets (Microsoft.VisualBasic.targets for .vbproj) which then imports Microsoft.Common.targets. If you look in Microsoft.common.targets you will see many different properties which are declared using $(Configuration). So this means that you must treat the Configuration property with care and abide by the rule that I have outlined above.
FYI If you want more details on this I have explained this entire process in great detail in my book Inside MSBuild and Team Build.
Configuration for web publishing
If you have used the new web publish experience in Visual Studio 2012 (also available for VS2010 from the Azure SDK) you may have noticed that the web publish profiles are MSBuild files. They are stored under Properties\PublishProfiles (My Project\PublishProfiles for VB) and have extensions of .pubxml. In that file (or in a .pubxml.user file associated with it) you will find a property defined as
This value corresponds to the value for the Configuration drop down in the VS web publish dialog. When you kick off a publish in VS we use this value and kick off a build and specify Configuration as a global property which is passed in. The reason why we did not name this property Configuration is because the web publish profile is imported into the web project itself during the publish process. By the file being imported you can natively access all the properties/items of the .csproj/.vbproj and also easily extend the build process. Since that is the case we cannot set the Configuration property because we know it’s value has already been set. Due to this when publishing from the command line you must specify the Configuration property.
When I setup this blog back in 2005 I had just graduated from college and most of my development experience at the time was in Java, but I had taken a job as an ASP.NET developer. When I setup the blog I didn’t know that much about web development. Last week Doug Rathbone let me know he was having issues viewing my site. This led me to take a closer look at my blog and I have to say that I’m embarrassed by what I found. I should have made the improvements outlined in this post a long time ago. In the long term I’d like to move off of dasBlog but I haven’t had the time to do that, but I needed to do something. I think I’m in a much better place, and wanted to share what I did. Before that let me recap what problems I discovered.
Poor performance
By far the most egregious aspect of my blog was it poor performance. I was violating every rule in the book! Ok well maybe not every rule as I somehow received a B rating in YSlow. After running YSlow with the Small Site or Blog settings on the site here were the results.
I was making too many http requests which was killing my site. Some of the request were for images in the content but from static content I had the following.
11 css files
11 JavaScript files
1 swf file to facilitate copy to clipboard
Bunch of small images for styling
Step: Reduce the startup time of the page
My pages were loading slowly, and for the most part un-necessarily. Two things that my site had which were slowing it down were the .js files are imported at the top of the page and un-needed ads showing content. I moved all the .js includes to the bottom of the page which helped the startup time. I also simply removed the ads.
Step: Reduce the number of http request
In total there were 65 requests, not all to my webserver but most of them. The .css files were mostly for the various webparts used by the theme and the generic dasBlog .css files. Many of the .js files were brushes for the syntax highlighter that I use. To take care of this I decided to update the way that my blog looked to avoid the un-necessary images used for styling. After that I removed the un-used .css files from the site template.
Then I downloaded Packer .NET. I used that to compress and combine all the .css files into a single minified .css file for the entire site. I had to update some relative paths in the .css file but other than that it was pretty simple. I also used packer to do the same for the .js files.
Step: Reduce the size of the content being sent
Not only did I want to reduce the number of request going back and forth but I wanted to reduce the overall number of bytes going back and forth. When I was viewing the request going back in forth in my browser I noticed that a lot of .pngs were being sent back and forth because most of my entries have at least 1 image. So I downloaded PNGGauntlet to take care of it. I searched for all .png files in my site and drag tem to PNGGauntlet and let it optimize them for me. After running that I knew that all the images were optimized. I plan to run this tool on all new .png files ever few months. I post my blogs with Windows Live Writer and I haven’t researched if I can integrate this directly into it. I also changed the site’s layout to reduce the content of the web request itself. More on those changes later.
Poor readability
I’m not a designer or a fashion expert but even I could tell that my site was not laid out correctly. It had a lot of elements which were distracting, un-necessary and downright ugly. Below you’ll see thumbnails of how my blog looked like on a hi-res screen and a mid-res screen.
You can see that the left hand column is an offender in both cases equally. The title bar is taking ~10% of the page on the hi-res screen and on the mid-res screen ~35% WTF!!! The most important thing on any blog is the content and the site should be optimized for readers to view the content. Everything else is just a distraction. The column on the left hand side had to go and the title bar needed some serious work. From the content in the sidebar the only items which I liked were; search, link to months, posts on this page and the categories. Everything else pretty much sucked.
Here is what I did; updated the title to be way more compact and less verbose. Removed the sidebar with ads and links. I placed the verbose sidebar content which I did like at the bottom of the page with an anchor. I linked to that in the hearder, which is where I placed the search bar. Now the distracting header is hopefully no longer distracting and the sidebar went away entirely. But all useful functionality and content were preserved.
While doing this I also looked at the HTML content which was being rendered. There were some un-needed <div/<span/<table elements coming through. I removed as much as I could in the template files. It’s still pretty bad, but until I move off of dasBlog I think this is about as good as it gets.
Lack of mobile support
My site was completely unusable on a mobile device. Here are some screen shots of how my blogged looked on a mobile device.
If you ever visited my site on a mobile device, I apologize :(
Since I had already removed the columns and made the title much smaller I was already on my way. But I also needed to add the view port meta tag to the header of the site so that the browser would render the site in the correct way.
Even with the decreased title when viewed on a mobile device it was too large. I used a simple CSS media query to create styles when the site was viewed in narrow views.
@media only screen and (max-width:600px)
{
/* Insert css here */
}
When testing this you can either download a mobile emulator, like Electric Plum, or simply resize your browser until it is less than the desired size. After the changes here are the screen shots of my new layout on a mobile device.
As you can see it’s much easier to see the contents of the entries. The title bar is still a bit big, but I’d have to have to shorten the text to make it smaller, but I’m OK with how it is currently.
View when docked in Windows 8
Then I looked at my site when it was docked on the left or right in Windows 8. Below is what my site looked like before any changes.
Not surprising, I thought it was gonna suck. Here was my site after the updates above.
To my surprise it still sucked! The problem here is a similar issue as to the mobile view. The device does not know the size to make the viewport. I had to add one line of css to enable my site to be rendered correctly.
Not many sites ready for being docked in windows 8.
Conclusion
After all these changes m site loads much faster, looks way better and is much easier to read on a variety of devices. After all of these changes I was able to get my YSlow score up to 98. The only remaining issue is to reduce the number of DOM elements. In order to address that issue I’ll have to wait until I can upgrade my blog software. For now I’m happy with where I’m at.
One thing that I haven’t done yet is to set expires headers for all my static content. I’m planning to do this, but after I make some other updates first.
For those of you who have been reading my blog for a while, I’m sorry to put you through the pain I did :) But I’m hoping that things are much better now. If I missed anything else please let me know.
“I’m using Visual Studio 2012 and publishing web projects to the file system. How can I include files to be published which are not a part of my project"?”
I thought that I would answer here so that everyone could see the answer.
In Visual Studio 2012 (and in VS 2010 if you have downloaded the web publish updates via the Azure SDK) when you create a web publish profile we will create a .pubxml file under the Properties\PublishProfiles for C# or My Project\PublishProfiles for VB. If you open that file you will notice that it is actually an MSBuild file. When you publish your web project (either from the VS dialog or from the command prompt) the .pubxml file is combined with your project file to execute the publish. Since this is an MSBuild file you can directly edit the file to customize behavior of the publish process. In this case the question asker, lets call him Chris, has asked how to include some additional files into the publish payload.
This can be accomplished by the following.
Create an MSBuild target which can gather the set of files to be added
Extend the web publish process to include the files
Creating a target is pretty simple, and I’ll cover the contents of the target but first lets look at issue #2.
We need to add an MSBuild target which executes during the period in which files are being collected to be published. We have an MSBuild property which contains the set of targets which make up this phase, PipelineCollectFilesPhaseDependsOn, which is used as a dependency property as you might have guessed. In order to insert a target into that you can use something like the following in your .pubxml file.
Here I extend the PipelineCollectFilesPhaseDependsOn by pre-pending CustomCollectFiles, which is a target that I declared directly in the .pubxml file. This will make sure that my target gets executed at the correct time. Now when you publish your web app the CustomCollectFiles will be executed. Now let’s move on to what the contents of the target should contain. One way that you can do this is to add files to the FilesForPackagingFromProject item list. In my case I wanted to publish all the files in a folder named “additional files” which was one folder above the project directory. Take a look at the modifications that I made to my .pubxml file.
In this case the CustomCollectFiles target gathers the files into the _CustomFiles item. Notice how I declared the path to the folder. I used the MSBuildThisFileDirectory property. This property was introduced in MSBuild 4.0 and it points to the folder of the MSBuild file which contains it. So it will point to the folder which contains the .pubxml file (either Properties\PublishProfiles or My Project\PublishProfiles). After that, the files are included in the FilesForPackagingFromProject item list. The one special item to take notice of here is the declaration for the DestinationRelativePath metadata value. Since this file is not in the project we have no context on where the files should be placed when published. This is where the DestinationRelativePath metadata comes in. Here you specify the relative location to the publish root of the file. In my case I used additional files\%(RecursiveDir)%(Filename)%(Extension). Which will place all the files in the additional files folder under the same relative path to where they were picked up from.
Web Deploy (aka MSDeploy) uses a provider model and there are a good number of providers available out of the box. To give you an example of some of the providers; when syncing an IIS web application you will use iisApp, for an MSDeploy package you will use package, for a web server webServer, etc. If you want to sync a local folder to a remote IIS path then you can use the contentPath provider. You can also use this provider to sync a folder from one website to another website.
The general idea of what we want to do in this case is to sync a folder from your PC to your IIS website. Calls to msdeploy.exe can be a bit verbose so let’s construct the command one step at at time. We will use the template below.
We use the sync verb to describe what we are trying to do, and then use the contentPath provider for both the source and the dest. Now let’s fill in what those values should be. For the source value you will need to pass in the full path to the folder that you want to sync. In my case the files are at C:\temp\files-to-pub. For the dest value you will give the path to the folder as an IIS path. In my case the website that I’m syncing to is named sayedupdemo so the IIS path that I want to sync is ‘sayedupdemo/files-to-pub’. Now that give us.
For the dest value we have not given any parameters indicating what server those command are supposed to be sent to. We will need to add those parameters. The parameters which typically need to be passed in are.
ComputerName – this is the URL or computer name which will handle the publish operation
Username – the username
Password – the password
AuthType – the authType to be used. Either NTLM or Basic. For WMSvc this is typically Basic, for Remote Agent Service this is NTLM
In my case I’m publishing to a Windows Azure Web Site. So the values that I will use are:
All of these values can be found in the .publishSettings file (can be downloaded from Web Site dashboard from WindowsAzure.com). For the ComputerName value you will need to append the name of your site to get the full URL. In the example above I manually added ?site=sayedupdemo, this is the same name as shown in the Azure portal. So now the command which we have is.
OK we are almost there! In my case I want to make sure that I do not delete any files from the server during this process. So I will also add –enableRule:DoNotDeleteRule. So our command is now.
At this point before I execute this command I’ll first execute it passing –whatif. This will give me a summary of what operations will be without actually causing any changes. When I do this the result is shown in the image below.
After I verified that the changes are all intentional, I removed the –whatif and executed the command. After that the local files were published to the remote server. Now that I have synced the files each publish after this will be result in only changed files being published.
In the case of the question it was asked with dest:auto, you can use that but you will have to pass in the IIS app name as a parameter and it will replace the path to the folder. Below is the command.
When we released VS2010 we add support for web.config (XDT) transforms during publish/package. Note: From now on I’ll only use the word publish from now on but the full content relates to packaging as well. In the original implementation when you published your web project the web.config file would be transformed by the file web.{Configuration}.config, where {Configuration} is the project build configuration. For example Debug, or Release. If you publish on Release and there exists a web.release.config we will take your web.config and transform it with web.release.config before publishing.
Cascading web.config transformations
In VS 2012 (as well as the publishing updates for VS2010 through the Azure SDK) now support the concept of publish specific transforms. You can also now specify the project configuration used for a profile when publishing on the publish dialog.
In this case I have created a profile named Production and set the Configuration to Release. When I publish this project the following transformations will be applied (if the files exist) in this order.
web.release.config
web.production.config
I think that we got this wrong when we initially implemented the support. We should have created profile specific transforms instead of ones based on build config, but having these cascading transforms are still pretty useful. For example I may want to remove the attribute debug=”true” from the compilation element and then inside of the profile specific transform we would override appSettings/WCF endpoints/logging config/etc for that environment.
In VS there is a right-click option on web.config for Add Config Transform, but we were not able to update the functionality of that to automatically create profile specific transforms. Don’t worry it will be released soon with our first set of updates for web tooling. For now you will need to create a new file with the correct name and add it to your project. Note: if you want it to show up nested under web.config you’ll need to add the metadata <DependentUpon>Web.config</DependentUpon> to the item in the .csproj/.vbproj file.
web.config transform preview
Previously the only way to test the functionality for these transformation was to actually publish or package the web project. This gets old pretty quick. In order to simplify creating these transforms we have introduced the Preview Transform menu option. This is the coolest feature in VS 2012 (OK I’m a bit biased, but still its the coolest).
In my web.release.config I have left the default contents, which just removes the debug attribute. Here is what I see when I select this on web.release.config for my project.
You can see that in the image above we can see that the debug flag was indeed removed as expected.
In my web.production.config I have a transform which simply updates the email app setting value. Here is the really cool part when I preview the transform for web.production.config the previewer will look into the profile and determine the build configuration which has been configured, and it will ensure that transform is applied before the profile specific one. For example take a look at the result for web.production.config.
In the image above you can see the note that web.release.config was applied first followed by web.production.config. In the result we can see that web.release.config removed the debug flag and that web.production.config updated the email address value.
We also do a little bit to help out in case there are errors in either the web.config or a transform. You can see errors in the Output Window and double click it to go directly to where the error exists.