Monday, October 7, 2013

SharePoint's Automatic Workflow Cleanup and a Loss of Approvals

The Problem

I haven't posted in a while because I have been really busy at work. But, I think it appropriate to take a little bit of time to detail a very serious problem that cropped up. Specifically it applies to approval workflows and libraries / lists being audited. And, I want to take some time to also explain what I did to work around this issue.

For this scenario I will use the Foo library and the Bar workflow in any given example.

So last week an issue come in that the approvals in the Foo library had suddenly disappeared. Auditors had gone in to review the library but any approval that had been showing in the Foo Approvals column, courtesy of our Bar approval workflow, had suddenly vanished if the approval itself was older than 60 days.

I immediately went into the Foo Approval Tasks list to find that the approval tasks themselves had also disappeared. Not to be found in the Site or the Site Collection Recycle bins either.

My next diagnostic step was to look at the Activity Duration Report to determine if these approvals had ever even occurred in the first place.



Sure enough, all of the data was there supporting that the approvals had occurred. After much more painstaking research and eyebrow raising I came to the conclusion that this wasn't the doing of some human. I had begun to think that someone had come in and deleted the Bar Workflow just to recreate another Bar Workflow with the same name. This too, wipes out prior Approvals but doesn't explain the every 60 days component.

Then I found it. The Automatic Workflow Cleanup job.


Microsoft actually designed this job in SharePoint to delete workflow instances and related task entries that still existed 60 days after the workflow completed or was canceled. WHAT?!? So now there is no evidence that my valuable and precious List items were approved?

Here is what they say about this:
By default, Microsoft SharePoint Server 2010 runs a daily Workflow Auto Cleanup job to permanently delete workflow instances and related task entries that still exist 60 days after a workflow is completed or canceled. Workflow history items themselves are not deleted, but the entry point to view them on the status page for a particular instance of a workflow will no longer be available. You can disable the Workflow Auto Cleanup job if you want to keep workflow data available longer. However, as with any SharePoint list, as the workflow history and task lists grow in size, site performance may be compromised. If you are concerned about the size of these lists, keep the Workflow Auto Cleanup job enabled. Whether or not you keep the Workflow Auto Cleanup job enabled, you can create a separate history and task list for each workflow association to distribute items across lists.
Workflow history is not intended to be used to audit workflow events and is not necessarily secure because a user who has edit permissions on the site can update items in the history list, by default.
And there you have it. In a nutshell we are not supposed to be using workflows for auditing purposes. *sigh*

The Workaround

The most appropriate work around is to use the auditing capabilities already found within SharePoint. I would even suggest doing this in conjunction with a Records Center and coupled with a solid retention policy. No small task when given the scale of that project. IT Admins, corporate Compliance Officers, Legal, Finance, Business Analysts and many other folks are required for that undertaking.

To solve this issue quickly I did the following:

  1. Opened the Workflow History list. This can be accessed by visiting http://[domainname]/[sitename]/lists/Workflow%20History or another similar path depending on where you are pointing the workflow's history.
  2. Created a new view called "Audit View" using the "All History" view as a basis. This will create a special URL http://[domainname]/[sitename]/lists/Workflow%20History/Audit%20View.aspx. During creation of the view I would recommend a few slight changes to make this easier to read for your auditors / compliance officers.
    • Only display the Description, Outcome, Date Occurred, User ID, and Data columns.
    • Sort by Date Occurred.
    • Filter where List ID is equal to the GUID (for example {066c342b-0715-4583-8a20-9a1f725e5359} or another number) to the type of item you are auditing. This is particularly useful if you are grouping all your histories into one history list.
    • Group by Primary Item ID and then by Workflow History Parent Instance.
  3. Back on your actual document library create a new Calculated column called "Audit Link". The formula will be similar to the following (change URL as is appropriate).
    =CONCATENATE("http://[domainname]/[sitename]/lists/Workflow%20History/Audit%20View.aspx?FilterField1=Item&FilterValue1","=",ID)
  4. You should now have a column that contains a URL to your Workflow History. Another annoyance I found is that apparently you can't put proper URLs in a calculated field. So users will need to copy / paste this into the browser. Or, I would recommend using a bit of JavaScript to handle the links for you.
  5. The last step involves going back to your Workflow History list. I would recommend modifying the permissions on this list as you deem is appropriate. Microsoft is correct in stating that the workflow history "...is not necessarily secure because a user who has edit permissions on the site can update items in the history list, by default.". I would recommend Restricted Read or Read here.
That's it! This is really only a short term work around for this problem. As I outlined above a more proper solution is to discuss File Retention, Compliance, and Record Centers with the appropriate teams.

Monday, July 1, 2013

Add additional / multiple build controllers for Microsoft Team Foundation Server 2012

While Microsoft doesn't officially support a multi-controller scenario for Team Foundation Server (TFS), sometimes it is a necessity. Especially when you have multiple Team Project Collections and are left holding one build controller.

