Tuesday, June 02, 2009

This coming Wednesday I will be at the Jacksonville Developer User Group. The topic title is "Leveraging Web Deployment Projects". I am still thinking about a new title, I'm not extremely happy about that one. Here is the description about the talk.

In this session we will take a look at how Web Deployment Projects can be used to assist in the deployment of web sites and web applications; including ASP.NET Web Applications and ASP.NET MVC Web Applications. We will give an overview of what Web Deployment Projects are and the functionality that is available out of the box. A Web Deployment Project is a wrapper for the aspnet_compiler.exe tool in the form of an MSBuild project and adds value to using the tool itself. Because they are MSBuild files we are able to customize and extend the process. We will discuss how we can customize the process to perform common steps such as

  1. Creating Virtual Directories
  2. Updating values in the web.config file
  3. Encrypting the web.config file
  4. Minimizing JavaScript files
  5. Versioning the Assemblies

In this session we will not be covering MSBuild itself, so I will not go into too much detail about MSBuild specifics. More to be discussed is how you can take advantage of Web Deployment Projects and how that build process can be extended and customized.

 

Sayed Ibrahim Hashimi

Tuesday, June 02, 2009 4:25:06 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 
Tuesday, May 26, 2009

Before I begin this post I must say that I do not have any inside information about the release of Visual Studio 2010 or .NET 4. The post is composed of 100 % speculation and based on information that has already been made publicly available.

I am pretty interested to know the release date for Visual Studio 2010, and .NET Framework 4.0, so I asked around but no one could tell me anything. So I decided to do some research as to the release dates for Visual Studio 2005 and Visual Studio 2008 based on the release of their Beta releases. I came up with the following table.

 

Beta 1

Beta 2

RTM

Beta 1 - Beta 2

Beta 2 - RTM

Visual Studio 2005

06/29/2004

04/18/2005

11/07/2005

43 Weeks

29 Weeks

Visual Studio 2008

04/19/2007

07/26/2007

11/19/2007

14 Weeks

17 Weeks

Visual Studio 2010

05/18/2009

11/30/2009

05/09/2010

28 Weeks

20 Weeks

Yellow cells are 100% based just on the averages of the two previous versions

 

When Visual Studio 2005 came out there were huge changes. I think this is why the amount of time between Beta 1 and Beta 2, and between Beta 2 and RTM were so much longer then their corresponding periods in Visual Studio 2008. I think for the release of Visual Studio 2010 we are going to be somewhere between the two time periods. So maybe a decent indicator would simply be the average of the two. This is what I used to come up with the cells that are shaded in yellow. I'm sure this will be off but hopefully by weeks and not months!

   

Sayed Ibrahim Hashimi

Tuesday, May 26, 2009 4:24:49 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 
Monday, May 18, 2009

If you are using the ASP.NET MVC DefaultModelBinder to manage the creating complex types from your views’ form data, as well as the validation summary helper provided with ASP.NET MVC then you may have run into the situation I did. I created a simple form, in a dummy app,  to create a new contact. The page is named AddContactClassic.aspx, the contents are shown below.

<% @ Page Title ="" Language ="C#" MasterPageFile ="~/Views/Shared/Site.Master" Inherits ="System.Web.Mvc.ViewPage" %>

 

<% @ Import Namespace ="Sedodream.Web.Common.Contact" %>

 

< asp : Content ID ="Content1" ContentPlaceHolderID ="TitleContent" runat ="server">

      Add Contact Classic

</ asp : Content >

 

