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 during build.

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.

image

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.

image

 

Make sure that packageRestore.proj is above (built before) your solution.

SNAGHTML158ea083

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.

Sayed Ibrahim Hashimi | @SayedIHashimi


Comment Section

Comments are closed.


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.



  
  

The dest manifest file will contain.



  
  

Then to do the sync you can use the command.

msdeploy -verb:sync -source:manifest="C:\Temp\publish\SourceManifest.xml" -dest:manifest="C:\Temp\publish\DestManifest.xml" -enableRule:DoNotDelete -useCheckSum -disableRule:BackupRule

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

Thanks,
Sayed Ibrahim Hashimi | @SayedIHashimi


Comment Section

Comments are closed.


My good friend Brady Gaster, has written up a great blog post at Managing Multiple Windows Azure Web Site Environments using Visual Studio Publishing Profiles. In that post he shows how you can create publish profiles and have profile specific web.config transforms as well as a bunch of other info. Its a great read, the content applies to any host which supports Web Deploy not just Azure Web Sites.

Thanks,
Sayed Ibrahim Hashimi | @SayedIHashimi


Comment Section

Comments are closed.


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:

Debug

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

$(BaseIntermediateOutputPath)$(Configuration)\

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

Release

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.

Sayed Ibrahim Hashimi | @SayedIHashimi


Comment Section

Comments are closed.


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.

image

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.

image image

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

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.

imageimageimage

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.

imageimageimage

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.

image

Not surprising, I thought it was gonna suck. Here was my site after the updates above.

image

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.

@media screen and (max-width: 320px) {
    @-ms-viewport { width: 320px; }
}

More info on this at http://blogs.msdn.com/b/ie/archive/2012/06/19/adapting-your-site-to-different-window-sizes.aspx. You can combine this with css media queries if you want to have finer grained control. More info on this at http://msdn.microsoft.com/en-us/library/ie/hh708740(v=vs.85).aspx. After that simple change here is what I now have. Much better.

image

After that I did a bit of looking around to see what sites look like docked in windows 8, there are very few which actually look nice.

Good sites

Scott Hansleman’s site is very readable for Windows 8 when docked. Kudos Scott! This doesn’t surprise me at all for Scott.

image

Microsoft.com this site is optimized for being docked, which I would expect.

image

 

Bad sites

Mads Kristensen’s blog is completely unreadable without zooming.

image

Even top-tier sites are not usable on windows 8 when docked. They still have a few weeks to GA, but they will need to get this taken care of soon.

Facebook

image

Twitter

image

cnn.com

image

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.

image

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.

FYI Scott Hanselman has a good post discussing these topics at http://www.hanselman.com/blog/TheImportanceAndEaseOfMinifyingYourCSSAndJavaScriptAndOptimizingPNGsForYourBlogOrWebsite.aspx.

Thanks,
Sayed Ibrahim Hashimi | @SayedIHashimi


Comment Section

Comments are closed.


© 2024 - Sayed Ibrahim Hashimi