The following steps will allow you to build additional controllers and manage them, in TFS 2012. As always,  I recommend doing a snapshot or backup of your server prior to making high-level changes such as this.

  1. First, open a Command Prompt window (as an Administrator).
    • From the Windows 2012 Server screen right-click and go to All apps.
    • Under the Windows System category right-click on Command Prompt and select the option to Run as administrator.
  2. In the Administrator: Command Prompt window, type in the following command.

    Note: You need to replace the [service name] with your build controller's service name. Also, you need to replace the [display name] as well with something that makes sense for you. I've included some best practice examples for you. "BuildService-TeamProjectCollectionName" and for the Display Name you would enter "Visual Studio Team Foundation Build Service Host (TeamProjectCollectionName)" for example. Make sure to remove the placeholder brackets [ ] and to keep spacing as it is below. Or this will not work.

    sc.exe create [service name] binpath= "C:\Program Files\Microsoft Team Foundation Server 11.0\Tools\TFSBuildServiceHost.exe /NamedInstance:[service name]" DisplayName= "[display name]"

  3. Hit your Enter key. You should get a message that [SC] CreateService SUCCESS. Otherwise, review the command above to rule out any errors or mistakes in keying.
  4. Now you need to register the controller and agents via the Team Foundation Server Administration Console. However, if you open the console via your icon you will only see your original build controller.

    There is an easier way. Create a batch file (.BAT) on your desktop. Add the following code to it, modifying where appropriate and without the placeholder brackets [ ]:


    :: Set the service host environment variable
    set TFSBUILDSERVICEHOST.2012=[service name]

    :: Open the Team Foundation Server Administration Console
    "C:\Program Files\Microsoft Team Foundation Server 11.0\Tools\tfsmgmt.exe"

  5. Run the batch file. This should open a TFS Admin Console window where the new build controller is accessible.
  6. On the Build Configuration screen click on the Register link. This process is similar to that found here. Your registration properties should be left pretty much alone. The only exception here is the Display Name. Best practice is to call it your Default Controller - YourServiceName.
  7. In some cases there may be a conflict between your controller URI and the original controller (they both may try to use the same address / port). Give it a few minutes and if an error appears on the screen via logs do the following:
    1. Register a build controller + agent as explained here. Then unregister the build controller service.
    2. Re-register the build controller service. After which, modify the URL to use a different port.
    3. Register your build controller + agent as you normally would.
That's it. You should now have two or more build controllers that won't conflict with one another. And, you can use that batch (.BAT) to get back in to manage your build controller / agents as needed.

Good luck and I hope this helps.

Thursday, June 27, 2013

Team Foundation Server - Branching and Merging Demystified

I have been asked frequent times to explain how branching and merging work in Microsoft's Team Foundation Server (TFS). There is often a lot of uncertainty (even for developers) which surrounds the concepts of branching and merging. More often than not this doubt arises regardless of the repository solution being used.

It is my hope that some of the information (both my own experience and knowledge gathered collectively from the internet) I am about to detail will not only explain some of the fundamentals behind setting up a correct branching and merging strategy, but will also help provide some guidelines for you to apply in your own solution.

Please note that most of the concepts below can really be applied to any repository solution. But, the information I am providing is truly in relation to Microsoft's TFS.

Also, this is not light reading by any means. So don't expect a TLDR version. (That is too long, didn't read for you non-geek folks)

What is a branch?



A branch is a set of files in a different part of your repository that allow two or more teams of people to work on the same part of a project in parallel. When you create a branch, it does not actually create new copies of all those files on the server. It instead creates a record pointing to them. This is the primary reason why creating a branch with a vast number of files can be done so quickly.

An example...


Imagine that two developers have modified the same line of code in the same file across two different branches. The person responsible for merging those two branches together must make a decision as to which change will "take". In some cases, this will result in a hybrid merge, where the combination of the intent behind the two changes requires a different result than the text in those version being merged.

The branch that contains your changes that are being merged is commonly referred too as the source branch. The branch you want to merge your changes into is referred too as the target branch. The common ancestor between them is often referred too as the base version. When you do a merge, you can select a range of changes in the source branch to merge into the target branch.

What happens if there is a conflict?



If the same file has been modified in both the source and the target branches, TFS will mark this as a conflict. If the file has been modified in both branches, it will always be flagged as a conflict, even if the changes are to completely different parts of the file.

For certain changes, TFS can make an educated guess about what should happen. This is often referred to as an automerge. When the automerge occurs, TFS will allow you to review the changes to make sure the desired merge behavior has been performed.

Another example...


Two different bug fixes are being implemented. You probably want both changes. However, if the two corrections were just fixing the same bug in two different ways, you may want to consider a different avenue. In most cases, where your development team has good communication, the changes are a result of different changes being made to the file.

In the example above, automerge can do a great job of merging the changes together, making it easy for the developer to validate those changes.

There are many scenarios that may require more manual conflict resolution. In that the person performing the merge is responsible for deciding the correct outcome based on their understanding of the code and communicating with the team members who made the conflicting changes to understand their intent.

What is a branch relationship?



When you create a branch, the relationship between those branches form a standard hierarchy. In that the source of the branch is the parent, and the target of the branch is the child. Children who have the same parent are often referred too as sibling branches.

Baseless Merging