< asp : Content ID ="Content2" ContentPlaceHolderID ="MainContent" runat ="server">

    < h2 > Add Contact Classic </ h2 >

   

    <% = Html.ValidationSummary( "Errors exist" ) %>

   

    < ol >< li >< span class ="success-message"> <% = ViewData[ "SuccessMessage" ]%> </ span ></ li ></ ol >

    <% using (Html.BeginForm())

       { %>

    < fieldset >

        < legend > Account Information </ legend >

        < ol >

            < li >

                < label for ="FirstName"> First name </ label >

                <% = Html.TextBox( "FirstName" ) %>

                <% = Html.ValidationMessage( "FirstName" , "*" ) %>

            </ li >

            < li >

                < label for ="LastName"> Last name </ label >

                <% = Html.TextBox( "LastName" ) %>

                <% = Html.ValidationMessage( "LastName" , "*" ) %>

            </ li >

            < li >

                < label for ="Email"> Email </ label >

                <% = Html.TextBox( "Email" )%>

                <% = Html.ValidationMessage( "Email" , "*" )%>

            </ li >

            < li >

                < label for ="Phone"> Phone </ label >

                <% = Html.TextBox( "Phone" )%>

                <% = Html.ValidationMessage( "Phone" , "*" )%>

            </ li >

            < li >

                < div class ="option-group" id ="Gender">

                    <% = Html.RadioButton( "Gender" , Gender .Male.ToString())%> < span > <% = Gender .Male.ToString() %> </ span >

                    <% = Html.RadioButton( "Gender" , Gender .Female.ToString())%> < span > <% = Gender .Female.ToString() %> </ span >

                </ div >

            </ li >            

            < li >

                < input type ="submit" value ="Add contact" />

            </ li >

        </ ol >

    </ fieldset >

    <% } %>

 

</ asp : Content >

In my ContactController class the following methods are defined.

public ActionResult AddContactClassic()

{

    return View();

}

[ AcceptVerbs ( HttpVerbs .Post)]

public ActionResult AddContactClassic( Contact contact)

{

    if (contact == null ) { throw new ArgumentNullException ( "contact" ); }

 

    InternalAddContact(contact);

 

    return View();

}

When I ran the app and filled in all the values on the AddContactClassic page I was a bit surprised to see an error simply stating “A value is required.” Here is a screen shot.

So I assumed that I must have misspelled one of the names of the fields that were passed to the Html.TextBox method. Obviously this was not the issue, so then I remembered that the Contact class that I defined had another property, Id, which I was not contained in a field on the form. This is the case because this page is supposed to create a new Contact, so its Id will not be set. I changed the AddContactClassic(Contact) method to ignore the Id property when binding was occurring. Here is the new method.

[ AcceptVerbs ( HttpVerbs .Post)]

public ActionResult AddContactClassic( [ Bind (Exclude= "Id" )] Contact contact)

{

    if (contact == null ) { throw new ArgumentNullException ( "contact" ); }

 

    InternalAddContact(contact);

 

    return View();

}

By using the Bind attribute I was able to let the DefaultModelBinder know that I was not interested in getting the value for that field. Once I made this change everything worked fine.

In the Contact class I had incorrectly defined the Id property to be Guid instead of Guid? which is better. If I had correctly declared that then the DefaultModelBinder   would have known that it was not a required field and it would not have complained. But if you are using the Entity Framework , you may still have this issue anyway because it does not always create nullable fields for all nullable columns in my experience. Even after changing the Contact class to use Guid? I have purposefully left the Bind(Exclude=”Id”) on the method in case something changes in the implementation of the Contact class.

Sayed Ibrahim Hashimi

Monday, May 18, 2009 4:25:27 AM (GMT Daylight Time, UTC+01:00)  #    Comments [2]  | 

If you are using the ASP.NET MVC DefaultModelBinder to manage the creating complex types from your views' form data, as well as the validation summary helper provided with ASP.NET MVC then you may have run into the situation I did. I created a simple form, in a dummy app, to create a new contact. The page is named AddContactClassic.aspx, the contents are shown below.

<% @ Page Title ="" Language ="C#" MasterPageFile ="~/Views/Shared/Site.Master" Inherits ="System.Web.Mvc.ViewPage" %>

 

<% @ Import Namespace ="Sedodream.Web.Common.Contact" %>

 

< asp : Content ID ="Content1" ContentPlaceHolderID ="TitleContent" runat ="server">

      Add Contact Classic

</ asp : Content >

 

