Unnecessary files remaining after Publish - asp.net-mvc

When I do a 'Publish' on my ASP.NET MVC website, I'm finding unnecessary empty folders in the publish folder.
This is annoying because I have to manually delete them so they don't get uploaded through FTP.
This happens even when I select the following radio-buttons:
Delete all existing files prior to publish
Copy
Only files needed to run this application
It doesn't copy every folder, only one or two random folders. I have no idea why it chooses to copy just these folders, but not the others. They're not system-folders or anything - I made them myself.
Why is this happening?

It's just the way the publish wizard works. If you want more control over how a web project is deployed you can make a web deployment project if you have developer edition of Visual Studio. (Perhaps professional as well I'm not sure.)
Looks like you might be able to download it too?
http://www.microsoft.com/downloads/details.aspx?FamilyId=0AA30AE8-C73B-4BDD-BB1B-FE697256C459&displaylang=en

The Publish Wizard seems to include empty root-level custom folders if they contain subfolders that also contain code. Example:
--Folder1 -+
+- ParentClass.cs
+- Subfolder2 -+
+- ChildClass1.cs
+- ChildClass2.cs
Will result in an empty "Folder1" showing up in the location you publish to. I think this is an artifact of the "Namespace Provider" property on folders and the <Compile Include="Folder1\Subfolder2\ChildClass1.cs" /> elements of the csproj file.

Related

Customise Build Build Output for Specific Projects

I have a solution which contains a number of 2 windows console projects, 1 website project and 20 class libraries.
I want TFS 2013 to push to the drop folder only the windows console and website projects to the drop folder.
I am looking for a folder structure similar to below.
DropFolder
- App1
- App2
- Website1
How is the best way to configure TFS to allow this?
Thanks
UPDATE
I have ended up using the nuget package http://www.nuget.org/packages/PublishedApplications for all the projects that I want to be published. This copies the projects into a _PublishedApplications folder. So that I have a folder structure like this
DropFolder
_PublishedApplications
- App1
- App2
_PublishedWebsites
- Website1
The default template has Solution Specific Build Outputs property under Process tab Advanced section.
Alternatively you can let MSBuild control your build flow.
Update:
The ultimate solution seems implementing NuGet's
PublishedApplications
I've used PublishedApplications NuGet package as well, but have encountered an issue. If referenced libraries had Content marked as Copy Always all content would be copied to the root folder and not hierarchically. For example if you have following projects and structure (some files omitted for brevity):
PublishLib
test
TextFile1.txt (marked as Content/CopyAlways)
TestPublishTargetApp - references PublishLib
targets
Microsoft.Application.targets
When team build is done this is the content of _PublishedApplications\TestPublishTargetApp folder:
PublishLib.dll
TestPublishTargetApp.exe
TestPublishTargetApp.exe.config
TestPublishTargetApp.pdb
TextFile1.txt
And what I expected was:
test\TextFile1.txt
PublishLib.dll
TestPublishTargetApp.exe
TestPublishTargetApp.exe.config
TestPublishTargetApp.pdb
After fiddling around a bit with Microsoft.Application.targets I was able to get what I wanted by changing last <Copy SourceFiles (original commented out):
<!--<Copy SourceFiles="#(_SourceItemsToCopyToOutputDirectoryAlways)"
DestinationFolder="$(ExeProjectOutputDir)"
SkipUnchangedFiles="false"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"/>-->
<Copy SourceFiles="#(_SourceItemsToCopyToOutputDirectoryAlways)"
DestinationFiles = "#(_SourceItemsToCopyToOutputDirectoryAlways->'$(ExeProjectOutputDir)\%(TargetPath)')"
SkipUnchangedFiles="false"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"/>
I am not sure if this is useful to anyone else, but for me this was essential change, plus PublishedApplications NuGet package was not changed since 2014 (seems like abandoned project).

asp.net mvc publish doesn't overwrite cshtml files

I've been publishing my site regularly without too much trouble. But today I noticed that it won't overwrite existing .cshtml razor files with the new versions. I publish, look at the folder, and see the files are still out of date. If I delete the file and then publish, it will put the new version there. But if the file already exists it won't overwrite it and my production website is out of date. I tried doing the option 'delete files before publishing' but it gives me an access error that it can't delete folders. I tried deleting the entire folder but then I lose my .svn folders and it won't recognize version control.
Is there a way to force the Publish command to overwrite my .cshtml files with the latest version? (note: the dll files get overwritten fine)
Have you set the Copy to Output Directory to Copy Always?
I use Build Action = Content too.
Seems like Read-Only attribute is set on files, so they can't be overwritten. Check VS Output window for signs of errors.
Advice: Try to NOT include generated files (this also means folder with published files) in source control. VCS tools usually tend to lock-up files they work on.
Having .svn files on Test/Prod server is also not a good idea.