A baseless merge is when two arbitrary branches merge without reference to the base version. This is sometimes a necessity when the source code was originally imported in a flat structure without the branch relationship being in place, or if you want to merge between a branch and another branch not a direct parent or child.

Since there is not a base version to compare against, the chance that the server will detect conflicts between the two branches increases significantly.

Yet another example...


If a file is renamed in one branch and modified in another, it will show up as a file delete conflicting with the file edit, and then a file add that gives no hint as to which file it was related to, or that there was an edit intended for this file in the other branch.

For this reason, among others, baseless merges are frowned upon in TFS. A warning will appear whenever a baseless merge operation is selected in Microsoft's Visual Studio (VS). Standard merging through the VS or Eclipse clients are the best practice and recommended method. Where only one branch up or down (a parent to a child or vice versa) is allowed. Your branching strategy and model should attempt to constrain most merges between parent and child branches to minimize the amount of baseless merging required.

What is Forward or Reverse Integration?



When you merge code from a parent branch to the child branch, it is considered forward integration (FI). When you merge code from a child branch to the parent branch, it is referred to as reverse integration (RI). If you are doing feature development in branches, it is common to use FI at various points during the feature development cycle, and then to use RI at the end.

What are some common Branching Strategies?



Back in February I posted a very brief description of a Branch Per Release versus a Code-Promotion Branching strategies. In it I touched on the flaws and benefits surrounding those branching strategies. This time I will spend more time detailing some common strategies, why we have them, and how they are used.

Each strategy has its pros and cons. However, just as every strategy in chess is made up of simple moves, every branching strategy uses one or more combinations of some basic techniques. When developing your own strategy, you should take into account your own needs.

When looking at any branching strategy, you should keep in mind the following:
  • Always chose simplicity over control.
  • Branch only when you really need to.
  • If you ever want to merge two branches together, keep the time between merges to a minimum.
  • Ensure that your branch hierarchy matches the path you intend your merges to follow.

No Branching



This may sound a bit counterintuitive, but often the simplest technique is to not branch at all. This should always be your default position when it comes to branching and merging scenarios. Do not branch unless you need to. Keep in mind that you are using a version control tool that tracks changes over time. You can branch at any point in the future from a point in the past. This gives you the flexibility of not having to create a branch "just in case". Again, create branches only when you really need too.

There are measures you can take, however, to ready yourself to make branching easier in the future if you decide you need a branch. Some TFS specifics incoming.
  1. When you first create your team project in TFS create a folder called Main.
  2. Check it in.
  3. Right-click the folder in Source Control Explorer and select Branching and Merging | Convert to Branch.
This gives you an easy point to branch from in the future, and it also makes you think about the areas of your source code that live in the same branch together. This will also help you should you ever decided to do a branch.

No branching? In reality you have only one branch of code to work in for all teams. This technique works great when you have small teams working on the same codebase, developing features for the same version of the application and supporting only one version of the application at a time. At some point, no matter how complex your branching strategy evolves to support your business needs, you need at least one stable area that is your main (also known as the mainline or trunk) code. This is a stable version of the code that will be used for the build that you will create, test, and deploy.

During stabilization and test periods, while you are getting ready to release, it may be necessary for the team to not check in any new code (essentially a code freeze). With smaller teams working on a single version, this does not impact productivity, because the people who would be checking in code are busy testing to ensure that the application works, as well was getting ready for deployment.

With this in mind, there is no way to start work on something new before the final build of the current version has been executed. The code freeze period can, therefore, be very disruptive because there is no way to start work on the next version until the current one has shipped. It is these times when other strategies become useful for teams of any size, even a team of one.

Branch per Release



For development teams that employ branching, the most common branching technique is branch per release. With this technique, the branches contain the code for a particular release version.

Development starts in the Main branch. After a period of time, when the software is considered ready for testing, a branch is made to the V1.0 branch under Releases/Staging or Releases/Test. At which time the test build is pushed into the staging or test environments. Again, after a period of time, when the software is considered ready, a branch is made to the Releases/Production location with the final production build getting a label to indicate which versions of which files were in that version. Meanwhile, development of new features for version 2 (V2 in this example) continues on the Main branch.

A scenario to consider...



Say some minor changes are requested or bugs discovered in production, and a small modification is necessary to reflect how the business needs something to work. However, the development group does not want to include all the work for V2 that has been going on in the Main branch. Therefore, these changes are made to the V1 branch, and builds are taken from it. Any bug fixes or changes that must also be included in the next version (to ensure the bug is still fixed in that next release) are merged back (reverse-integrated or RI) into the Main branch. If a bug fix was already in the Main branch, but needed to go into V1, it might be merged (forward-integrated or FI) into it. At a certain point, the build is determined to be good, and a new V1.1 build is performed from the V1 branch and deployed to production.

During this time, development on the next version can continue uninterrupted without the risk of features being added into the code accidentally and making their way into the V1.X set of releases. At a certain point, suppose it is decided that V2.0 is ready to go out the door, the mainline of code is branched again to the V2 branch, and the V2.0 build is created from it. Work can continue on the next release in the Main branch, but it is now easy to support and release new builds to customers running on any version that you want to keep supporting.