< asp : Content ID ="Content2" ContentPlaceHolderID ="MainContent" runat ="server">

    < h2 > Add Contact Classic </ h2 >

   

    <% = Html.ValidationSummary( "Errors exist" ) %>

   

    < ol >< li >< span class ="success-message"> <% = ViewData[ "SuccessMessage" ]%> </ span ></ li ></ ol >

    <% using (Html.BeginForm())

       { %>

    < fieldset >

        < legend > Account Information </ legend >

        < ol >

            < li >

                < label for ="FirstName"> First name </ label >

                <% = Html.TextBox( "FirstName" ) %>

                <% = Html.ValidationMessage( "FirstName" , "*" ) %>

            </ li >

            < li >

                < label for ="LastName"> Last name </ label >

                <% = Html.TextBox( "LastName" ) %>

                <% = Html.ValidationMessage( "LastName" , "*" ) %>

            </ li >

            < li >

                < label for ="Email"> Email </ label >

                <% = Html.TextBox( "Email" )%>

                <% = Html.ValidationMessage( "Email" , "*" )%>

            </ li >

            < li >

                < label for ="Phone"> Phone </ label >

                <% = Html.TextBox( "Phone" )%>

                <% = Html.ValidationMessage( "Phone" , "*" )%>

            </ li >

            < li >

                < div class ="option-group" id ="Gender">

                    <% = Html.RadioButton( "Gender" , Gender .Male.ToString())%> < span > <% = Gender .Male.ToString() %> </ span >

                    <% = Html.RadioButton( "Gender" , Gender .Female.ToString())%> < span > <% = Gender .Female.ToString() %> </ span >

                </ div >

            </ li >            

            < li >

                < input type ="submit" value ="Add contact" />

            </ li >

        </ ol >

    </ fieldset >

    <% } %>

 

</ asp : Content >

In my ContactController class the following methods are defined.

public ActionResult AddContactClassic()

{

    return View();

}

[ AcceptVerbs ( HttpVerbs .Post)]

public ActionResult AddContactClassic( Contact contact)

{

    if (contact == null ) { throw new ArgumentNullException ( "contact" ); }

 

    InternalAddContact(contact);

 

    return View();

}

When I ran the app and filled in all the values on the AddContactClassic page I was a bit surprised to see an error simply stating "A value is required." Here is a screen shot.

So I assumed that I must have misspelled one of the names of the fields that were passed to the Html.TextBox method. Obviously this was not the issue, so then I remembered that the Contact class that I defined had another property, Id, which I was not contained in a field on the form. This is the case because this page is supposed to create a new Contact, so its Id will not be set. I changed the AddContactClassic(Contact) method to ignore the Id property when binding was occurring. Here is the new method.

[ AcceptVerbs ( HttpVerbs .Post)]

public ActionResult AddContactClassic( [ Bind (Exclude= "Id" )] Contact contact)

{

    if (contact == null ) { throw new ArgumentNullException ( "contact" ); }

 

    InternalAddContact(contact);

 

    return View();

}

By using the Bind attribute I was able to let the DefaultModelBinder know that I was not interested in getting the value for that field. Once I made this change everything worked fine.

In the Contact class I had incorrectly defined the Id property to be Guid instead of Guid? which is better. If I had correctly declared that then the DefaultModelBinder would have known that it was not a required field and it would not have complained. But if you are using the Entity Framework, you may still have this issue anyway because it does not always create nullable fields for all nullable columns in my experience. Even after changing the Contact class to use Guid? I have purposefully left the Bind(Exclude="Id") on the method in case something changes in the implementation of the Contact class.

Sayed Ibrahim Hashimi

Monday, May 18, 2009 4:24:19 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 
Thursday, May 14, 2009

A little while ago I received an email from a reader in which he provided a sample MSBuild script. Here were some comments that I sent him.

“One thing that I did notice that may be problematic in your MyBranchTool.common.targets is the following item group.

<ItemGroup>

    <MyTargetFiles Include="$(ProjectDir)$(OutDir)*" />

</ItemGroup>