How do you share scripts among multiple projects in one solution?

In case the question wasn't clear. I have 3 MVC projects in one Solution. Every time I create a new project it adds the "Scripts" folder with all the .js files I'll ever need. I don't want to have this created every time for every application. Is there a way to reference scripts from a central folder in the solution so all applications/projects can share one common script folder with all the scripts common among them?
Edit:
Please explain the pros and cons of doing this if there are any...now I'm curious.
Here is what I would recommend:
Right click the solution and create a New Solution Folder called Common Javascript Files (or whatever you feel like calling it.
Right click on the Solution, click Open Folder in Windows Explorer,
or navigate there manually for other versions of Visual Studio :(
In the solution directory, create a directory with the same name as the solution folder (solution folders do not normally match directories at the source code level but this will for sanity sake).
In this new directory, add files that need to be shared between solutions.
In Visual Studio, click the solution folder and select Add - Existing Item.
In the file selection dialog, navigate to the directory previous created, select the file(s) added to the directory and click Add.
In each Project that needs a shared file, right click on the project (or directory within the project) and click Add - Existing Item.
Navigate to the shared Directory, Select the files and click the drop down arrow then click Add As Link.
Now the files in the projects are essentially short cuts to the files in the Solution Folder. But they are treated as actual files in the project (this includes .CS or Visual Basic files, they will be compiled as files that actually exist in the project).
PROS
Files are truly shared across projects at Design time
Only the files needed for each project can be added, it's not all or nothing
Does not require any configuration in IIS (virtual directory etc)
If the solution is in TFS Source control, you can add the Directory to the TFS Source and the shared files will be source controlled.
Editing a file by selecting it in the Project, will edit the actual file.
Deleting a Linked file does not delete the file.
This is not limited to JS files, linked files can be ANY file you might need (Images, Css, Xml, CS, CSHTML, etc)
CONS
Each deployment gets it's own file.
There is a small learning curve when understanding that Solution Folders are not Directories that exist in a Solution Directory.
The best thing to do, imo, is to roll your own CDN... Basically just create another site in IIS and give it it's own binding, e.g. "http://cdn.somedomain.com"
Then store all of your css/js/fonts/shared images etc on the CDN site and link to them from your other sites.
Doing so solves 2 problems,
All of your stuff is shared when it needs to be and you only have to manage 1 revision per file.
Your users browsers can cache them in 1 single location instead of downloading copies of your stuff for every site that uses them..
I added this answer because I see a lot of people referrencing creating virtual directories. While that does indeed share the files, it creates multiple download paths for them which is an extreme waste of bandwidth. Why make your users download jquery.js (1 * number of sites) when you can allow them to download it once on (cdn.somedomain.com).
Also when I say waste of bandwidth, I'm not just talking about server bandwidth, I'm talking about mobile users on data plans... As an example, I hit our companies HR site (insuance etc) on my phone the other day and it consumed 25mb right out the gate, downloaded jquery and a bunch of stuff 5 times each... On a 2gb a month data plan, websites that do that really annoy me.
Here it goes, IMO the best and easiest solution, I spent a week trying to find best and easiest way which always had more cons than pros:
Resources(DLL)
Shared
images
image.png
css
shared.css
scripts
jquery.js
MvcApp1
Images
Content
Shared <- We want to get files from above dll here
...
MvcApp2
Images
Content
Shared <- We want to get files from above dll here
...
Add following to MvcApp1 -> Project -> MvcApp1 Properties -> Build events -> post build event:
start xcopy "$(SolutionDir)Resources\Shared\*" "$(SolutionDir)MvcApp1\Shared" /r /s /i /y
Here is explanation on what it does: Including Build action content files directory from referenced assembly at same level as bin directory
Do the same for MvcApp2. Now after every build fresh static files will be copied to your app and you can access files like "~/Shared/css/site.css"
If you want you can adjust the above command to copy scripts from .dll to scripts folder of every app, that way you could move some scripts to .dll without having to change any paths,here is example:
If you want to copy only scripts from Resources/Shared/scripts into MvcApp1/scripts after each build:
start xcopy "$(SolutionDir)Resources\Shared\Scripts\*" "$(SolutionDir)MvcApp1\Scripts" /r /s /i /y
This is a late answer but Microsoft has added a project type called Shared Project starting Visual Studio 2013 Update 2 that can do exactly what you wan't without having to link files.
The shared project reference shows up under the References node in the
Solution Explorer, but the code and assets in the shared project are
treated as if they were files linked into the main project.
"In previous versions of Visual Studio, you could share source code between projects by Add -> Existing Item and then choosing to Link. But this was kind of clunky and each separate source file had to be selected individually. With the move to supporting multiple disparate platforms (iOS, Android, etc), they decided to make it easier to share source between projects by adding the concept of Shared Projects."
https://blogs.msdn.microsoft.com/somasegar/2014/04/02/visual-studio-2013-update-2-rc-windows-phone-8-1-tools-shared-projects-and-universal-windows-apps/
Info from this thread:
What is the difference between a Shared Project and a Class Library in Visual Studio 2015?
https://stackoverflow.com/a/30638495/3850405
A suggestion that will allow you to debug your scripts without re-compiling the project:
Pick one "master" project (which you will use for debugging) and add the physical files to it
Use "Add As Link" feature as described in Eric's answer to add the script files to the other projects in solution
Use CopyLinkedContentFiles task on Build, as suggested in Mac's comment to copy the files over to the second over to your additional projects
This way you can modify the scripts in the "master" project without restarting the debugger, which to me makes the world of difference.
In IIS create a virtual folder pointing to the same scripts folder for each of the 3 applications. Then you'll only need to keep them in a single application. There are other alternatives, but it really depends on how your applications are structured.
Edit
A scarier idea is to use Areas. In a common area have a scripts directory with the scripts set to be compiled. Then serve them up yourself by getting them out of the dll. This might be a good idea if you foresee the common Area having more functionality later.
Most of the files that are included by default are also available via various CDN's.
If you're not adding your own custom scripts, you may not even need a scripts directory.
Microsoft's CDN for scripts: http://www.asp.net/ajaxlibrary/cdn.ashx

.Net Build does not contain output folders from other projects

We had a Project in our solution called DatabaseCreation - which was responsible for creating the database and running the scripts (contained in directories within the project).
Everything was fine.
We then wanted to make the creation of this database to be available from an app and from a console, so re-factored so that we had ...
DatabaseCreation.Core
DatabaseCreation.App
DatabaseCreation.Console
Core has the directories containing scripts, and the App and Console run them.
When built with Visual Studio the directories containing the scripts are copied to the Output bin directory (either App or Console) but problem is: when the build server runs, the script directories don't get copied to the bin folder.
We've tried with TFS and Team City. I realise I could just copy them over, but its frustrating that it works when building in Visual Studio!
Can anyone put me on the right track please?
Check the Build Type for the files in the scripts directory. Find that by clicking one or many files (ctrl+click) then hitting properties (often f4). You likely want them to be content with Copy Always or Copy if newer.
The files were set to copy always, but the build just wouldn't pick them up.
The slightly awkward work around was to add the files as links from one project to another.
Add Existing -> navigate to other project - Looking for the little arrow on the right of the add button -> press that, Add as link option appears.

How to ignore files/directories in TFS for avoiding them to go to central source repository?

Is it possible to set up files/folders to ignore on a per-project basis in TFS source control?
For example, I've a website with an assets folder that I do not want to go in to source control. These assets are maintained by a separate system. Also, I don't want to put several gigabytes of assets into source control, but I need a couple of samples on my dev machine, but I don't want to check those in either.
If I'm working on this website while bound to source control and I refresh the tree, these files will automatically get added again
I want to prevent this from happening.
If you're using local workspaces (TFS 2012+) you can now use the .tfignore file to exclude local folders and files from being checked in.
If you add that file to source control you can ensure others on your team share the same exclusion settings.
Full details on MSDN - http://msdn.microsoft.com/en-us/library/ms245454.aspx#tfignore
For the lazy:
You can configure which kinds of files are ignored by placing a text
file called .tfignore in the folder where you want rules to apply. The
effects of the .tfignore file are recursive. However, you can create
.tfignore files in sub-folders to override the effects of a .tfignore
file in a parent folder.
The following rules apply to a .tfignore file:
# begins a comment line
The * and ? wildcards are supported.
A filespec is recursive unless prefixed by the \ character.
! negates a filespec (files that match the pattern are not ignored)
Example file:
# Ignore .cpp files in the ProjA sub-folder and all its subfolders
ProjA\*.cpp
#
# Ignore .txt files in this folder
\*.txt
#
# Ignore .xml files in this folder and all its sub-folders
*.xml
#
# Ignore all files in the Temp sub-folder
\Temp
#
# Do not ignore .dll files in this folder nor in any of its sub-folders
!*.dll
For VS2015 and VS2017
Works with TFS (on-prem) or VSO (Visual Studio Online - the Azure-hosted offering)
The NuGet documentation provides instructions on how to accomplish this and I just followed them successfully for Visual Studio 2015 & Visual Studio 2017 against VSTS (Azure-hosted TFS). Everything is fully updated as of Nov 2016 Aug 2018.
I recommend you follow NuGet's instructions but just to recap what I did:
Make sure your packages folder is not committed to TFS. If it is, get it out of there.
Everything else we create below goes into the same folder that your .sln file exists in unless otherwise specified (NuGet's instructions aren't completely clear on this).
Create a .nuget folder. You can use Windows Explorer to name it .nuget. for it to successfully save as .nuget (it automatically removes the last period) but directly trying to name it .nuget may not work (you may get an error or it may change the name, depending on your version of Windows).
Or name the directory nuget, and open the parent directory in command line prompt. type. ren nuget .nuget
Inside of that folder, create a NuGet.config file and add the following contents and save it:
NuGet.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<solution>
<add key="disableSourceControlIntegration" value="true" />
</solution>
</configuration>
Go back in your .sln's folder and create a new text file and name it .tfignore (if using Windows Explorer, use the same trick as above and name it .tfignore.)
Put the following content into that file:
.tfignore:
# Ignore the NuGet packages folder in the root of the repository.
# If needed, prefix 'packages' with additional folder names if it's
# not in the same folder as .tfignore.
packages
# include package target files which may be required for msbuild,
# again prefixing the folder name as needed.
!packages/*.targets
Save all of this, commit it to TFS, then close & re-open Visual Studio and the Team Explorer should no longer identify the packages folder as a pending check-in.
Copy/pasted via Windows Explorer the .tfignore file and .nuget folder to all of my various solutions and committed them and I no longer have the packages folder trying to sneak into my source control repo!
Further Customization
While not mine, I have found this .tfignore template by sirkirby to be handy. The example in my answer covers the Nuget packages folder but this template includes some other things as well as provides additional examples that can be useful if you wish to customize this further.
It does seem a little cumbersome to ignore files (and folders) in Team Foundation Server. I've found a couple ways to do this (using TFS / Team Explorer / Visual Studio 2008). These methods work with the web site ASP project type, too.
One way is to add a new or existing item to a project (e.g. right click on project, Add Existing Item or drag and drop from Windows explorer into the solution explorer), let TFS process the file(s) or folder, then undo pending changes on the item(s). TFS will unmark them as having a pending add change, and the files will sit quietly in the project and stay out of TFS.
Another way is with the Add Items to Folder command of Source Control Explorer. This launches a small wizard, and on one of the steps you can select items to exclude (although, I think you have to add at least one item to TFS with this method for the wizard to let you continue).
You can even add a forbidden patterns check-in policy (under Team -> Team Project Settings -> Source Control... -> Check-in Policy) to disallow other people on the team from mistakenly checking in certain assets.
For TFS 2013:
Start in VisualStudio-Team Explorer, in the PendingChanges Dialog undo the Changes whith the state [add], which should be ignored.
Visual Studio will detect the Add(s) again. Click On "Detected: x add(s)"-in Excluded Changes
In the opened "Promote Cadidate Changes"-Dialog You can easy exclude Files and Folders with the Contextmenu. Options are:
Ignore this item
Ignore by extension
Ignore by file name
Ignore by ffolder (yes ffolder, TFS 2013 Update 4/Visual Studio 2013 Premium Update 4)
Don't forget to Check In the changed .tfignore-File.
For VS 2015/2017:
The same procedure:
In the "Excluded Changes Tab" in TeamExplorer\Pending Changes
click on Detected: xxx add(s)
The "Promote Candidate Changes" Dialog opens, and on the entries you can Right-Click for the Contextmenu. Typo is fixed now :-)
I found the perfect way to Ignore files in TFS like SVN does.
First of all, select the file that you want to ignore (e.g. the Web.config).
Now go to the menu tab and select:
File Source control > Advanced > Exclude web.config from source control
... and boom; your file is permanently excluded from source control.
I'm going to assume you are using Web Site Projects. These automatically crawl their project directory and throw everything into source control. There's no way to stop them.
However, don't despair. Web Application Projects don't exhibit this strange and rather unexpected (imho: moronic) behavior. WAP is an addon on for VS2005 and comes direct with VS2008.
As an alternative to changing your projects to WAP, you might consider moving the Assets folder out of Source control and into a TFS Document Library. Only do this IF the project itself doesn't directly use the assets files.

Resources