Branch per release is very easy to understand and allows many versions to be supported at a time. It can be extended to multiple supported releases very easily, and it makes it trivial to view and compare the code that was included in a particular version of the application. Branch per release is well-suited to organization that must support multiple versions of code in parallel -- such as a typical software vendor.

However, for a particular release, there is still no more parallelism of development than in a standard "no branching" strategy. Also, if the organization must support only two or three versions at a time (the latest version, the previous version, and, perhaps, the version currently being tested by the business), this model can lead to a number of stale branches. While having lots of old, stale branches doesn't impact performance of Team Foundation Server, or even cause any significant additional storage requirements, it can clutter the repository and make it difficult to find the versions you are interested in -- especially if the organization frequently releases new versions. If this is the case, you may want to move old branches into an Archive folder, and have only the active branches (the versions that the development team are currently supporting) in the Releases folder.

Code-Promotion Branching



An alternative to branch per release is code-promotion branching (or, as it is sometimes referred to, promotion-level branching). This technique involves splitting the branches into different promotion levels.

As before, development starts with just the Main branch. When the development team is ready to test the application with the business, it pushes the code to the Test branch (also often called the QA or Staging branch). While the code is being tested, work on the next development version is carried out in the Main branch. If any fixes are required during testing, they can be developed on the Test branch and merged back in to the Main branch for inclusion in the next release. Once the code is ready to release, it is branched again from Test to Prod. When the next release cycle comes along, the same is done again. Changes are merged from Main to Test, and then Test to Prod.

Code-promotion branching works well in environments that have a single version running in production but have long test-validation cycles that do not involve all of the development team. This allows development to continue on the next version of Main while test and stabilization of the build occurs in the Test branch. It also makes it trivial for the development team to look at the code currently on each system. Finally, a branch structure makes it easy to create an automated build and deployment system using Team Foundation Build that can automatically update the QA/Test/Staging environment as code is pushed to the QA branch.

Feature Branching



The previous branching strategies all involve a single team working on the system in its entirety as it works towards a release. All features for that release are developed in parallel, and the build can be deployed only when all features in flight have been completed and tested. However, in large systems, or systems that require very frequent deployment (such as a large commercial website), feature branching (or branch per feature) can be useful.

Feature branching is used when a project requires multiple teams to be working on the same codebase in parallel. For example, you could have four feature teams working in separate branches (lets call it F1, F2, F3, and F4). Note that in a real branching structure, the feature branches themselves would likely have meaningful names such as BroadbandSelling, TroubleTickets, or whatever shorthand is used by the project to refer to the feature that is under development. The Main branch is conserved "gold code", which means no active development goes on directly in this branch. However, a feature must be reverse-integrated into this branch for it to appear in the final build and for other teams to pick it up.

Initially, F1 is started with a branch from Main. But, while it is being developed, a second and third team start F2 and F3, respectively. At the end of development of the feature, F1 is merged back into the Main branch, and the F1 branch is deleted. Then, that team starts on feature f4. The next feature to finish is F3, followed by F2. At each point, once the feature is merged into the Main branch, a new version of the software is released to the public website. But only one version is ever supported at any time.

Feature branching allows for a large amount of parallel development. However, this comes at the cost of delaying the pain of integrating each team's changes until the feature is complete, and you are merging the feature branch back into the Main branch. For example, when merging the F2 branch, all changes and inevitable conflicts introduced by features F1, F2, F3, and F4 must be analyzed and resolved.

The longer a period of time that code is separated into branches, the more independent changes occur and, therefore, the greater the likelihood of merge conflicts. To minimize conflicts, and to reduce the amount of integration debt building up, you should do the following:
  • Keep the life of the feature short. Features should be as short as possible and should be merged back into the Main branch as soon as possible.
  • Take integrations from the Main branch regularly. When F1 is merged back into Main, the feature teams still working on their features should merge those changes into their feature branches at the earliest possible convenient point.
  • Organize features into discrete areas in the codebase. Having the code related to a particular feature in one area will reduce the amount of common code being edited in multiple branches and, therefore, reduce the risk of making conflicting changes during feature development. Often, the number of teams that can be working in parallel is defined by the number of discrete areas of code in the repository.
When using feature branching, the whole team does not necessarily have to be involved. For example, one or two developers might split off from the rest of the team to go work on a well-isolated feature when there is a risk of the move not being possible (they are working on a proof of concept), or when it is decided that the current release should not wait for that particular feature to be implemented.

What does this all mean?



In conclusion, you can now see the benefits of having a solid branching strategy before utilizing your repository tools. Be it TFS or some other solution. TFS not only allows for some complex software configuration management scenarios, but also provides the tooling to help understand what is happening with changes in your repository

Friday, June 21, 2013

Some minor configuration needed after a K2 Blackpearl installation