Here you are declaring an item (outside of a target) which pickups files inside the OutDir. This may include files that were created (or moved there) during the build process.Items and properties declared outside of targets are evaluated before any target executes. What this means is that your MyTargetFiles item may not include all the files that it should. Instead you should put this decclaration inside of a target right before it is needed (which should be after the files have been placed inside the OutDir folder). Unless you are intentionally wanting to pick up the files in that folder before the build starts. If you have my book there is a section on Property & Item Evaluation take a look at that. I think it is somewhere near page 60 or so.”

Also if you are using MSBuild 3.5 you should specify the ToolsVersion on the Project element.”

Here is his response

“Ah, yes thanks for that! I was getting errors sometimes and I thought it was something like that but I didn’t know how to fix it - some files would be deleted by the Rebuild but not recreated, and then the Copy fails because those files are missing.

I have ordered your book, hopefully it arrives soon :) I look forward to reading through it!

Thanks again”

His initial question was not related to the issue that I commented on here. This happened to surface because he sent me his build script. I didn’t have the script that actually used that item, but I recognized that an item was being created from the $(OutDir) in a static item, which is a red flag for a problem ! Like I stated to him since files are placed into the OutDir folder at build time the item should be dynamic and not static. You should look for this in your build scripts as you edit them and make sure that they do not repeat this.

 

Sayed Ibrahim Hashimi

Thursday, May 14, 2009 3:59:35 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 
Wednesday, April 29, 2009

With MSBuild 3.5 two new known metadata names were introduced for items passed to the MSBuild Task. Those known metadata names are Properties and AdditionalProperties. The idea is that you can now specify properties on the item itself instead of having to pass all the properties using the Properties attribute on the MSBuild Task. For example you could define an item, Projects, to be:

<ItemGroup>

    <Projects Include="Project01.proj">

        <Properties>Configuration=Release</Properties>

    </Projects>

</ItemGroup>
Then you can build the values contained in the Projects item using the MSBuild task:

<Target Name="BuildProjects">

    <MSBuild Projects="@(Projects)"/>

</Target>

 

Like I said previously there are two new ways to pass properties in item metadata, Properties and AdditionalProperties. The difference can be confusing and very problematic if used incorrectly. Admittedly I didn't know the difference until about 6 months ago (but soon enough to include in my book J ). The difference is that if you specify properties using the Properties metadata then any properties defined using the Properties attribute on the MSBuild Task will be ignored. In contrast to that if you use the AdditionalProperties metadata then both values will be used, with a preference going to the AdditionalProperties values.

Now let's take a look at an example to make this clear. The following MSBuild file is named Properties.proj and is shown below.

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

 

<PropertyGroup>

    <ProjectPath>Project01.proj</ProjectPath>

</PropertyGroup>

 

<ItemGroup>

     <_ProjectToBuild_Properties Include="$(ProjectPath)">

         <Properties>Configuration=Debug</Properties>

    </_ProjectToBuild_Properties>

</ItemGroup>

<ItemGroup>

    <_ProjectToBuild_AdditionalProperties Include="$(ProjectPath)">

        <AdditionalProperties>Configuration=Debug</AdditionalProperties>

    </_ProjectToBuild_AdditionalProperties>

</ItemGroup>

 

<Target Name="Build_Properties">

    <Message Text="Building project with Properties metadata" Importance="high"/>

    <MSBuild Projects="@(_ProjectToBuild_Properties)" Properties="DebugSymbols=true" />

</Target>

 

<Target Name="Build_AProperties">

    <Message Text="Building project with AdditionalProperties metadata" Importance="high"/>

    <MSBuild Projects="@(_ProjectToBuild_AdditionalProperties)" Properties="DebugSymbols=true" />

</Target>

 

</Project>

I've highlighted a few important elements contained in this file. Firstly if you do not specify your ToolsVersion to be 3.5 then none of this functionality will work. Make sure to always provide this value, or you may be baffled by the un-expected behavior.

Inside of both targets you can see that I and providing the value Properties="DebugSymbols=true". Below is the definition of the file that it is building, the Project01.proj file.

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

 

