How do I ensure that Visual Studio copies dependencies of dependencies to the output folder? - asp.net

I am using Visual Studio 2010 to manage a web application. This web application is organised into a number of projects, where the UI itself is one project, and the business logic resides in another assembly which is then set up as a project reference for the UI, and makes calls out to code in third-party libraries.
When I do a deployment build, MSBuild creates the usual _PublishedWebsites folder and copies the web application into there. What it does not do is copy the dependencies of the business layer, which means nasty YSOD when I try to run the application. Now, I can set the third-party libraries as references of the UI project, and that ensures the libraries are copied and deployed as expected - however, that rather misses the point of having the business layer doing all the work, and means additional maintenance in that when another third-party library is added, it needs to be added in more than one place.
How can I ensure, once and for all, that dependencies of my business layer are deployed to the _PublishedWebsites folder when the deployment build is run?

As per my comment to #Shaun Plourde's response, it appears that this scenario is not supported. If you want indirectly-referenced assemblies to appear in the build output, you'll need to reference them directly.

This should just work out of the box with VS.NET. Try setting "Copy local" to true where the dependencies are actually needed. Your UI project should not require any explicit references to those assemblies.
For smaller projects, this may scale fine in terms of compilation performance. For larger projects, you may want to consider alternative approaches such as those outlined in Patrick Smacchia's article at http://www.simple-talk.com/dotnet/.net-framework/partitioning-your-code-base-through-.net-assemblies-and-visual-studio-projects/.

It isn't a perfectly automated solution, but you can solve this with a post-build script on your main project.
I've found that the $(WebProjectOutputDir) variable is managed such that it resolves to the "_PublishedWebsites" directory when you supply an output directory that is not equal to the directory of the project being built. (Otherwise, it is the same as the current project directory.) So, for your problem, you could put this in the post build of your web application:
xcopy /Y /S "$(ProjectDir)..\Your Business Logic Project\bin" "$(WebProjectOutputDir)\bin"
It should work both on your machine and on your build server.

Related

ASP.NET Web application main dll not being copied to Bin on build

I have an ASP.NET (4) Web App solution with 3 projects. Project A references B & C (along witha bunch of other 3rd party DLLS like Crystal Reports etc).
I have 3 build configs, Debug, Test & Release.
If I do a build in any of the configs, the built DLLS (and PDB if it is Debug) are placed as they should in their respective folders.
So Test gets built into {root}\bin\x86\Test
Release into {root}\bin\x86\Release
Debug into {root}\bin\x86\Debug
Also, all the dlls that are referenced have their 'Copy Local' property set to true and so they are copied into the {root}\bin folder so I can run and test locally in VS.
BUT
The main app DLL (ProjectA.dll) is not being copied into the {Root}\bin folder when it is being built/rebuilt, just being left in the folder for the chosen build config as described above. So when I run the app in VS I get an error 'Could not load type 'ProjectA.Global_asax'. Not surprising given the main project DLL is not in the Bin folder where the web server is looking for it.
The only way I can get it to run is to manually copy the ProjectA.dll into the {Root}\bin folder myself which seems a nonsense and obviously fraught with the risk of me forgetting to copy the latest on over after each build.
Surely there must be a way of telling VS to copy the main app dll (ProjectA.dll) as well as all the referenced dlls, into the main {Root}\bin folder?
Obviously, as ProjectA.dll is the main app assembly it is not in the list of references so I cant just set the 'Copy Local' prperty for it. Unless it is hidden away somewhere else? I have trawled every form and dialog in VS (and hours on Google!) and just cant see how to tell VS 'Please copy the main app assembly back into th bin folder when you have finished building'.
Can someone pls help ths is driving me nuts!
Many thanks
Mark
If you just want avoid the manual work of moving the dll after every build, then you can create a Visual Studio post-build event to copy the dll. Some examples here and here.

MSBuild: Web application, build once package and deploy many

I'm sure this question has come up before, but I can't seem to find an elegant solution.
I have a web application project with multiple configurations based on deployment environment (Test, QA, Production) along with web.config transforms for each environment. We are using a web deployment package to automatically create the .zip of the app which can be deployed via MSDeploy. It's easy enough to call the package target multiple times, each with a different configuration:
msbuild MyProject.csproj /t:Package /p:Configuration=QA
msbuild MyProject.csproj /t:Package /p:Configuration=Test
But this triggers a complete rebuild of the web project each time before packaging. I want to build once, then apply the web.config transforms, and create separate packages for each environment. Is there an easy way to accomplish this without forcing a complete rebuild for each environment?
Dupe of Build once and deploy to multiple environments with msdeploy & Visual Studio 2012
I've also been wanting a solution to this, but apparently there isn't any real COMPLETE MS solution that I know of. Visual Studio provides the following (as noted here):
Web.Config transformation
Parameterization
Vishal Joshi concluded with the following:
If you can know your environment settings during build time use
Web.Config transformation.
If you would want to create deployment package only once and then
enter the settings during install time then use Parameters.xml
What I would like to see, though, is have the best of both worlds. I want to "package" up a target having ALL the configuration transformations embedded. Therefore, when the IT guy runs the WebDeploy cmd file (that gets generated when you "package"), they can provide a switch of which environment configuration they want (i.e. Dev, Test, Stage, Prod, Release, etc). I don't believe there is a solution from MS out there that does that. :(

.NET equivalents for ANT and WAR files?

