Issues with Content Management Systems and Source Control
When developing a Sitefinity web site, you run into some challenges when it comes to properly storing your work in source control. Out of the box from its project manager, Sitefinity houses its references in the bin directory of the application so that a project build is not required to get it up and running. Being a content management system, a lot of changes occur in the site’s database. When developers want to put their Sitefinity site in source control and wish to collaborate, these sorts of issues can be difficult to deal with. This post offers a way of overcoming some of these difficulties, starting from a brand new Sitefinity site and ending on a Sitefinity site being properly committed.
This post will be using Git as the source control system, but these methods can of course be applied to any source control system you’re comfortable with.
Starting Fresh
We’re beginning with a clean slate. To create a new Sitefinity site, I’ll be using Sitefinity Project Manager. While this post uses version 8.0.5710.0 of Sitefinity, these steps can be applied to almost any version of Sitefinity. The only differences will be DLL references in your project and a few other files here and there.
Here is “My Great Site”. I created it via Sitefinity Project Manager and ran through the setup process (specifying a license file, initial database setup, etc.) and now have a brand new functional Sitefinity site.
Initial Source Control Directory and Solution
You can create a Git repository anywhere on disk, including where the project manager created the site, but I’m going to move the files to another directory instead. Not only do I have a dedicated place for source control, but doing this also gives me assurance that I have no hidden dependencies on Sitefinity Project Manager.
Note that I put the Sitefinity web project and all its files one directory deeper, into a folder called Web. Our source control solution will have other materials and we don’t want them living in the same folder as the web site, so we want to make room.
There are a few more things I like to do before making an initial commit. I want to make sure that a buildable solution for the web site is created and that no build artifacts (bin/obj files et al) are included in source control. We’ll start off by creating a solution file for the web site by opening SitefinityWebApp.csproj in Visual Studio.
Visual Studio 2013 will run an upgrade against the csproj file and generate a Migration Report. The warnings generated can be safely ignored, as they’re only saying that a few non-functional changes were made in order to make the project compatible, as well as 100+ messages indicating that the project’s files were backed up successfully. Delete the Backup folder created in /Web/. It’s a redundant set of files that we don’t need.
I recommend naming the solution file something other than the default (SitefinityWebApp.sln) as shown in the above screenshot, to distinguish it from other Sitefinity projects.
Ignoring Files That Do Not Belong In Source Control
In addition to the usual build artifact directories, we also don’t want to be including files that Sitefinity generates when it runs. This includes any log files, search index artifacts, and other temporary items. To accomplish this, since we’re using Git, we’re going to create a .gitignore file and place it at the root of our solution. You can start with the default C# .gitignore file that GitHub generates for you when creating a new repository, but I find it a bit too chubby for a new project and prefer to only add what’s needed.
My initial .gitignore file contains the following entries:
# User-specific files *.suo *.user *.sln.docstates # Build results [Bb]in/ [Oo]bj/ # Sitefinity-specific folders */App_Data/Sitefinity/Logs/ */App_Data/Sitefinity/Search/ */App_Data/Sitefinity/Temp/
These include files generated for a particular user’s dev environment, the standard build artifact directories, and Sitefinity-specific directories that we don’t want to have in source control. I was explicit about particular folders within App_Data because there are other App_Data files (most notably those in /App_Data/Sitefinity/Configuration) that I do want tracked.
Making the Initial Commit
We’re now ready for our first commit. You can create a new Git repository either via the command line or via SourceTree. In SourceTree I selected “Clone / New” and selected the “Create new Repository” tab.
The first item we’ll want to commit is our .gitignore file. In SourceTree you’ll see a ton of files marked as Unstaged and Untracked, but .gitignore is on the top. Commit the .gitignore file. You can scroll through the file list if you wish to verify that the .gitignore file is already filtering out unwanted files.
After the first commit is successful, go ahead and commit the rest of the uncommitted files as well. We’re ignoring files we don’t want committed already, and the rest are at their final destination.
Moving Sitefinity References to Libs Directory
Keeping track of Sitefinity references is very important in source control. You don’t want to push a Sitefinity site in source control only to be unable to build and run it on another machine. The bin directory, while okay for getting a site up and running from Sitefinity Project Manager, is not the place to keep mandatory references for your project. We’ll extract Sitefinity references from the bin, and move them to their own directory, then update the web project to reference these files instead of the bin. Once done we should be able to Clean and Rebuild the solution with no errors.
Copying the bin files
Open up the bin directory (/Web/bin/ in this example), and copy every file in there. In the root folder of the solution, create the folder path Libs/Sitefinity/8.0.5710.0, then paste the copied bin files into this directory. We create the Sitefinity folder inside Libs in case we have other non-Sitefinity libraries to add to the project later, and we further create a directory for the specific version of Sitefinity we’re using both for a handy reference of what Sitefinity version we’re on, as well as making the Sitefinity upgrade process a little less painful down the road.
Once the copy step is complete, you may delete the “bin” and “obj” directories inside Web/, and check SourceTree to verify that no unwanted files snuck in to source control (they’d be flagged as Deleted by SourceTree if they were). This is a quick and easy way to verify that we aren’t committing files we don’t want to be.
If you have the solution open in Visual Studio still, you will of course notice that the project’s references will nearly all be missing at this point. We need to edit SitefinityWebApp.csproj so that it’s referencing the new location.
- Close Visual Studio (if still open)
- Open Web/SitefinityWebApp.csproj in a text editor (for this post I’m using Notepad++)
- Do a search for “HintPath” to find the first instance of a bin reference. I do this to verify that my Find and Replace strings are correct.
- Do a Find and Replace: Find “<HintPath>bin\” and Replace with “<HintPath>..\Libs\Sitefinity\8.0.5710.0\”
- For Sitefinity 8.0.5710.0, 145 occurrences were replaced.
- Save changes and close
Once the changes are made, you can re-open the solution in Visual Studio. Expand the SitefinityWebApp project’s references and verify that no references have the little yellow warning triangle indicating that a reference is missing. Once verified, perform a Build (or a Clean and Rebuild, since we now have that power).
We’re not entirely done yet though. The Sitefinity project does not always reference every file that is originally in the bin directory. As such, when the site is run, you may get a Yellow Screen of Death saying that a certain DLL could not be found. Work through those errors, adding references to the project as needed. If a reference already exists, verify that “Copy Local” is set to true for that particular reference. Verify that you can access both the frontend and backend of your Sitefinity site. In this instance I ran into no Yellow Screens of Death, but I have in the past. It’s an easy fix, but one to be cognizant of.
Checkpoint
Taking advantage of source control is of course the main reason we’re doing this. Once we’ve built the solution and run it successfully, resolving any potential reference issues, commit. This commit will contain all the Lib references, so it’ll be a hefty one. If you’re not using a DVCS and checking in with something that requires an Internet connection (e.g. TFS), this commit could last a few moments depending on your Internet speed.
Make sure that SourceTree is not globally ignoring DLL files when you commit. When installing SourceTree initially, it asks if you want to create a global ignore. If you do, than DLL files will get ignored on commit. If this is the case, than your Libs commit will only contain the XML files from the references. If you run into this, remove your global gitignore file, or force add the files to your commit via the command “git add -f Libs/Sitefinity/8.0.5710.0/*.dll” in the Git command line.
Include App_Data Files in your Project
For some reason, Sitefinity does not include its App_Data configuration files in the SitefinityWebApp project by default. This can bite you if you’re leveraging Visual Studio’s Publish capabilities to deploy your site, as the mandatory files won’t be included in the published result. Add all the files located in Web/App_Data/Sitefinity/Configuration/ to the porject (using “Show All Files” in Visual Studio to reveal the hidden directory). While here, also include your Sitefinity license file in the solution, so that it similarly does not get missed when publishing. Save all changes and commit.
As you develop and use your Sitefinity site, you may find new configuration files appearing within the Configuration directory every now and then. It’s best to occasionally check this directory inside Visual Studio (leaving “Show All Files” enabled makes this easy) to verify that you have all config files included in the project.
Commit Database Backup
One of the goals of source control is to be able to work on a project without having to acquire needed materials from any other source. Checkout the solution, build and restore, and start being productive. With that in mind, we’re going to add a backup of our empty site’s database to source control, so that developers (or yourself, if on multiple machines) can get up and running instantly. While this initial database backup will only be a few megabytes in size, it’s best to get into the habit of compressing the database backup file before committing, as database backups compress really well. I personally recommend 7zip for this, but any sort of compression will net some benefit at least. In this instance my 11 MB database was compressed down to 545 KB. That ratio is very important when your database swells to a much larger size!
At the project root directory, create a “Backups” folder, and place your backup in there. Then commit the change to source control.
Success
We’re done! We have successfully placed a Sitefinity site, and all dependencies and files, into source control. We’ve pruned out unnecessary files and directories, included a working database backup, and are now ready to push to a remote repository and checkout elsewhere.
Using the Created Repository as a Template for Future Sites
The greatest advantage of having this particular repository available is that when we need to create another Sitefinity site in the same version, we can merely clone this repository, copy the files to a different source control folder, and start development immediately! The only catch is that you have to have Sitefinity recreate the database for you, so that you don’t end up with a web site with the same name, etc. You can invoke this by simply deleting the files in App_Data/Sitefinity/Configuration. On run, Sitefinity will recreate them and run you through the first-time setup process again. Going forward you can now use your original site as a template for any future Sitefinity development you do.
The post Storing Sitefinity Sites In Source Control appeared first on Falafel Software Blog.