<Target Name="Build">

    <Message Text="Building $(MSBuildProjectFile)" Importance="high"/>

    <Message Text="Configuration: $(Configuration)"/>

    <Message Text="DebugSymbols: $(DebugSymbols)"/>

    <Message Text="OutputPath: $(OutputPath)"/>

</Target>

 

</Project>

This file just prints out the values for a couple of properties that are not defined inside the file itself. Now let's see the behavior when we execute both of these targets. The result is shown in the image below.

As I've highlighted here the result of executing the Build_Properties target results in the attribute Properties="DebugSymbols=true" being completely ignored. The result from the Build_AProperties target takes the Properties attribute into consideration as well as the AdditionalProperties metadata. Don't use both of these together!

I personally prefer using the AdditionalProperties because I think that ignoring the Properties attribute can be confusing and hard to diagnose. This is why I tend to use that approach instead of the Properties metadata unless I have a specific reason.

Sayed Ibrahim Hashimi

 

 

 

Wednesday, April 29, 2009 5:04:17 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 
Thursday, April 23, 2009

If you are you using ASP.NET MVC and the Entity Framework then odds are that you will want to use some of your entity object inside of your views. If you've tried this you may have run into the following exception: "CS0234: The type or namespace name 'Entity' does not exist in the namespace 'System.Data' (are you missing an assembly reference?)".


So the first guess is to add a reference to System.Data.Entity assembly in the MVC project. I did that then ran my app again, and I encountered the same error. After some poking around I figured out that you need to manually add the assembly to the web.config file. So in your web.config file you need to add the element

<add assembly="System.Data.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

Under the compiliation\assembiles node, here it is:

Once you've done this you should be able to run your app with no problems.

 

Sayed Ibrahim Hashimi

Thursday, April 23, 2009 7:18:20 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 
Saturday, April 11, 2009

After my previous entry a reader requested that I post a table of contents for my book Inside the Microsoft Build Engine. After searching I realized that I didn't have one. So I put one together here it is.

Contents at a Glance

Part I Overview

  1. MSBuild Quick Start
  2. MSBuild Deep Dive, Part 1
  3. MSBuild Deep Dive, Part 2

Part II Customizing MSBuild

  1. Custom Tasks
  2. Custom Loggers

Part III Advanced MSBuild Topics

  1. Batching and Incremental Building
  2. External Tools

Part IV MSBuild Cookbook

  1. Practical Applications, Part 1
  2. Practical Applications, Part 2

Part V Team Foundation Build

  1. Team Build Quick Start
  2. Team Build Deep Dive
  3. Team Build Cookbook

Appendixes

  • New Features in MSBuild 3.5
  • Common Properties and Items
  • New Features in Visual Studio Team System 2010 Team Build

 

Sayed Ibrahim Hashimi

Saturday, April 11, 2009 4:55:18 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 
Thursday, April 09, 2009

Since the release of Inside the Microsoft Build Engine, the book that I wrote along with William Bartholomew, there has been a continuous stream of positive feedback posted. I would like to thank everyone that has taken the time to post reviews of the book. I think it is important that feedback is provided (positive or negative) so that potential readers can more accurately decide whether or not to purchase a particular book. I would like to highlight some of the reviews that I have found here.

Steve St. Jean, who is himself regarded as an MSBuild expert, posted a very thorough review of the book on his blog. I personally have never seen a book review by an independent party with soo much detail. Thanks Steve! Here is some of his comments.

"Wow! This is the book that I wish I had written. Sayed and William have covered the topic's depth and breadth with enough illustrations and code examples to make any developer productive with MSBuild and Team Build. No Experience Required."
"The "Deep Dive – Part 2" builds on the prior chapter to go deeper into Dynamic Properties and Items. One of the best nuggets of the book can be found here. On pages 60 & 61 they show the "MSBuild Order of Evaluation" which is essential to all but the most trivial MSBuild script. Up until this point I knew the basics of the evaluation order but had never been able to find a definitive order. This was the first time I knew that there was much I didn't know but sadly not the last."
"Batching is a process whereby MSBuild looks at an Item list and groups its elements based on some metadata attribute's values."
[Discussing Team Build Content]: "The "Deep Dive" section is truly "deep". It describes the default build process and then shows how you can customize the defaults to bring in your project's specific steps. Need to customize the Clean process? It's in there. Want to package your website into a Zip file? No problem. All the overridable "hook" Targets that Microsoft left in the process are described along with those Targets that you shouldn't touch."

