Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

One of the things I really hate about 2010 and the packaging solution that comes out-of-the box is that it encourages bad practices (plopping everything - web code, static artifacts, packaging) into one project.

There are lots of issues with this, but the most egregious issue -- in my opinion -- is that it forces the creation of artifacts in a hierarchy that needs to map to the SharePoint deployment targets instead of making sense in the logical structure of the application and code. I find that this decreases navigability and if some code is separated out into other libraries, just makes things that much harder to find and find a home for.

With 2007 and even with 2010, when using WSPBuilder, I've followed the standard project layout pattern of having at least three projects:

  1. Package - The package project that encapsulates the deployment artifacts and the deployment artifacts ONLY
  2. Web - The UI project that contains the static web artifacts, the ASPX pages, the ASMX endpoints, the WCF endpoints, etc. - has no direct reference to SharePoint
  3. Core - A class library project with the core business logic - encapsulates the direct reference to SharePoint. Feature receivers, event receivers, base classes, domain model classes, data mapping classes, helper classes, etc. go here.

With WSPBuilder, it was easy to separate the artifacts by simply using XCOPY on pre- or post-build to move artifacts from the Web project to the Package project before calling the WSPBuilder executable. WSPBuilder didn't care if the .aspx or .js or .css file was part of the VS solution tree; it would include it in the package if it was in the directory on the file system.

This allowed me to separate web code from the SharePoint code and build a nice boundary to prevent "leakage" of SharePoint API calls to the web artifacts (as well as logically organize the web code into a hierarchy that made more sense). In other words, it forced everything on the front-end in Web to call through a domain model in Core. The Web project becomes a "pure" ASP.NET web application that has no knowledge of SharePoint. I can have strong ASP.NET developers work on the front-end and strong SharePoint developers work on the domain model without giving the ASP.NET guys a chance to "cheat" and write "dirty" code in the codebehind since they have no reference to SharePoint.

I've been trying to figure out how exactly this type of separation can be duplicated with the OOB packaging with Visual Studio 2010.

The core problem with VS2010 is that the contents of mapped folders (i.e. Layouts) don't get included in the manifest and package if they are not included in the project in the VS solution. In other words, if I just XCOPY the files from the Web project to the Package project, they don't get added to the package because -- even though they are in the file system -- they are not part of the solution.

One workaround is to manually create "stubs" for the files (same name) in mapped Layouts directory so that when the XCOPY occurs, it's copying the latest file and replacing the placeholder in the package. But this seems a pain in the butt, redundant, and easy for developers to forget when adding new files.

But I'm curious how other shops out there are handling this issue. I feel strongly that for any non-prototype code, this type of separation becomes a must to ensure maintainability and approachability of the code for new developers. Are there workarounds to short-circuit the OOB packaging quirks that can be automated and remove manual steps like creating a stub .aspx? Are there alternative patterns for separating logic out of the package?

share|improve this question
    
I need to check: Do you still deploy things like filesystem elements and assemblies with WSPs in your separated model, yes? –  James Love Oct 11 '11 at 20:51
    
Yes. With WSPBuilder, again using XCOPY on pre- or post-build, I just copy the dependent binaries to the /GAC directory of the Package project and WSPBuilder handles generation of the manifest. Same with .aspx, .css, .js, and other artifacts -- these just get xcopied to /14/TEMPLATE/{TARGET_PATH} in the solution tree. But I'm not necessarily looking for the same exact workflow -- just some practical, automated way of allowing for the same type of separation and be able to keep web artifacts like .aspx files in a web project and not the package until it's time to build the package. –  Charles Chen Oct 11 '11 at 21:04
    
I'm now thinking that I can use the BeforeLayout MSBuild target to perform custom file layout before packaging. Challenge is that the documentation on how to do this is severely lacking (non-existent?). MSDN only gives some fairly generic references: msdn.microsoft.com/en-us/library/ee231560.aspx, msdn.microsoft.com/en-us/library/ee231572.aspx and there's not much on the Internet on this topic (or my Googlefu is weak....). Will keep this thread posted. –  Charles Chen Oct 12 '11 at 15:43
    
The BeforeLayout target is not enough as it does the copy fine and the file ends up in the package, but the file is not added to the manifest. As far I can tell, the manifest is not generated as a part of the msbuild process so there is no way to control how it's generated aside from the basic manifest merge as it doesn't seem like new files are picked up automatically and added to the manifest dynamically. Wondering if there are more sophisticated ways to manipulate the manifest now. –  Charles Chen Oct 12 '11 at 18:00
    
Blog all this somewhere when you get results, there'll be plenty of people who'll benefit from your findings, I guarantee it. –  James Love Oct 12 '11 at 18:02

2 Answers 2

up vote 1 down vote accepted

Found the magic sauce :)

Assume that we have three projects:

  1. Awe.Some.Product.Core - Class library; the core library of the product
  2. Awe.Some.Product.Web - ASP.NET web application; contains the .aspx, .ascx, .js, .css files, etc.
  3. Awe.Some.Product.Pkg - SharePoint package files used mostly for the build process; should contain no .cs files, no .aspx, .ascx, .js, .css files, etc.

The build process must copy the files from the Web to Pkg so that it is included in the .wsp output file. This allows development of the web artifacts in the Web project only and leaves no code artifacts in the Pkg project.

I do this via standard XCOPY in a pre-build event on the project.

Once the copy is set up, the next step is to edit the .csproj file to customize the file inclusion criteria.

By default, you'll see something like this:

<ItemGroup>
  <Content Include="Layouts\Awe.Some.Product.Pkg\Pages\SomePage.aspx" />
</ItemGroup>

If you add the file directly to the Pkg project.

We simply modify this to have:

<ItemGroup>
  <Content Include="Layouts\Awe.Some.Product.Pkg\Pages\*.*" />
</ItemGroup>  

Now any files that get copied into the directory on pre-build will be automatically included in the manifest and the package when the package is built. Repeat for script files, image files, CSS files, JS files, and so on.

The tip came from another question: http://stackoverflow.com/questions/2551107/is-there-a-way-to-automatically-include-content-files-into-asp-net-project-file

So long as you don't modify the Layouts\Awe.Some.Product.Pkg\Pages\ directory from VS (by adding a file in VS, for example), this method will work.

The one other downside is that those files end up being included in the project in VS in both projects, but at least it's automated and there's no initial manual step of adding it to the second project Pkg.

Perhaps there are better solutions? It would be nice if the team responsible for the SharePoint VS dev tools made the directories "virtual" so that they can be mapped to directories in other projects or could pull content from other directories.

share|improve this answer

Why don't you include in Package project the mapped folders from the other projects? They are also available in package designer.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.