When first building SharePoint projects in Visual Studio, it can be confusing to know how to organize your various SharePoint assets. Like many things with SharePoint in particular and software development in general, there’s no “right” solution. However, having built numerous Visual Studio solutions for various clients, I’ve come up with general methodology that I thought I’d share, since virtually every client asks me how they should organize their projects. (I was prompted to write this because I saw a similar question posted in the SharePoint Forums.)
First off, I always name the following assets using an identical “namespace-like” name:
- Visual Studio Solution
- Visual Studio Project
- Assembly name
- Solution Package Name
- Feature Folder name
For example, say my prefix is “BB.SP2010” (for Becky Bertram, SharePoint 2010). I would have a Visual Studio project called BB.SP2010. Inside that solution I might have a Visual Studio project called BB.SP2010.Lists and another project called BB.SP2010.WebParts. In this way, it’s obvious that the two projects are related, because they share the same prefix. Typically, Visual Studio projects pick up their namespace and their assembly name from the name of the project. So, my BB.SP2010.Lists project now also has an assembly name of BB.SP2010.Lists.dll and a namespace of BB.SP2010.Lists. Furthermore, I’ll go ahead and make sure my solution package has a name of BB.SP2010.Lists. Finally, I’ll make sure my Feature folder has the same name. (Keep in mind the name of the Feature is what shows up in the browser, and that can be a little more “user friendly”, such as “Becky Bertram’s Custom Lists”. Also keep in mind that SharePoint automatically tries to append the Visual Studio project name to the front of the Feature folder name. However, this isn’t necessary if we’re using this common naming system, so make sure you customize the folder name to remove that Project name prefix.)
As you can imagine, comparing apples to apples to apples to apples simplifies life. If I see an assembly called BB.SP2010.Lists in my GAC, it’s not hard for me to figure out it probably got there when the solution package called BB.SP2010.Lists was deployed. Along the same lines, if I see a Feature folder on the file system in the “FEATURES” folder, called BB.SP2010.Lists, it’s not hard for me to figure out that the code for the feature is stored in the assembly by the same name.
Another, more minor helpful thing about naming projects in this way, is the fact that if you have mulitple assets (assemblies, Feature folders, solution packages, etc.) deployed to the same location, it’s easier to spot all your custom assets at once because they’ll be listed next to each other alphabetically.
Once your naming conventions are determined, knowing how to organize your content is a different matter. Say you have an event receiver, a custom list definition, a master page, a web part, and a workflow that you want to deploy. How do you structure your Visual Studio solution, projects, and more specifically solution packages and features?
As I said before, there’s no right answer. I always tell my customers, even if you pick an approach that’s not perfect, just be consistent! I’ve generally chosen one of two approaches:
- Creating Visual Studio projects (and therefore solution packages) based on the type of asset I’m creating. In this scenario, I might have one Visual Studio solution with two projects: BB.SP2010.Intranet.Lists, and BB.SP2010.Intranet.WebParts. I often go this route if I’m building a new application from scratch, such as an Intranet site. This way it’s easy to know that if I’m building an event receiver on a list, it goes in the Lists project, and if I’m building a Visual Web Part, it goes in the WebParts project. If I have dependencies in these two I make sure my Features have dependencies specified. (For instance, I shouldn’t be able to add a web part to my site that displays data from a custom list until the Lists feature has been activated so that the custom list is available.)
The important thing to keep in mind with this approach is what happens when a solution package upgrade happens. Files on the file system are replaced with new files from the new solution package. Why is this important?
1. People don’t like the idea of upgrading the code-behind of 10 web parts if they’re only making a small change to one of them. However, if when the solution package is deployed, the code-behind for the other 9 web parts is replaced with replaced with the same code they had before, who cares? There really are no negative repercussions. (provided you don’t give your assembly a new version number.)
2. Sometimes the thing you’re updating only gets updated when a Feature is activated. For instance, the new version of your solution package might execute code in a Feature event receiver when the Feature is activated. What this means is that even though the new code is on the file system, it’s irrelevent until it gets executed by deactivating and reactivating the Feature. This can be good or bad, depending on how you want your code to work. It’s just something you need to keep in mind. However, the key is that just because you put new assets out there by upgrading your solution package, it doesn’t necessarily mean those changes will immediately “take”.
The reason I point these things out is that people sometimes are scared to put a whole bunch of items in a single solution because they don’t want to update a bunch of extraneous stuff just to make one change. I’m just pointing out that “updating” the other items isn’t always a bad thing if you’re just overwriting the assets with identical versions.
- Create Visual Studio projects according to application functionality. This approach works well for discrete pieces of functionality that really can be encapsulated. For instance, I might have a particular application that I want to deploy. That application has a custom list. When users add an item to that list, an event receiver needs to fire that will lock down the list item to allow only that person to view the item and edit it. I need to have three web parts: one to render the contents of the list, one to allow users to edit items in the list, and one to allow users to view an item from that list. I need just one Feature that, when activated, will add the list definition, list instance, three web parts, and event receiver in the site collection. In this kind of scenario, I would create a new project called BB.SP2010.MyCustomApp. In this scneario, I might have multiple Visual Studio projects in the same Visual Studio solution, each “bundled” by application logic. (all having the same prefix, of course.)
The benefit to this approach is that if you have multiple developers, you can tell one developer, “You work on Application A” and tell the other developer “You work on Application B”, and you know they won’t be tripping over one another.
I personally tend to go with the first option. The reason is that I often build Publishing sites for clients, and I’m often the only developer writing code. I might create a site column that’s used in both lists and page layouts. I also probably have web parts that use styles that were defined in a style sheet that got deployed with my publishing features. Because I typically have so many dependencies, it doesn’t work so well for me to use the application-centric model. I would end up having some pretty bizarre dependencies (“Why is my Accounts Payable feature dependent on my Health and Fitness Tracking feature?”) So I don’t have strange dependencies where maybe a workflow in one Feature is dependent on a site column having been provisioned in another Feature, it might makes sense to come up with sort of “base” solution packages that deploy common assets such as site columns, content types, style sheets, etc., that other projects/solution packages/features/assets might use. However, in my mind, once I’ve done that, I figure I’m already down the path of createing “Workflow”, “Columns”, “Publishing” projects, etc., which sounds an awful lot like the first approach I mentioned. For me, that’s why I go with approach number 1.