Wes MacDonald who is a Team Systems MVP has these comments.

"This book was fantastic, full of great examples and guides you through customizing MSBuild and Team Build. I was initially surprised to find so many chapters dedicated to MSBuild but afterwards I realized there is just so much you can do with it, there probably could have been more."

Doug Holland who is a Visual C# MVP who works for Intel wrote on his blog:

"I have got to say this book totally rocks and I'll be looking for a second edition once VS2010 RTM is released."

Peter Blomqvist writes a blog post titled "Finally a proper book about MSBuild and Team Build"

"The book is well structured and is down to earth with a lot of practical examples from real world scenarios. I truely wish that I would have had access to this book back in 2005 when I started out with build automation in Team System."
"The book is a must read for anyone considering working with build automation using Team System (atleast until VSTS 2010 comes out and changes it again)."

Mathias Olausson has these comments on his blog.

"The book covers MSBuild and Team Build first with the basics and then with deep-dives that cover topics that are hard to find in one place."

 

Amazon.com

Reviews

 

Currently on Amazon.com we have 5 reviews and all 5 are rated 5 stars, and I didn't solicit any of them! Here are snippets from those reviews:

Highly Impressed

"This is a well written book on the MSBuild system. I was working on an open source project that will generate the MSBuild scripts and wanted to understand it well enough to take maximum advantage of it.

This book is all that I was waiting for, it is worth the price. The explanations are simply and very clear - easy to understand language."

A "must have" for any budding build master

"Even though I have decent experience in MSBuild I read this book from front to back twice over and was exceptionally impressed with how this book was put together."
"There is some fantastic advice and guidance for customizing MSBuilds, batch building and incremental building and there are 3 chapters dedicated to Team Foundation Build which were highly educational for me in not only a gathering a better understanding of the build process in Team Foundation but also a stronger understanding of how to utilize Build Agents, retention policies, triggers, and unit testing within Team Foundation Build."

The Definitive Companion on MSBuild and Team Build 2008

"This book's focus on making sure that MSBuild is explained to the tiniest details is a big win. The explanation and coverage of MSBuild is something you will not find in any other book (or even MSDN)."
"This is the definitive guide on Team Build 2008. I was particularly impressed with the Team Build Cookbook chapter, especially the load balancing discussion of the tool that William wrote"

Best book on the subject, hands down

"This book is outstanding."
"I highly recommend this book to anyone who is both new or experienced with MSBuild or Team Build. Great work!"

The book that everyone who does builds with Visual Studio needs

"I picked up this book because even though I knew how to use MSBuild and TFS Build I did not know all of the nitty gritty pieces of the underlying engine and all of the available options. I know them now."
"Having said that, if you are new to MSBuild then this is a great book. It very quickly introduces you to the basics of MSBuild (which you all use anyway if you use Visual Studio 2005 or greater) and how to quickly customize MSBuild to suit your needs."


Sayed Ibrahim Hashimi

Thursday, April 09, 2009 4:44:55 AM (GMT Daylight Time, UTC+01:00)  #    Comments [1]  | 
Wednesday, April 01, 2009

Earlier today I was awarded the status of Microsoft MVP! The area that they have put me in is Visual C#, you can see my profile at https://mvp.support.microsoft.com/profile/Sayed.Ibrahim.Hashimi.

I know that a lot of different people have nominated me for this award, and I am very grateful for that. I would especially like to thank Joe Healy. Joe has been pushing the MVP guys to accept me for quite some time. Now that I have received the award I just have to make sure that I keep it!

Sayed Ibrahim Hashimi
Visual C# MVP!

Wednesday, April 01, 2009 9:38:30 PM (GMT Daylight Time, UTC+01:00)  #    Comments [4]  | 

Theme design by Jelle Druyts