The below information details the steps involved for configuration after a fresh installation of K2 Blackpearl. This is strictly for development licensed installs. I just wanted to share this information in the hopes that it would help some fellow admins curb a bit of frustration after their install is finished.
  1. ​Access Central Administration
  2. Under "K2 for SharePoint" select the Activate All K2 Features and K2 Configuration Settings option.
  3. Add a check next to sp-intranet-scadmins under the Workflow Designers section.
  4. Repeat step 3 for the Workflow Participants section.
  5. Click OK.
  6. Close out of Central Administration
  7. Navigate to C:\inetpub\wwwroot\wss\VirtualDirectories and select the virtual directory setup for your SharePoint web application. Open it.
  8. Open the web.config for editing.
  9. Search for the <PageParserPaths> tag. You will add a new tag between that and the closing tag.

    <PageParserPath VirtualPath="/*" CompilationMode="Always" AllowServerSideScript="true" IncludeSubFolders="true" />
  10. Save the web.config.
  11. Restart IIS via Administration Tools | Internet Information Services (IIS) Manager.
That's it. You should now be configured for K2 Blackpearl. You can tweak the security settings via steps 3 and 4 depending on who you want having access to what.

How to add SMTP to your SharePoint farm?

Just wanted to post a really quick, and hopefully helpful, guide on setting up the SMTP Server feature for your SharePoint 2010 farm.

  1. Server Manager
    • Features
    • Add Features
      • SMTP Server (in list)
        Click on Add Required Role Services
        • Next
        • Next
        • Next
        • Install
      • Click on Close when finished
    • Exit the Server Manager
  2. (Optional) Control Panel
    • System and Security
      • Administrative Tools
        • Internet Information Services (IIS) 6.0 Manager
          • XXXX (local computer)
            • SMTP Virtual Server #1
              Right-click, properties.
              • Access Tab
                • Authentication
                  May have to adjust for Active Directory (AD).
That's it. SMTP should now be enabled on your farm.

How do I update the favicon.ico for my SharePoint 2010 site?