The majority of our internal apps are built on a Java EE stack using Ant, and deployed to Tomcat with a WAR file. We have a build box that creates a Production-targeted WAR, and the WAR is then delivered to the Test environment. A script is run to convert the deployed webapp to point to Test data environments.
After a few cycles of Test -> Bug Fix -> Build -> Redeploy to test, the WAR file is then deployed to Production, and is then live.
I've recently inherited some ASP.NET 4.0 webapps, and their Build/Deploy is quite different; the code is built in VS, and then the entire project directory is copied to each environment. It is then tweaked by hand, and is occasionally rebuilt with a VS instance on the server.
This is a bit scary, as there are plenty of opportunities for tweaks in one environment to be forgotten, and thus require that we're playing around with our apps after they're "live", outside the bounds of testing, version control, etc.
So, all of this being said:
Is there an equivalent to the Ant/WAR mechanism in a .NET world? What's the safest way to create an executable artifact from a .NET webapp and move it between environments with minimal modification? I know that "best pratices" is a taboo phrase, but I'd like to dip into some expert knowledge before I remake Ant in .NET. :-)
Three technologies you need to know about to automate web deployments:
MSBuild - This is Microsoft's equivalent of ANT. Project files are basically just a series of MSBuild tasks.
WebDeploy - This is essentially your WAR/Tomcat equivalent, except that it creates deploy packages, and is meant for IIS.
XML Transforms - You should never have to manually edit configuration by hand. Config transforms are essential if you have multiple environments you need to deploy to.
Put all these together with your favorite Build server (I use Jenkins), and you can totally automate your entire deployment process to any environment. Each of these individual topics is too broad to cover in depth here, but you should be able to get started with minimal knowledge of each.
To give you an example of how simple it can be, here is a sample command line build that will deploy a website to a 2003/IIS6 box.
MSBUILD "MyWebSite.csproj"
/p:Configuration=Dev
/p:OutputPath=bin
/t:Rebuild
/p:DeployOnBuild=true
/p:DeployTarget=MSDeployPublish
/P:AllowUntrustedCertificate=True
/p:MSDeployPublishMethod=RemoteAgent
/p:MsDeployServiceUrl=http://MyDevServer
/p:DeployIisAppPath="Default Web Site/MyWebSite"
/p:username=deployUser
/p:password=deployPassword

Better alternative to Web Deploy Projects

I have a solution with a fair few projects, 3 of them web-based (WCF in IIS / MVC site). When the solution builds, it dumps each of the components of this distributed system in a 'Build' folder. Running the 'configurator' part of the whole output will set up the system in the cloud automatically. It's very neat :) However, the Web Deploy Projects are a major pain. They "build" (i.e. deploy) every, single, time I build - even when no changes have been made to their respective projects.
Changed a single line of code? Look forward to waiting around a minute for the 3 web projects to redeploy.
[These projects are VERY straightforward at the moment - two have a single .svc and one .ashx file - the other is an MVC app with ~5 views]
I realise I can change solution configurations to not 'build' them, but I've been doing that and it's very easy to log on the next day and forget about it, and spend a couple of hours tracking down bugs in distributed systems due to something simply having not been built.
Why I use Web Deploy Projects? Well, because I need all pages + binaries from the web project. The build output for the project itself is the 'bin' folder, so no pages. The entire project folder? It has .cs, .csproj and other files I don't want included.
This will be building on build servers eventually, but it's local at the moment. But I want a quick way of getting the actual output files from the web project to my target folder. Any ideas?
Not sure if this will help in your situation, (plug for own project coming up), but I am working on a project to help ease IIS deployments:
https://github.com/twistedtwig/AutomatedDeployments
The idea being you can use config files for IIS (app Pool, applications and websites) to automate the creation and update of sites locally (dev machines) or remotely (test and production machines).
It is still a work in progress but is ready to be used in production systems.
using the package creation as a post build step might get you closer to what you want, (don't believe it includes all the extra files), but that would still build it each time, (although if code hasn't changed it should not rebuild unless you choose rebuild all projects).
In the end I created a utility/tool which, given a project file, XCOPYies the project folder for the web project to a target location, then looks in said project file and deletes anything that doesn't have Build Action set to Content. Very quick and effective.
I know it is still in RC but VS2012 does have a neat feature when doing publish that it detects the changes and publishes only those. Might be something a little deeper down in the build where it does an automatic publish too.
You can take a look to the Octopus project: http://octopusdeploy.com/
Deployment based on nuget packages.

CCNET - build task required? Multiple repositories, one CCNET source section per project

CCNET questions - Here's the scenario:
I've got 10 developers doing local development to a Sitecore installation w/GIT as version control. When done with their feature/fix they push to an integration repository.
I've got CCNET setup for the Sitecore project that points to the remote Integration rep and the local live qa code base. CCNET finds the commits that my developers have made to integration repository and then updates the qa code base repository.
I also have a couple other .Net class lib projects that are managed by CCNET, compiled with their output pointed to the Sitecore bin dir.
The Sitecore installation is merely a result of a build with no compilable aspects. Its a web product with it's own API as well as the ability to integrate custom dll that we create to customize the product.
Questions:
Is CCNET build task required as a condition to execute other activities such as nUnit or robocopy? (the reason I ask this is because a "build" is natively used to compile an app and generate output, whereas, the only reason why we'd want to build is to make sure all dependencies are there and we can jump to unit testing...).
If my developers are NOT pointing to a centralized rep like integration, how would CCNET know where all of their remote GIT repositories are when the config doc only allows one GIT source control section per project?
Per project when I configure the GIT vc specs it asks for the branch that needs to be statically saved to the doc. Does CCNET have the ability to accept different branches dynamically?
There's no need to have an "actual build" in your project - it could consist of any type of tasks inside the tasks element. I have a couple of projects which only copy the files from the repository to an FTP server after deleting some files which shouldn't be published.
I have no experience with GIT but you have a possibility to define multiple source control blocks of any type if you use the multi source control block.
You could use dynamic parameters which allow the user to set their values when triggering the build.

Resources