Brian's profilePoints to sharePhotosBlogLists Tools Help

Blog


    2/11/2009

    IMPORTANT: Good bye live spaces! Hello Word Press!!!

    AS OF TODAY, THIS BLOG WILL NO LONGER BE RUNNING HERE! PLEASE UPDATE YOUR FAVOURITES AND RSS FEEDS!

    After almost a year of using Spaces for my blog (being the Microsoft fan boy that I am, I can admit it) I have decided it was time for a change. This was mostly inspired by the fact that I decided I wanted a more professional blog, and while spaces is fine for a basic blog, there are more powerful tools out there for me, and I chose WordPress as the most suitable for me.

    Anyway, I have migrated the full contents of this blog to the new address, so eventually I will delete this space but I’ll leave it around for the time being until I’m sure everything is fine. But you should go and check out the new blog and update your RSS feeds!

    2/5/2009

    How to configure proxy settings for SharePoint

    If you have a SharePoint site that is sitting behind a proxy and you are using things like the XML Reader web part to access external content, then you need to configure SharePoint to go through the proxy to get the data. Now fortunately for us SharePoint is based on ASP.NET 2.0 we can configure the proxy in the same was as a regular .NET web app – through the web.config file. Here is a sample:

       1: <system.net>
       2:     <defaultProxy useDefaultCredentials="true">
       3:         <proxy usesystemdefault="False" proxyaddress="http://[proxy address]:8080" bypassonlocal="True" />
       4:     </defaultProxy>
       5: </system.net>
       6:  

    All you need to do is to set the proxy address together with the port number into the property there and put that in the web.config and then that’s all you need – problem solved!

    2/4/2009

    Hiding elements on a publishing page when fields are blank

    This has been something that bugs me about most page layouts I have done before – you have a field like the description or something like that and when you put it in you have to put it in a <p> tag to get it to render properly. The problem then is that if you don’t populate the field you then don’t want the <p> tag outside the element to render otherwise you will have some unwanted white space. I had a quick Google around and found a pretty good solution for this at http://social.technet.microsoft.com/Forums/en-US/sharepointecm/thread/dcfc5fe2-5ee1-439a-af44-b59b5c6f59bd/.

    Essentially the solution involves creating a custom control based on the security trimmer control, and telling it to trim the components inside it when the specific field is blank. I found the code example at that URL didn’t quite work, so here is my code with some minor adjustments made:

       1: public class HideWhenBlank : SPSecurityTrimmedControl
       2: {
       3:     public String FieldNameToCheck { get; set; }
       4:  
       5:     protected override void Render(System.Web.UI.HtmlTextWriter output)
       6:     {
       7:         SPListItem item = null;
       8:         WebPartDisplayMode mode = ((SPWebPartManager)this.Page.Master.FindControl("wpmMain")).DisplayMode;
       9:         if (mode.Name == "Design")
      10:         {
      11:             base.Render(output);
      12:         }
      13:         else if (SPContext.Current != null)
      14:         {
      15:             item = SPContext.Current.ListItem;
      16:             if (!String.IsNullOrEmpty(FieldNameToCheck) && item != null)
      17:             {
      18:                 if (!ValueIsNullOrBlank(item[FieldNameToCheck]))
      19:                 {
      20:                     base.Render(output);
      21:                 }
      22:             }
      23:         }
      24:     }
      25:  
      26:     private Boolean ValueIsNullOrBlank(Object data)
      27:     {
      28:         if (data == null || String.IsNullOrEmpty(Convert.ToString(data).Trim()))
      29:         {
      30:             return true;
      31:         }
      32:         else
      33:         {
      34:             return false;
      35:         }
      36:     }
      37: }

    Compile this class and you can go and use this one in your page layouts like this:

       1: <MyCustomTagPrefix:HideWhenBlank runat="server" FieldNameToCheck="Comments">
       2:     <p>
       3:         <!-- Some sort of custom publishing element in here -->
       4:     </p>
       5: </MyCustomTagPrefix:HideWhenBlank>

    So basically in this example when the comments field is empty, then the <p> tag as well as anything else inside the custom tag won’t be rendered. The tag will always allow the content to be rendered in edit mode though which means you can always add a value later. Thsi is nice and easy to implement and can help tidy up your page layouts a bit.

    1/30/2009

    SPDisposeCheck goes public!

    If you are a SharePoint developer, then chances are that you know of the fact that there are several SharePoint objects that always need to be disposed of correctly in order to prevent memory leaks (and if you don’t know about this, then learn about it real quick! There is a good article over at MSDN - Best Practices- Using Disposable Windows SharePoint Services Objects).

    Anyway, there has been a tool in the works for a little while now to help developers get this right – SPDisposeCheck. What this tool will do is assess a /NET library (either a DLL or EXE file) and it will tell you about all the lines of code that you need to change in order to meet the best practices for memory management in SharePoint. I’ve seen this tool in action a few months back (wasn’t allowed to say anything about it at that point) and I gotta tell you its pretty awesome. From what we found it was pretty good at picking up any of the issues we had in our code, with a couple of small exceptions and one or two false positives. The point is though that it greatly reduced the likelihood of human error when we reviewed the code because the tool would do it for us, and do it much quicker too.

    Now the catch with this tool is that it isn’t officially supported by Microsoft, so don’t go throwing it around on every SharePoint machine you have – but every one of your SharePoint developers should have a copy of this tool on their development environments, and its probably not a bad idea to enforce its use as part of some sort of code review process as well.

    So go and download this tool now! It is at http://code.msdn.microsoft.com/SPDisposeCheck

    Source: http://blogs.msdn.com/pandrew/archive/2009/01/29/spdisposecheck-v1-3-1-is-released.aspx

    1/27/2009

    Creating web applications through command line actions

    When deploying SharePoint sites I personally am a big fan of the good old batch file - they are simple enough to put together and with a bit of knowledge of the commands that stsadm offers you can create quite a powerful deployment that is reproducible and not prone to human error that you might get when deploying things that require user interaction with the UI.

    The scenario that I find is the most common is that you need to deploy your solutions to a SharePoint farm and then create a site that uses them. For example I could have a solution for an intranet site that after I deploy the WSP I would like to create the site based off the templates in the solution. To do this there are a few steps to go through to get this going:

    • Add and deploy the WSP files
    • Create the web application
    • Create the site collection
    • Reset IIS

    The first step most people who deploy solutions via command line will be familiar with - the addsolution and deploysolution commands. Basically addsolution is used to store a WSP file in the configuration database so that it can be deployed to the farm, and deploysolution will deploy the solution to the farm from the configuration database. Here is a basic sample of these commands:

       1: stsadm -o addsolution -filename MySolution.wsp
       2: stsadm -o deploysolution -name MySolution.wsp -immediate -allowgacdeployment -allcontenturls
       3:  
       4: stsadm -o execadmsvcjobs

    The addsoltuion command is very straight forward, just give it the path to your WSP file and it is a happy camper. The deploysolution command has plenty of options to it, such as allowing the solution to put resources in the GAC, allowing it to deploy CAS policies, which URLs it should be deployed to, and when it should be deployed. This command will create a timer job, and in this case you will want to use the -immediate tag so that when the next line runs the timer job will be executed immediately. Thats it for the first part!

    The next thing we want to do is to create a web application. Now I'm assuming here that you know what the URLs and application pool details will be, as you will need them in this command. Here is a sample:

       1: stsadm -o extendvs -description "ShrePoint - My new site -url %internalUrl% -ownerlogin %siteCollectionAdmin% -owneremail %siteCollectionAdminEmail% -databasename %databaseName% -exclusivelyusentlm -donotcreatesite -apidname %appPoolName% -apidlogin %appPoolUser% -apidpwd %appPoolPassword% -apidtype configurableid -allowanonymous
       2:  

    The command we use here is extendvs. It will create a web application for us, here are a few things you should know about it:

    • 'description' will be the name of the web applicaiton as you see it in Central Administration
    • 'url' will be the URL of the site in SharePoint. What is worth noting with this is that when SharePoint creates the web application here by default it will ignore the host header in your URL and just use the port number. If you add the -sethostheader option then it will apply the host header for you, so this is usually a must. Also worth knowing is that if you do set the host header then you have to use the application pool username and password options, but I'll explain that below
    • 'ownerlogin' and 'owneremail' are the details of the primary site collection administrator
    • 'databasename' will let you customise the name of the database that is created. There are also options for database server and credentials if you want to configure them too.
    • 'exclusivelyusentlm' tells the new web applicaiton to only use NTLM security. There is also an option to enable kerberos in place of this one
    • 'donotcreatesite' tells the command to not create a site collection in the web application - we will use a seperate command for this that allows us more control over it. You can however do this in one command if you want to
    • 'apidname', 'apidtype', 'apidlogin' and 'apidpwd' all refer to the application pool details (Name, type, username and password of the applicaiton pool identity, in that order). The type attribute can be either 'configurableid' or 'networkservice', use the first if you are using a specific account for the app pool, or the later for just using the network service account.
    • 'allowanonymous' sets the security policy for the site to allow anonymous users

    From here we can now create a site collection in our web application, here is a command that will do this:

       1: stsadm -o createsite -url %internalUrl% -title "My new site" -owneremail %siteCollectionAdminEmail% -ownerlogin %siteCollectionAdmin% -sitetemplate STS#0
       2:  

    So most of the options here are self explanatory, with the siteTemplate attribute specifying what type of site to create. Once this is done we through in an IIS reset and your new site is good to go

       1: iisreset
       2:  

    What I would recommend to anyone who is going to batch deployments like this is to come up with a common file and put all the appropriate variables at the top (you can see the variables in my examples). Then create a copy of the batch file for each environment and and put in the appropriate details into the variables at the top. That way there is less messing around with the batch files at each deployment, which means less chance for things to not be done correctly. Also it might be worth not including the password to your service account in the batch file, and having whoever is responsible for the deployment putting that in manually before it is run, just to keep things a bit tighter from a security perspective. Other than that, your good to go!

    And to finish up, here are some references to the commands I’m talking about from TechNet:

    1/23/2009

    Interesting issue with publishing pages provisioned from the page layout

    This is a bit of an interesting issue that I came across yesterday afternoon while working on a clients intranet site. Basically it has to do with how you provision publishing pages in MOSS – if you provision a page from the page layout file (using the setuppath attribute in your module element) after the page is provisioned if you go to the page settings page where you would normally change the layout, the option to do so will not be there. Let me explain in detail what I am talking about here:

    If you go on over to MSDN (http://msdn.microsoft.com/en-us/library/ms441170.aspx) you will see the usual way for provisioning a file through a feature, and it looks something like this:

       1: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
       2:     <Module Name="SubSiteHome" Url="$Resources:cmscore,List_Pages_UrlName;" Path="">
       3:       <File Url="default.aspx" Type="GhostableInLibrary" >
       4:         <Property Name="Title" Value="My Page Title" />
       5:         <Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/MyPageLayout.aspx, ~SiteCollection/_catalogs/masterpage/MyPageLayout.aspx" />
       6:         <Property Name="ContentType" Value="My Content Type" />
       7:       </File>
       8:     </Module>
       9: </Elements>

    Now, this method works fine and will deploy a copy of the file default.aspx that you will have in your features directory. But as a good friend of mine Zak Azeez once showed me, you can provision a publishing page directly from the page layout (provided you know where it sits in the 12 hive). This means you don’t need to have the pesky default.aspx file that only has one line of code sitting around. To do this, you provision the file like this:

       1: <Module Name="SubSiteHome" Url="$Resources:cmscore,List_Pages_UrlName;" Path="" SetupPath="FEATURES\PageLayoutFeatureName">
       2:   <File Url="MyPageLayout.aspx" Name="default.aspx" Type="GhostableInLibrary">
       3:     <Property Name="Title" ValueMy Page Title" />
       4:     <Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/MyPageLayout.aspx, ~SiteCollection/_catalogs/masterpage/MyPageLayout.aspx" />
       5:     <Property Name="ContentType" Value="My Content Type" />
       6:     <Property Name="PublishingAssociatedContentType" Value=";#My Content Type;#[ContentType ID goes here];#" />
       7:   </File>
       8: </Module>

    In this method you use the SetupPath attribute of the module element and point it to the feature folder that has the page layout that you want your new publishing page to use. Then when you provision the file the Url attribute is the file name of the page layout and the Name attribute is what you want it to be called when it is provisioned. After that the only extra attribute you need to use is the PublishingAssociatedContentType (just like you would when you provision the page layout to the master page gallery) and your all set.

    So the interesting thing I discovered was that any pages that I had provisioned using the second method would not let me change the page layout. I would browse to the page settings page and all the other properties would be there (title, description, contact, scheduling etc) but the normal drop down with the list of page layouts to change to wasn’t there, while on pages provisioned with the first method I discussed can quite happily change their layout. I’m assuming this is something that was perhaps by design and that we just weren’t aware of (it is actually going to help now because this was I can prevent users from changing the page layout on important pages in the site) but still something we didn’t know about and I thought was worth sharing. Hope someone else finds this useful too!

    1/11/2009

    Things I want to achieve in 2009

    Well its my last day of holidays and its back to the office for me tomorrow. I’m keen to get back to the projects I am working on and I’m out to make this year bigger and better than last year, which will take some effort because last year was such a massive year for me. Last year saw me start work with Unique World, become a co-manager of the Canberra SharePoint User Group, start this very blog and get plenty of good stuff in to it, which in turn helped me get my skills with all aspects of SharePoint to a level even I didn’t think they would – and then to top it all off I finally got my MCAD as well. So how on earth do I plan to top that all this year?

    Well my first idea is to release a project on CodePlex – I have a couple of good ideas that could help SharePoint developers out there, I just need to find the time to put them together and get them out there! Next I want to try to increase the readership of my blog – I know I get plenty of traffic from Google but I want to try to come up with some way to get more people sitting on my RSS feed. I want to find more places that I can do presentations (I really enjoyed presenting at Office DevCon last year and I always like talking to the Canberra SP User Group) so I might start looking outside of Canberra to do them. And last but certainly not least I want to make sure that the projects I am working on for our clients really shine and are things I can be proud of.

    So I think I’m ready to hit the ground running – look out 2009 because I’m out to make it a big one!

    12/30/2008

    How to get TFS to automate your WSP builds with WSPBuilder

    Now this is what happens when I have too much time on my hands over the holidays (you would think I would have something better to do, and yet here I am anyway!). Essentially I had rebuilt my laptop and I have included TFS in the setup for my source control on local projects that I was working on (for example, when I'm on site with a client and not connected to the corporate source control solution, this makes for a good backup). Anyway I wanted to look into something that I know has plagued me on other projects, and that was how to use the TFS Build Server to automatically build our WSP files for us as part of its automated builds. So here is how I got that right (and I'll warn you now, this is gonna be a long blog post!), but the thing is I don't have a massive amount of experience with TFS outside of the basic stuff, I also am keen to see if anyone out there has ideas on how to improve this process for everyone.

    Essentially what I wanted to work was when I do a local build of a project that it gives me a copy of the WSP file that isn't checked in and is just local to my environment, so I can test it on my local server before checking the code in. Then when I check the code in I want an automated build to take place and drop the WSP file in a location I specify.

    Step One: Install WSPBuilder on the build server

    So the first thing I decided upon was that I was using WSPBuilder for my WSP files, I have used WSPBuilder for every SharePoint project I have worked on and I like the way it all ties in to Visual Studio, so it seemed that the next step for me was to get WSPBuilder to make my automated build WSP files. To do this, the software needed to be installed on the build server, so that was step 1.

    Step Two: add WSPBuilder to the paths environment variable

    My next issue was that I wanted to be able to create the WSP files from the build action when I build from the client and when TFS does the builds. This meant that I would put the majority of the actions into the post build activities of each project. This raised an interesting issue for me - my host OS where I do my development is 64-bit and my TFS server (which is the build box) is 32-bit (see my previous rant about TFS not running on 64-bit). This meant that the path to the WSP builder app was going to be different on each box (because of the "program files" and "program files (x86)" thing). So to simplify the post build actions a bit I decided to add the WSPBuilder path (C:\Program Files (x86)\WSPTools\WSPBuilderExtensions) to the PATH system variable on both the development box and the build box.

    Step Three: Set files included in the WSP file to copy to output directory

    Now, when TFS does a build in the directory that it puts the DLL's it will only give you the DLL's themselves, not the files that also need to go into your WSP. My idea for a way around this is to put all of the files that get deployed to the 12 hive (so everything in my projects that isn't code) to copy to the output directory on build (this is done by selecting the file in the solution explorer of Visual Studio, and in the properties window set the item to be Content, and to copy if newer). This would mean that my compiled DLL's and all the other files for the 12 hive would be in the same directory at the same time on the TFS server, ready for the WSP builder call to run.

    Step Four: Add the post build activity to the appropriate projects

    Now that we know all the files will be where we need them to, we can add the post build actions. Add this to the post build of each project that should output a WSP file:

       1: IF ("$(OutDir)")==("bin\Debug\") GOTO LocalBuild
       2:  
       3: :TfsBuild
       4:  
       5: MD "$(TargetDir)bin\Debug\"
       6: COPY "$(TargetDir)*.dll" "$(TargetDir)bin\Debug\"
       7: WSPBuilder -SolutionPath "$(TargetDir)" - OutputPath "$(TargetDir)"
       8: RENAME "$(TargetDir)Debug.wsp" "$(ProjectName).wsp"
       9: RMDIR "$(TargetDir)bin" /S /Q
      10: RMDIR "$(TargetDir)12" /S /Q
      11:  
      12: GOTO Finish
      13:  
      14: :LocalBuild
      15:  
      16: WspBuilder -SolutionPath "$(ProjectDir)" -OutputPath "$(TargetDir)"
      17:  
      18: :Finish

    This code is broken down into the following key actions:

    • Firstly, determine if the build is a local build or a TFS build. Now I'm sure there has got to be a better way to do this, but here is one that works - in a local build the $(OutDir) variable will always be relative (like "bin\debug\") but in a TFS build. this path will always be the complete path to where the build is outputting to, so by checking this we can determine where the build is happening. If it is a local build we use a go to statement
    • The Next section is the TFS build actions. Firstly we create a "bin\debug" folder and move all the DLLs from the solution to it. This essentially makes the "Debug" folder that is the output for the DLLs the equivalent of the solution directory as far as WSP builder is concerned (remember all the other supporting files are still in the 12 folder because we copied them to the output directory). So once the DLL's are moved we call WSPBuilder (with just the name of the app, not the path to the executable because we added the path to the PATH environment variable earlier). This will always then output a WSP file called "debug.wsp" so we need to rename it to something more useful, so change it to match the ProjectName, and then when we are done delete the bin and 12 directories (we don't need them dumped to the drop location now that we have the WSP file)
    • The last section is just a call the WSPBuilder that will run for local builds. This does the same thing as if you had called the "Build WSP File" option from within Visual Studio.

    So with this post build action in place, when we do a build, either local or on the build server, we will have a new WSP file ready to roll.

    Step Five: Create a new build in TFS

    This is pretty straight forward, create a new build that targets the debug build of the solution. Nothing too complicated here other than to just make sure you choose the debug option - WSPBuilder expects everything to be in the debug folder.

    Step Six: Add additional reference paths

    Now unless your TFS server happens to be a MOSS server as well (which may be the case since it requires WSS for it to run) chances are you are referencing DLL's in your code that the build server won't know about, which will cause your new build to fail. There are a couple of solutions here, the first is to just GAC what you need, but I personally don't like this one. The second option that I did is to create a folder on the build server and add it as an additional reference path. This tells the TFS builder to look for referenced DLLs in a specific location. To do this, open the TFSBuild.proj file that is created for your TFS build and add this to the appropriate section (the very last one by default, read the comments to be sure).

       1: <AdditionalReferencePath Include="C:\Assemblies" />

    Then you can set this folder up as a network share and drop referenced assemblies in there as required.

    Step Seven: Add a pre-build action

    Now this isn't required if your solution only has one project and one WSP file, but if like my example I had set up here locally it has two projects that each have a WSP file then you might need to add this to the pre-build of each project (and I can't explain exactly why it works yet, I'm tired and was just happy that it all works in the first place).

       1: IF ("$(OutDir)")==("bin\Debug\") GOTO Finish
       2:  
       3: DEL "$(TargetDir)*.dll" /F /S /Q
       4:  
       5: :Finish

    If you don't put this in then you will find that the DLL's from the first projects that are build will make their way into the second and subsequent WSP files. Put this in and all seemed to work well for me.

    So now if you put all of that together and run an automated build (I've been testing this with a build on each check-in) you should find that your drop location will now contain all the DLL's, PDB and config files, as well as your WSP files! Now while this is working for me, there are things I do plan to improve about this process to make it a bit more streamlined, so if you have any suggestions I would love to hear them, just leave me a comment. One thing I have on my to-do list is to automate the upgrade of the solution to a specified server - this would mean that you could automate your WSP file builds nightly and deploy them to a staging server automatically over night. If I do that I'll be sure to add more to my blog here, and also I do plan on putting this up at http://SharePointDevWiki.com to see what else people can add to it (again, too tired to do it now and my Xbox is calling me to spend some time with it before I go back to work, so it will be there soon). I hope this helps someone else out there!

    12/23/2008

    Team Foundation Server 2008 and 64-bit – its just not meant to be

    My first blog post while I’m on holidays, and its to complain about a big lack of functionality in Team Foundation Server. Basically this all started while I was rebuilding my laptop (still a work in progress, but coming along well) and when it came time for me to install TFS 2008 on the box I get a big error message saying that it can’t install TFS on a 64-bit system! Now this just doesn’t make sense to me, with the way MS are pushing 64-bit, especially for server applications. I have read that TFS 2010 will have 64-bit support, but I can’t wait for it.

    So I got a few ideas for workarounds when I hit up Google for some info. Basically my fix will be to host the TFS application tier on a 32-bit virtual PC (running in HyperV). The data tier and the build server (I’m told) will still run fine on 64-bit, which means that I can still host the data and do my builds on the host OS. I will post here later once I have gone through the process to let you know how it went. In the mean time though, has anyone else run into this issue? What did you do to get around it? I would love to hear it!

    12/20/2008

    Planning to rebuild my dev environment and want second opinions

    What does a SharePoint developer do when he is on holiday – well the most common answers would probably involve doing things that in no way relate to SharePoint. But for me, near the top of my list is rebuild the laptop that I use for my development. There are a few things that I do know that I will be putting on there, but I would be interested in hearing anyone else’s thoughts on what could go on there and how I can configure it. Here is what I do know it will have:

    • Windows Server 2008 (configured to be a local domain controller, running Hyper-V for virtualisation)
    • Visual Studio 2008 SP1
    • Office 2007 Ultimate
    • MOSS 2007 (patched up to the infrastructure update)
    • SharePoint Designer 2007
    • SharePoint Manager 2007
    • POP3 and SMTP services
    • SQL Server 2008

    Right, so that gives a nice overview of the functionality I want this thing to have 9the laptop is a Dell XPS M1330, so it can handle it and do it quite well). There are a few things I am tossing around in my head that I am thinking about doing with it. Here is a list:

    Install Exchange Server 2007 instead of the POP3 service

    This is the first thing I’m not sure about – I currently haven exchange running on a VM so the accounts I set up in AD for testing things like emails from workflow all have mailboxes that I can easily access through different profiles in outlook. I haven’t used the POP3 service before but it was recommended to me by a colleague as it isn’t anywhere near as heavy as exchange. Would be interested to hear thoughts on it.

    WSPBuilder or custom scripts

    If you have ever talked to me about this or seen me give a presentation on anything to do with SharePoint you will know that I am huge fan of WSPBuilder (www.codeplex.com/wspbuilder). I do however find that it does a few funny little things sometimes (doesn’t always add safecontrols entries for me, the output WSP is different when you choose build to when you choose upgrade and tell it to do a build first, and a few other little things) so the thought of writing my own custom WSP generation scripts has been rolling around the back of my head for a while now. Of course the awesome thing about WSP builder is that it has templates for everything in Visual Studio, meaning adding features and other things to a solution is always a single click, so if I went with the scripts option I would also end up having to create some templates as well I think. Again would love to hear what others think about this.

    To virtualise or not to virtualise

    In my current setup I have a virtual PC that runs my complete development set up and I use one virtual PC for each environment. This is great for isolating code for each client, but means my VMs are quite fat and memory hungry. This time around each of my VMs will use services from the host (AD, SQL, Email, etc) but I am unsure as to whether or not I want to put my development tools on each VM. Essentially what I want is to be able to work with just one installation of Visual Studio on the host OS but then have an easy way to deploy the WSP to a predefined virtual server. This still allows me to isolate each SharePoint installation for each client/project and means I don’t need to have a copy of VS on each virtual machine (essentially meaning each VM would be nothing more than a MOSS install). I just don;t know how practical this would be to implement, and would love to hear others thoughts

    Source control

    One thing I don’t have with my current set up is local source control. I currently use Live Mesh to take backups of my code as I write it (it all syncs right up to my mesh) but I have been thinking about installing TFS on my host OS so I get full source control and bug tracking, at least for the stuff that I develop locally (obviously our bigger projects that involve more than just me writing code for them would have me using other source control solutions to work with the team and this might vary from client to client). Has anyone ever done this and do you think it would be worthwhile? I was thinking that I could still have Live Mesh sync the TFS data to my mesh as a plan “B” for disaster recovery.

     

    So there you have it, those are some of the big ideas I have in mind for my rebuild. I will probably start it some time this week and II will be sure to share what the final outcomes are, but please leave me a comment here if you have thoughts on any of because I would love to hear it.

    12/18/2008

    Why I like using site definitions!

    I had a bit of a chat with Jeremy Thake yesterday about one of the pages on SharePointDevWiki.com - the discussion of site features vs site templates vs site definitions. I suppose most of the discussion came from the fact that there really wasn't a lot of discussion on the topic, which was a little weird because if you talk to a lot of SharePoint developers they all have their favourite and reasons why the other options are evil.

    So I went and put in some info about my strategy for doing sites, and I'll say it loud and proud, I'm in the site definition camp. There are however some catches to that - you need to do them right, and I think this is where a lot of the fear and loathing of site definitions comes from. I'll be clear here - if you are doing anything to the content databases (triggers or modifying stored procedures) then you are doing the wrong thing, and are one of the big reasons that site definitions have the rep they do. Now let me explain how I do mine though.

    I start by creating a new site definition (again, editing the OOTB ones is evil and you shouldn't ever do it) and I try to put an absolute minimum of content in to it. I then build all the functionality into individual features, and reference the features in the site definition (in the WebFeatures and SiteFeatures sections). Why do I do this? Basically it is easy to identify the different types of sites post deployment, and because all of your functionality is in features it is easy to turn on/off more features to add or remove functionality later as well.

    Here is what I put on SharePointDevWiki as an example of this method:

    An example of how this method could be used is with a customised publishing portal. It has a site definition that contains 4 configurations (1 for the root site, and 3 different sub site models that could represent the different areas of a business and their specific requirements for example) and each use a combination of features to build their functionality up what goes in to each site. Some of the features that each site uses can be shared (for example, a customised document library might be required in all 3 sub sites, but this is still done with a single feature) while there might be some features that are used in only a specific sub site. After the site is deployed and has been in production for a while you might find you need to upgrade the sites for one of the business areas to add or remove a feature. The site definition can be upgraded and deployed with a new WSP to ensure new sub sites meet the new design, and existing sites can be updated programmatically to have the features modified. These sites can be easily identified (through the SPWeb.WebTemplate property) to ensure that only they are upgraded and the other sites are left alone.

    So there is my two cents on the topic, and I would love to hear anyone else's thoughts on the topic - just leave me a comment below!

    12/17/2008

    100 people to follow on Twitter

    Just a quick post this morning - Joel Oleson has put together a list of 100 SharePoint people to follow on twitter and I ended up making it on to the list (which I thought was kinda cool). Anyway if you use twitter and wanna keep in touch with what the big names in SharePoint are doing then head on over to http://www.sharepointjoel.com/Lists/Posts/Post.aspx?List=0cd1a63d-183c-4fc2-8320-ba5369008acb&ID=152 and start following some of those people!

    12/12/2008

    Creating CAML queries that use three or more filters

    Just a quick one that a came across today - I have a scenario where I am building a CAML query on the fly based on the part of the site that a user is browsing. Essentially the query will have a number of statements that need to go into an <Or> clause. Now I got caught out by putting my query together like this:

       1: <Where>
       2:     <Or>
       3:         <FieldRef Name="Field1" ... />
       4:         <FieldRef Name="Field2" ... />
       5:         <FieldRef Name="Field3" ... />
       6:     </Or>
       7: </Where>

    Now this worked fine when I ran it in the U2U Caml Creator tool (I manually typed the query in), but when I ran code that used this as part of an SPQuery I got the error message "Cannot complete this action, please try again". I had a look at it and it turns out that my query should have been written like this:

       1: <Where>
       2:     <Or>
       3:         <Or>
       4:             <FieldRef Name="Field1" ... />
       5:             <FieldRef Name="Field2" ... />
       6:         </Or>
       7:         <FieldRef Name="Field3" ... />
       8:     </Or>
       9: </Where>

    Each <Or> operator (or any of the operators that combine two values for that matter) can only contain the two values, so to get the multiple or statements going. Makes sense when you think about it, but I had me.

    12/11/2008

    Making a context sensitive content query web part

    conker8[1]I will start by explaining the picture - after I thought of the title of this blog post the very next thing I thought of was from Conker's Bad Fur day (which if you haven't played, go and get it. It was originally released on the N64 but is also on the Xbox and I believe is backwards compatible with the 360). Anyway there is a scene in it where a drunk scarecrow is trying to explain what context sensitive is to conker, who at this point is also still a bit drunk - good times.

    Anyway, onto the serious stuff. The requirement I am solving with this one is to make a content query web part automatically pick up items from the current web without me having to tell it where that web is. let me explain that a bit better - I am using a delegate control to put a content query web part into a page layout, and the page layout will be used across the entire site collection. I want the content query web part to display items based on the current site when a user browses to a page that uses this layout - so in other words, the web part needs to be context sensitive ... sensitive to context (another Conker reference there).

    So the bad news is OOTB you need to specify the WebURL property to tell the web part where to get its items from, the good news though is that it is very, very easy to override the content query web part to add this functionality. Here is the entire class that I wrote to add this functionality:

       1: public class CurrentSiteContentQuery : Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart
       2:     {
       3:         protected override void OnInit(EventArgs e)
       4:         {
       5:             base.OnInit(e);
       6:             this.WebUrl = this.WebUrl.ToLower().Replace("~site", SPContext.Current.Web.ServerRelativeUrl);
       7:         }
       8:  
       9:     }

    Yep, thats it. When I put "~site" into the WebURL property that will resolve to the current URL that is gets from the SPContext property. So now I just tell my delegate control to use my web part instead of the OOTB one and I'm done, context sensitive queries are now appearing in my page layouts. Its a beautiful thing.

    12/8/2008

    Using the delegate control to deploy a web part through features

    This is something I had no idea about until a friend of mine, Zak Azeez (don't say I didn't give you credit for this one mate!) pointed it out to me when we were discussing how I could best put a predefined web part into the master page of a SharePoint site. He suggested that I use the delegate control to deploy it with a feature. Now I knew the delegate control was used to deploy ASCX pages that you could incorporate into a page (the best example of this is the OOTB search control that is in the top right corner of the default master page, it is done with a delegate control) but I had no idea you could actually deploy a web part in the same way. Here is a quick run down of the process (and it is really easy).

    1. Go to your site and put your web part onto a page in a normal web part zone, configure it the way you want to appear
    2. Export the webpart
    3. Create a new feature and put the details from the exported web part into the Control element (see code sample below)
    4. Edit your master page and put in a delegate control that has a ControlID attribute that matches up with what is in your feature file
    5. Turn on the feature and the web part will appear where the delegate control is

    Pretty simple huh? What is even simpler is setting up the feature because its more or less a copy and paste from what you export from SharePoint when you get the web part out. here is a brief sample of how I put a content query web part in:

       1: <Control ControlAssembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
       2:            ControlClass="Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart"
       3:            Id="MyControlId"
       4:            Sequence="200">
       5:     <Property Name="FilterType3" />
       6:     <Property Name="PageSize">-1</Property>
       7:     <Property Name="SortBy">{f69504ad-fd94-4e65-a31d-c456f8c7f1be}</Property>
       8:     <Property Name="ChromeState">Normal</Property>
       9:     <Property Name="AllowZoneChange">True</Property>
      10:     ...
      11:     <Property Name="AllowClose">True</Property>
      12:     <Property Name="FilterField3" />
      13:     <Property Name="CatalogIconImageUrl" />
      14:   </Control>

    So you see the assembly and class attributes are put into the control node, and then all of the property tags are just copied and pasted from the external web part (make sure you remove the "type" attributes though, you don't need them here - also I think I needed to change the tags from property to Property (uppercase "P") so that it would be fine when it validated against the schema). So when I deploy that it will go and put a content query web part on the page for me. Obviously I didn't put all the properties from that web part on here (thus the dots in the middle) but you get the idea.

    What I do find to be very cool about this though is that it means my web part is now nicely tied to a feature, meaning that if we need to change the properties of the web part we can just update the feature and redeploy the WSP file, SharePoint will pick up the change when the application pool is recycled and the changes will appear to users - this makes the process of updating the web part so very very simple. Also it means if we don't want it anymore we can just disable to feature and the web part will no longer display, no editing of the master page is required. If you are putting web parts or controls onto your master page then this is definitely something you should consider doing.

    12/4/2008

    New SharePoint development wiki site needs your content!

    Big thanks to Jeremy Thake for getting this idea together - A new wiki site has been started that is going to be specifically aimed at SharePoint developers. Essentially what we are looking to do is to bring together all the data that is floating around your favourite search engine and link to it all on the wiki, so you can go to the wiki and get a good overview of heaps of stuff to do with a particular aspect of developing for and customising SharePoint.

    Personally I think this is a great idea and I'm looking forward to finding some time to put some content up on the site myself in the coming days and weeks, and if you want to contribute just head on over to the site and sign up. The URL is below!

    http://www.sharepointdevwiki.com

    SharePoint Dev Wiki

    12/2/2008

    Planning on using the SharePoint API in your silverlight app? Better think again

    ... and the issues keep on coming for my silverlight app! It looks like you can't reference Microsoft.SharePoint.dll in your silverlight projects (or a lot of other libraries for that matter) because they are not compiled for the silverlight runtime. For those who don't know, the silverlgiht runtime is essentially just a cut down version of the .NET framework (from what I have briefly read about it anyway) and so you can't use just any code in your silverlight app. This is why when you install the visual studio tools for silverlight you see the "Silverlight class library" project type - this is used to compile a library against the silverlight library so will make sure you don't reference anything you shouldn't.

    So in this case, my work around will be to use web services - silverlight is perfectly capable of calling them, so I can still get the data I need from SharePoint from the out of the box web services. Now I know this will work, but I would have much preferred to call the SharePoint API directly. I suppose I'll just stop my whining and get down to writing the code, but if you are planning on writing a silverlight app for SharePoint make sure you keep this in mind.

    12/1/2008

    How to get silverlight and MOSS to play nice

    I have recently started putting together a silverlight control for use in a MOSS site I am working on for a client. I went and downloaded the Visual Studio 2008 SP1 tools for silverlight and installed them and got in and came up with a nice looking silverlight control that run fine when I ran it from Visual Studio. However I went and deployed my WSP to the local SharePoint farm and all over sudden none of my MOSS sites were working, not even central admin.

    I get this error when I try to browse to a SharePoint site:

    Exception information:
        Exception type: HttpException
        Exception message: The DataSourceID of 'QuickLaunchMenu' must be the ID of a control of type IHierarchicalDataSource.  A control with ID 'QuickLaunchSiteMap' could not be found.
    Request information:
        Request URL:
    http://server2008:1000/default.aspx
        Request path: /default.aspx
        User host address: fe80::24c5:21da:f8e8:22a1WSS_Minimal
        User: DEVELOPMENT\Administrator
        Is authenticated: True
        Authentication Type: NTLM
        Thread account name: DEVELOPMENT\svcMOSSDBAccess

    And I see that this is also in the event log next to each of the above errors as well:

    Safe mode did not start successfully. Could not load file or assembly 'System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its dependencies. The system cannot find the file specified.

    After some looking in to it a bit I found that the safecontrol entry for the library containing the code for my Silverlight code in the web.config of each web app was what was killing it. So after putting two and two together (and reading a few forum posts) I realised that my code had a dependency on the System.Windows DLL that silverlight provides. The solution then is to make sure that System.Windows.dll and System.Core.dll are copied to the GAC from the silverlight directory (which in this case is C:\Program Files (x86)\Microsoft Silverlight\2.0.31005.0).

    I'm still a little uncertain if I would go abotu putting those DLL's into my WSP file - I don't think I will, I will just document it as a separate process that needs to happen before the WSP file is deployed. Would be interested to hear anyone's thoughts on this though, especially if you have deployed silverlight to MOSS before and come across the same issue.

    11/26/2008

    Customising SharePoint navigation using OOTB features

    If you have ever written a custom site definition, then chances are you have also probably wanted to control the site navigation settings for your new site def as part of the definition (rather than something that must be changed after the site is created, or something that you have to write your own feature for). Well as luck would have it there is an OOTB feature that you can use to set the navigation settings of your site, it's just that it's properties aren't very well documented.

    To control the navigation settings of your site you need to activate the 'NavigationProperties' feature and specify the properties that you want to apply to the site. The best place I have found to do this is in the onet.xml file for your site definition as you can specify appropriate properties for each configuration of your site. Here is an example of a basic implementation of this feature:

       1: <WebFeatures>
       2:     ...
       3:     <Feature ID="541F5F57-C847-4e16-B59A-B31E90E6F9EA">
       4:       <!-- Per-Web Portal Navigation Properties-->
       5:       <Properties xmlns="http://schemas.microsoft.com/sharepoint/">
       6:         <Property Key="InheritGlobalNavigation" Value="true"/>
       7:         <Property Key="IncludeSubSites" Value="true"/>
       8:         <Property Key="IncludePages" Value="false"/>
       9:       </Properties>
      10:     </Feature>
      11:     ...
      12: </WebFeatures>

    The above will activate the feature and tell the site to inherit the global navigation, and to show sub sites in the navigation but not to show pages. There is a pretty nice selection of properties to include with this feature if you want to (this is the undocumented part), here is a list of them and what they do:

    • IncludeInGlobalNavigation - (Boolean) Tells SharePoint that this site should/shouldn't be included in any global navigation
    • IncludeInCurrentNavigation - (Boolean) Tells SharePoint that this site should/shouldn't appear in any current navigation
    • InheritGlobalNavigation- (Boolean) Tells the site that it should/shouldn't inherit the global navigation from the parent site
    • InheritCurrentNavigation- (Boolean) Tells the site that it should/shouldn't inherit the current navigation from the parent site
    • ShowSiblings - (Boolean) Tells SharePoint that the sibling sites of this site should be shown or not shown in the navigation
    • IncludeSubSites - (Boolean) Tells SharePoint to show/hide sub-sites from the navigation
    • IncludePages - (Boolean) Tells SharePoint to show/hide pages in the current site from the navigation
    • OrderingMethod - (OrderingMethod) This enum tells SharePoint how to sort the navigation items
    • AutomaticSortingMathod - (AutomaticSortingMethod) This enum tells SharePoint how to sort the navigation if the OrderingMethod property is set to 'Automatic'
    • SortAscending - (Boolean) Tells SharePoint if the navigation should be sorted in ascending order

    The two enum options use the following options that are pretty self explanatory:

    OrderingMethod: Automatic, ManualWithAutomaticPageSorting, Manual
    AutomaticSortingMethod: Title, CreatedDate, LastModifiedDate

    Also I'll just quickly highlight the difference between global navigation and current navigation. The global navigation is the navigation that goes across the top of the page, and the current navigation refers to the quick launch that runs down the side of the page.

    One other thing that is worth mentioning is that the property "AutomaticSortingMathod" has a typo in the 'method' part of the name (a instead of e). This is deliberate, and not one of the many typos I know I make when I blog. If you reflect the feature receiver for this feature you will see it expects it to be spelt this way.

    So if you put some of these features together you get a lot of control over the navigation settings of your site without having to write and custom code to change the settings, and it is all still controlled through features. A great way to use this (and this is how I am implementing it currently) is for a portal site. I am using the portal provisioning provider (see my post about this at http://pointstoshare.spaces.live.com/blog/cns!AEC42F315B4528B0!3139.entry) to create a portal, and I list the sites in my portal.xml file in the order I want them to appear in the navigation. Then I set the navigation to orderthe pages by order date and then to not show pages so I get the sites I want in the global navigation. Here is the feature XML for that.

       1: <Feature ID="541F5F57-C847-4e16-B59A-B31E90E6F9EA">
       2:   <!-- Per-Web Portal Navigation Properties-->
       3:   <Properties xmlns="http://schemas.microsoft.com/sharepoint/">
       4:     <Property Key="InheritGlobalNavigation" Value="true"/>
       5:     <Property Key="IncludeSubSites" Value="true"/>
       6:     <Property Key="IncludePages" Value="false"/>
       7:     <Property Key="OrderingMethod" Value="Automatic"/>
       8:     <Property Key="AutomaticSortingMathod" Value="CreatedDate"/>
       9:   </Properties>
      10: </Feature>

    So there we have it, one of the longer blog posts I have put together in a little while. Hopefully you can use this to get your navigation settings right without having to write your own features for it!

    11/25/2008

    Announcing Isolator for SharePoint : Unit testing for SharePoint made easier

    If you have been a SharePoint developer for any period of time, you might know that testing SharePoint applications can be a troublesome experience. Well thankfully there are people out there that are working to make this an easier process, such as the folks over at TypeMock. Here is some info from their web site about a new product call 'Isolator for SharePoint'

    Typemock are offering their new product for unit testing SharePoint called Isolator For SharePoint, for a special introduction price. it is the only tool that allows you to unit test SharePoint without a SharePoint server. To learn more click here.

    The first 50 bloggers who blog this text in their blog and tell us about it, will get a Full Isolator license, Free. for rules and info click here.

    So, obviously I am trying to get myself a free license here so I can check the product out - If I do get one I will be sure to put info here about how the product goes!