Tired and sick of the stock orange people SharePoint icon that haunts you at every turn in SharePoint? It is quite simple to update the favicon.ico to something a little more appropriate for your site's branding. Just follow the steps outlined below and you will be all set.
  1. Upload your new favicon.ico file to a location you can easily manage it. Such as your Site Collection Images library or your SharePoint Hive.
    • From the top level of your site or site collection click on All Site Content.
    • Under Document Libraries click on Site Collection Images.
    • On your ribbon menu at the top, click on Documents and click on Upload Document under the New tab.
    • Upload your favicon.ico. Once finished you will need to copy the URL. Unless you made some special changes this will likely be the URL of /SiteCollectionImages/favicon.ico (this is a relative URL as opposed to an absolute URL, it's better... trust me...).
  2. From the top level of your site or site collection click on Site Actions and select Edit in SharePoint Designer.
  3. Under your Site Objects on the left you will see the Master Pages object. Click on it.
  4. On this list you will see a master page called v4.master. Right-click on this and select Edit File in Advanced Mode.
    • If prompted to check out, select Yes.
  5. In the advanced editor, switch the view from Design (or Split if that is what you have it on) to Code.
    • Look for the tabs Design - Split - Code located at the bottom of the screen.
  6. You are then going to replace...

    <SharePoint:SPShortcutIcon runat="server" IconUrl="/_layouts/images/favicon.ico"/>

    ...with...

    <SharePoint:SPShortcutIcon runat="server" IconUrl="/SiteCollectionImages/favicon.ico"/>

  1. Save the file.
  2. Back on the master pages list, right-click on the v4.master again. This time select Check In. You must check in a major version so this is published. Feel free to add an appropriate note, such as "Updated the favicon for the master page".
  3. Click on Ok.
  4. Back in your web browser, click on Site Actions and select Site Settings.
  5. Under the Galleries heading click on Master pages.
  6. In the drop-down menu (indicated by a small triangle) for the v4.master you should get an option to Approve/Decline the publish.
  7. Approve and place notes if you feel it is appropriate.

That's it, you may need to clear your browser cache and in some rare cases you may need to have the administrator restart IIS. But, you should now see a nice, new favicon.

Tuesday, February 19, 2013

Building custom SharePoint 2010 Site Pages using Visual Studio (Part II)

Hello again. In my previous post I showed you how to create customized Site Pages using Visual Studio (VS) instead of being limited by SharePoint Designer (SPD). Now I am going to explain how to instruct SharePoint that it is alright to allow code-behind for these Site Pages. Which by default, is not allowed.

NOTE: You will absolutely want to configure your event handler to undo these changes when appropriate and to make these changes when appropriate. This way you can be sure that when the feature is activated / deactivated.... you get the drift. My recommendation would be to create a separate feature just for this security change. My previous feature was called CustomPages so I will name this one CustomPages Security.

  1. Add SafeControls
    • Click on your module (SitePages from my last post) and open your properties window.
    • Under the SafeControls section add a new SafeControl.
      • Assembly = $SharePoint.Project.AssemblyFullName$
      • Namespace = CustomPages
      • TypeName = MyCustomPageTemplate
      • Safe = true
      • SafeAgainstScript = false
  2. What happens to my web.config?
    • What is getting added to the web.config is the following:

      <SafeMode MaxControls="200"
                         
      CallStack
      ="false"
                         
      DirectFileDependencies
      ="10"
                         
      TotalFileDependencies
      ="50"
                         
      AllowPageLevelTrace="false">
          <PageParserPaths>
              <PageParserPath VirtualPath="/SitePages/MyCustomPage.aspx*"
                                          CompilationMode="Always"
                                          AllowServerSideScript="true"
                                          IncludeSubFolders="true" />
          </PageParserPaths>
      </SafeMode>
    • Create a new feature and add an event receiver to it. This feature's scope also needs to be WebApplication (you can check by double-clicking the feature to bring up designer view).
    • Add the following code and change as is appropriate for your needs. This is the sample and shouldn't be used as a straight copy / paste.

      using System;
      using System.Collections.ObjectModel;
      using System.Runtime.InteropServices;
      using System.Security.Permissions;
      using Microsoft.SharePoint;
      using Microsoft.SharePoint.Security;
      using Microsoft.SharePoint.Administration;

      namespace CustomPages.Features.CustomPages_Security
      {
          /// <summary>
          /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
          /// </summary>
          /// <remarks>
          /// The GUID attached to this class may be used during packaging and should not be modified.
          /// </remarks>

          [Guid("674c2a19-9913-4465-af57-198bd0416b49")]
          public class CustomPages_SecurityEventReceiver : SPFeatureReceiver
          {       
              public override void FeatureActivated(SPFeatureReceiverProperties properties)
              {
                  SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;

                  SPSecurity.RunWithElevatedPrivileges(delegate()
                  {
                      SPWebConfigModification wcMod = new SPWebConfigModification();

                      wcMod.Path = "configuration/SharePoint/SafeMode/PageParserPaths";
                      wcMod.Name = "PageParserPath[@VirtualPath='/SitePages/MyCustomPage.aspx']";
                      wcMod.Owner = "CustomPages";
                      wcMod.Sequence = 0;
                      wcMod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
                      wcMod.Value = "<PageParserPath VirtualPath='/SitePages/MyCustomPage.aspx' CompilationMode='Always' AllowServerSideScript='true' />";

                      webApp.WebConfigModifications.Add(wcMod);
                      webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
                      webApp.Update();
                  });

              }

              public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
              {
                  SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;

                  SPSecurity.RunWithElevatedPrivileges(delegate()
                  {
                      Collection<SPWebConfigModification> wcMods = webApp.WebConfigModifications;
                      int initialModificationsCount = wcMods .Count;

                      for (int i = initialModificationsCount - 1; i >= 0; i--)
                      {
                          if (wcMods [i].Owner == "CustomPages")
                          {
                              SPWebConfigModification modToRemove = wcMods[i];
                              wcMods.Remove(modToRemove);
                          }
                      }

                      if (initialModificationsCount > wcMods.Count)
                      {
                          webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
                          webApp.Update();
                      }

                  });
              }

          }
      }
There you have it. Not only do you have a customized Site Page from Visual Studio but, it also is allowed to use code-behind. I hope this helps you.

Building custom SharePoint 2010 Site Pages using Visual Studio (Part I)

Hi everyone. I decided today to write some instructions on how to create Site Pages that you can customize via Visual Studio (VS). Including the ability to execute server-side scripting. As I couldn't find a good resource on the internet for this I decided to do it myself.

First you need to create the custom site page. You could go through and build the page completely within SharePoint Designer (SPD) but, this will at least give us a good starting point for VS.

  1. Launch Internet Explorer (IE) and navigate to the Site where you wish to create your custom site page. In my case this will be http://localhost/mycustomsite.
  2. Select Site Actions | Edit in SharePoint Designer.
  3. Select File | Add Item | New Page from Master | v4.master (Default) | Create. When it asks you, change the name to MyCustomPageTemplate and in my case I am using the Site Pages library. But, you can use any Wiki Page Library you have setup as well.
  4. Click OK.
  5. Give it a second or two and when the alert comes up just click Yes.

    NOTE: At this point I am assuming C-Sharp (C#) but if you are a Visual Basic (VB) programmer you can just change the language setting in the page tag as is appropriate.
  6. Switch the page to Design view.
  7. Locate the PlaceHolderMain(Master) content place holder. It is the open area in the middle of the page for those not familiar. In the menu for it, click Create Custom Content. That menu can be accessed by clicking the little drop-down arrow right on the component itself.
  8. You can now click into the PlaceHolderMain(Custom) area, notice it says custom now, and it can be editted. Type some placeholder information like "My Content Goes Here".
  9. Switch the page to Code view.
  10. Hit [CTRL+A] to highlight all the contents of the page and [CTRL+C] to copy it into your clipboard.
  11. Save the page and close SPD.
Now we are ready to get into VS to finish our page up. We are going to use a Module to provision the page(s) in SharePoint. To provision a file into a particular document library (e.g., Site Pages) you need to create a module with the same name as the document library. You then add the files you want provisioned and fix up the Categorical Abstract Machine Language (CAML) file so they load the way you want them too.

  1. Launch VS and create a new Empty SharePoint Project. Let's call it the CustomPages project for now.
  2. Right-click the CustomPages project and select Add | New Item | Module.
  3. Name the module SitePages or whatever your library is and click Add.
  4. In the CustomPages project, select File | New File... | Web | Visual Basic or C# | Web Form and click Open.
  5. Right-click inside the contents of the file (anywhere on the screen should be fine) and select Move Default1.aspx into | CustomPages. Navigate to your SitePages module and save the file there with a name of MyCustomPage.aspx or whatever you want to call it.

    NOTE: Make sure that the new page shows up in your Solution Explorer window under the SitePages folder. If it doesn't you may need to drag-and-drop it there.
  6. Highlight all of the contents of the MyCustomPage.aspx and replace with the contents on your clipboard.
  7. Expand the Features folder and double-click Feature1 to open its settings.
  8. Set the feature title to CustomPages (or whatever makes sense) and set an appropriate description.
  9. Switch back to your solution explorer. Go ahead and delete the Sample.txt document found in your SitePages module folder.
  10. Open the Elements.xml document for editting. Remove the SitePages/ from the Url. The Path attribute should be left alone.
  11. Add the attribute Type with the value GhostableInLibrary to the File element you just modified. Also, add a Url of SitePages to the Module element. Should look like something this:
     
    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
        <Module Name="SitePages" Url="SitePages">
            <File Path="SitePages\MyCustomPage.aspx"
                     Url="MyCustomPage.aspx"
                     Type="GhostableInLibrary" />
        </Module>
    </Elements>
     
  12. Save all of your changes.
You should now be able to Build and then Deploy. Congratulations, you now have a Site Page constructed in VS and deployed to your site.

In my next blog post I'll describe how to mark your page as safe and show how to enable code-behind for these Site Pages.

Thursday, February 7, 2013

How to setup a SharePoint 2010 list to accept email submissions

This question has actually cropped up often here recently. Both for work and from members of the SharePoint community. Essentially people want to be able to hit an email address and have their contents transform into SharePoint 2010 list objects.

This is actually very easy to configure and setup. The following instructions assume that Exchange is being used. So please feel free to modify "here and there" as necessary.

First, you need to make sure your SharePoint Farm has SMTP enabled. Next, after following the instructions on MSDN do the following (or have your Farm Administrator do the following):

  1. Open Central Administrator
  2. Click on the System Settings heading.
  3. Under the E-Mail and Text Messages (SMS) heading, click on Configure incoming e-mail settings.
    • You may see a few messages if this has never been setup before. The SMTP service must be running on the farm. Refer to the MSDN link above if you need help configuring this.
  4. Under the Enable Incoming E-Mail category:
    • Enable sites on this server to receive e-mail? (Yes)
    • Use the SharePoint Directory Management Service to create distribution groups and contacts? (Yes)
  5. Click OK.
  6. Click on the Monitoring link under your Quick Launch navigation (on the left).
  7. Click on Review job definitions under the Timer Jobs heading.
    • This may take a little bit to render the page as jobs are cleared.
  8. Click on the job Microsoft SharePoint Foundation Incoming E-Mail.
    • You can reconfigure the job timer for emails, if necessary. Please note that if the job doesn't run properly you should check security on your "Drop Folder".
  9. Exit Central Administrator
Next, you will need to configure your List or Library to properly accept emails as added items on the list / library. Please keep in mind you can only do this for the following types of SharePoint lists:

  • Document library
  • Form library
  • Picture library
  • Announcements list
  • Calendar list
  • Discussion board
  • Blog
SharePoint doesn't support if you are using a custom list or something outside what I listed above. To configure your list (or library, which is very similar in settings) just do the following:

  1. In the List use the ribbon to access the List Tools | List | List Settings.
  2. Under the Communications heading you should now see an Incoming e-mail settings option. Click on it. If it isn't there, you need to recheck your settings within Central Administrator.
    • Allow this list to receive e-mail? (Yes)
    • E-mail address:
      • Enter an appropriate address. The @domain.com should automatically be appended with whatever your Farm Administrator has setup on the server.
  3. Click OK.
You should be able to test your settings after this last step. For example, if you send an email to an Announcements list the subject line of the email should appear as the title of the announcement. The body of the email is the body of the announcement.

So there you have it. A very simple way of setting up your SharePoint lists to be updated via email.

Wednesday, February 6, 2013

Completely delete or remove a project from Team Foundation Server (TFS) 2010

Hello again -

Team Foundation Server (TFS) is designed not to permanently delete items you remove. Such as projects, branches, or even unused folders. It is a version control system for source code afterall. Though there is a way around this via command line if you are absolutely sure you want to remove those items.

I use a project here as an example. But you can really target anything. Simply by adjusting the path (URL) to the item. To delete a project completely from Team Foundation Server you will need to run the following command within your Administrator Visual Studio Command Prompt (2010).

TFSDeleteProject [/q] [/force] [/excludewss] /collection:<url> <team project name>

[/q] - Do not prompt for confirmation.

[/force] - Continue even if some data cannot be deleted.

[/excludewss] - Exclude the project's SharePoint® portal site when deleting the project. This option will leave site intact so that it remains for other projects that may be using it.

/collection:<url> - The url for a Team Project Collection.

<team project name> - The name of the project. Use quotes if there are spaces in the name.

Tuesday, February 5, 2013

How to install a self-signed certificate as a Trusted Root CA

I'm sure there are other sources on the Internet for this task but, I wanted to provide what worked for me. Here are the basic instructions for installing a self-signed certificate into your trusted root Certification Authority (CA). These instructions were designed with Windows Vista or higher in mind. But, should suffice as a basic guideline for lower versions of Windows. Be absolutely sure you trust this certificate before doing this.

  1. When you get the security alert that "The identity of this web site or the integrity of this connection cannot be verified" you should see an option to View Certificate. Click on that.
  2. Next, click on Install Certificate....



  3. Under the Certificate Import Wizard choose the option "Place all certificates in the following store" and select browse.


  4. Select Trusted Root Certification Authorities and click OK.


  5. Select Local Computer (some cases you have to select Show Physical Stores here). Click OK.


  6. Click Finish on the Completing the Certificate Import Wizard screen.


  7. Click yes on the warning message to install the certificate.


  8. Done!
You shouldn't be pestered by the alerts any longer for the certificate that you just installed. Remember though that these are only valid for the domain you are installing on. You can follow the same instructions for other domains though if needed.

What are Software Requirements?

Hello again. Good programmers have at least a basic understanding of project management. This includes project requirements. I'll attempt to explain below an example of what those requirements look like when you are dealing with a new software project.

Software Requirements are the elicitation, analysis, specification, and validation of requirements for software. A requirement itself is a singular documented physical and functional need that a particular solution or service must be or must perform.

The following information should always be provided when putting together proper software requirements within a software requirements specification (SRS) document.

Requirement Type The type of requirement.
Event / Use Cases List of events / use cases that need this requirement.
​Description Describe the requirement being requested within the project. Additional requirements should be inclusive of additional secondary headers (for table of contents tracking in documentation).
​Justification ​Describe the justification of the requirement.
Measurement Describe the measurement of the requirement such that it is possible to test if the solution matches the original requirement.
​Source Who raised this requirement?
​Customer Satisfaction ​Degree of stakeholder happiness if this requirement is successfully implemented. Scale from 1 = uninterested to 5 = extremely pleased.
​Customer Dissatisfaction ​Measure of stakeholder unhappiness if this requirement is not part of the final product. Scale from 1 = hardly matters to 5 = extremely displeased.
Dependencies A list of other requirements that have some dependency on this one.
Conflicts Other requirements that cannot be implemented if this one is.
Supporting Materials This is a pointer to documents that illustrate and explain this requirement

Branch Per Release vs. Code-Promotion Branching

Making for lost time on my blog here since I haven't posted in awhile. I wanted to give a clear picture between a "branch per release" approach to source code control. And, a "code-promotion branching" approach. For those unfamiliar with the two.

Branch Per Release

Development starts in the Main (or it is sometimes called the Trunk) branch. When a feature or change is requested a branch is created to the 1.0.0-Candidate (or sometimes the V1) branch. After a period of time, when the software is considered ready, it is built to the Test environment. It is then released into Production with the code in the final Production build getting a label to indicate which versions of which files were in that version. This is also known as "tagging". Once built into Production, a "tag" branch is created to the 1.0.0-Release.



Code-Promotion Branching

Development starts with just the Main branch. When the development team is ready to test the application with the business, it pushes the code to the Test branch. While the code is being tested, work on the next development version is carried out in the Main branch. If any fixes are required during testing, they can be developed on the Test branch and merged back into the Main branch for inclusion in the next release. Once the code is ready to release, it is branched again from Test to Production. When the next release cycle comes along, the same is done again. Changes are merged from Main to Test, then Test to Production.

Code-promotion branching works well in environments that have a single version running in Production, but have long test-validation cycles that do not involve all of the development team. This allows development to continue on the next version in Main while testing and stabilization of the build occurs in the Test branch. It also makes it trivial for the development team to look at the code currently on each system. Finally, the branch structure makes it easy to create an automated build and deployment system using Team Foundation Build ( http://msdn.microsoft.com/en-us/vstudio/ff637362.aspx ) that can automatically update the QA/Test environment as code is pushed to the QA branch.

I don't want people requesting access to my stuff!!!

I haven't posted in quite some time. So I figure it is time to get back into adding to my blog. To kick things off I am going to keep it pretty simple today. I'll explain how to enable / disable access requests.

Essentially, when it comes to access requests, SharePoint 2010 works in two ways. First, if you deny access to a site, list, library, or what not, the system will conceal (permission trim) that object from your view. Assuming it is within the same site collection. Second, if you deny access but have management of access requests turned on it gives the user the opportunity to request access. This is done via an email communication to the owner.

To enable or disable this feature (using a Site as the example here) simply do the following  accordingly:
  1. "Site Actions | Site Permissions"
  2. Under "Permission Tools | Edit" you will see a category called Manage.
  3. Click on Manage Access Requests.
  4. Uncheck the "Allow requests for access" option and click OK.
That's it. It is a pretty simple process. With this option you can easily manage those folks who may need access that you were unaware of.