MVC Shared layout between projects - asp.net-mvc

I was wondering if there is a way to share the _layout.cshtml file across all projects. This way if I ever wanted to make a change to our companies page layout I only have to change it in one place. From the research I've seen so far people have made mention of possibly creating a .dll file. Also I'm not talking about areas in mvc. What I want is for all my separate applications to reference one shared layout page instead of each application having it's own layout.

Once pattern (which I've been involved in the implementation of) is to make a Nuget package containing the layout file (and anything else you want to share in common between all your sites, such as other CSS files, error handling routines, etc), and installing the package (from a private feed) into each project which requires it, thus overwriting the default layout file).
The source of the Nuget package is itself a C# MVC project with a custom nuget config which makes sure that it includes just the necessary content from the C# project into the distributable nuget file.
Apart from ease of installation and separation of concerns, another big advantage of distributing via Nuget is that if you make changes to the source files and update the package, each application which has the package installed can choose when would be a good time to update to the latest version (if at all), so you don't have issues where if you change one thing you have to change everything which depends on it all at the same time (For instance, the Add as Link option in Slappywag's answer would suffer from that problem - if you changed the layout file in that scenario it would immediately propagate to all the projects which use it, so if you wanted to make any other changes in that project you'd have to deal with any implications of the layout change before you could publish your other changes, which might not be desirable/convenient at the time.)

The way I've achieved this in the past is to use 'add as link'.
Firstly, add your layout files to a new library which can be shared between your different projects. Then in each of your projects which you want to use the layout page add the layout page as a link:
In solution explorer right click on the folder in whcih you want to place your layout file.
Click add existing, and select the layout file you want to use.
Click the little arrow on the right hand side of the 'Add' button, and select 'Add as link' from the dropdown. Your layout file will now be in place.
Depending on how your project is set up you may need to follow the steps in this answer to ensure your linked files are copied at build time. You may also want to make sure the copied files are being ignored by your source control.
Update your ViewStart to use the new layout file.
Any changes you need to make to the layout can be made to the original file, and on build changes will be picked up by your projects.

Related

Add as link intellisense for Views

I'm trying to share some views across projects by using the "Add as Link" feature in VS2015 but the linked view appears broken in VS even though it works fine on the site.
Is there a way to get features like intellisense and "go to definition" working for a linked View?
I can reproduce this with a new solution/project:
Move Home/Index.cshtml to some other folder (currently I'm using a Solution Folder but it doesn't seem to matter where I move the files)
delete Index.cshtml from Home/
from Home/ right click and "add existing item"
choose Index.cshtml from the Solution Folder but choose "Add as Link" from the button drop down
on the linked Index.cshtml choose properties "Copy to Output Directory = Copy Always"
The site will work fine but in VS2015 the view then appears broken and no intellisense works.
This would be a great way to share a view across multiple projects but if VS thinks the view is broken it makes developing a pain.
Any suggestions? Is there a better way to share views across projects?
Here's the painful way I got it to work:
Unload the solution
Create a copy of one of the projects containing the views I want to replicate. Let's call the new project [SharedItems].
Rename the .csproj file and edit the .csproj file manually and replace the old name with the new name (probably optional, but made things easier)
Load the solution and add the new project.
Delete any files you don't need.
Rename the namespaces in the new project.
Build just to make sure it's working and Intellisense is working correctly.
Delete the files you intend to link in the original projects and create links.
Installed the MSBuild.WebApplication.CopyContentLinkedFiles NuGet package on all the original projects to automatically make physical copies of the linked files.
Now I can do all my edits in the templated project without having to maintain multiple copies everywhere.
Two big downsides:
I have to build after making edits to any linked object before I can see the changes.
I have to open the actual .cshtml files in the [SharedItems] project only. Opening a linked file breaks Intellisense until you close it and open it directly. This is especially annoying with Resharper's Search Everywhere feature because it suggests linked files.

How do I add a source controlled (tfs) project to a solution and maintain binding?

I would like to create three separate ASP.NET MVC solutions, all pointing to the same Model project. How do I keep changes made from one solution update the others?
Ex, is there is way in Visual Studio to "Add new project from Source Control" like you can with a whole solution?
So you are hoping to have 3 solutions that share a common project.
You can achieve this in 2 ways.
NuGet
Have the project in it's own solution and create a NuGet package of the output, your other solutions can then consume the NuGet Package.
Shared Project
A shared project is easy to do, just ensure that your shared project is available in the same workspace as your solutions.Do a get latest, You can then just right click on the solution and choose add existing project.
Any changes you make will need to be checked back into source control, these changes will then appear in each 'copy' of the project in each of the different solutions.
The shared project works fine, but you may have to make some considerations when you come to building the solutions, the main one being that if you only make a change to the shared project would you want all of the solutions that consume it to be built on check-in?

How to share company wide settings across multiple team projects in TFS?

This is a problem we have been living with for a while already. Suppose that I have three files:
a FxCop ruleset, containing our basic Code Analysis rules
a Resharper .DotSettings file, with company defined naming conventions, for instance
a StyleCop.Settings file, with some of the default style cop settings disabled
How do I share these kinds of company wide settings files across multiple TFS Team Projects?
At the moment, we have these replicated in a Resources folder in each project, but this is quite a maintenance nightmare, since when we decide to update a few rules on any of these files, we have to update them in a lot of different places.
One approach I've seen is to create a team project specifically to store these files on TFS, for instance $/Core, and by some means share the files this way, either using workspace mappings or branching the project into the other projects.
I don't like this primarily because it requires manual intervention and hardcoded paths. Ideally, I'd like an approach that was not intrusive, i.e. a developer gets the project from source control and compiles without any problems. No need for separate mappings into specific forlders, setting environment variables, anything like that.
At the same time, I'd like to keep the history on these files, so it would be nice if they could still be source controlled. Since they are central to the company, it would be ideal to have limited permissions on them, and that each change was documented appropriately (changesets provide that).
Another approach that crossed my mind was to share these settings via company internal nuget packages. Say for instance that I do have this $/Core project, but instead of using workspace mapping or branching it inside the other projects, I publish a nuget package (or more than one even) containing the configuration files, and add these packages to each project that needs it. I can then use relative paths to the package folder when referencing them, and it would require no manual intervention on the developers part.
Although using nuget would probably work fine, this solution seems weird to me, since nuget packages are meant to be project specific, but this would be "whole team project" specific instead. Again, using this approach, I'd probably have to add the package to one of the projects inside one of the solutions inside each team project. This is actually quite similar to how test adapters are shared now. For instance, NUnit already support this approach. I feel I'd have to do something very similar to that if I went with an internal nuget package: each solution would have to load the package at least once.
Is there some other way to share these kinds of things across the whole company, while still maintaining them on source control? What if I loosened this constraint, and accepted that they don't need to be source controlled? Would it open up other options to share them?
If you go down the NuGet route, you could create Packages for your FXCOP and Resharper files, and then store them in a local feed.
For Stylecop you could use the existing NuGet Package for StyleCop.MSBuild and then repackage it with your own settings file.

How to organize CSS,JS and other files into ASP MVC 4

I am totally new to ASP.NET MVC 4 as I was developing into PHP (Laravel) and the way to organize things is usually something like a "public" folder which would then be separated into css, img, js, lib, and so on.... which is the way I prefer to organize my files...Trying to follow this into ASP MVC 4, and I found and read this question that is similar to what I want achieve. organizing custom javascripts in asp.net mvc 4I did it the way they said and added my custom JS files and added them in the Bundle, it compile and also run fine but the problem I have is that inside the Solution Explorer all the files that I moved are showing with an exclamation mark and also my newly created folders (directly in file explorer, not doing it through VS) are not showing by default, they are for some reason hidden, which I can see with Show All Files. I made sure that they exist inside the Bundle but then my Solution Explorer does not get refreshed. I am trying to make a structure that looks the following:
Contents
img
ui-icons.png
css
bootstrap
bootstrap.css
bootstrap.min.css
Scripts
lib
bootstrap
bootstrap.min.js
bootstrap.js
jquery
jquery.js
jquery.min.js
jquery.ui.js
jquery.ui.min.js
modernizr
modernizr.js
custom
mycustom.js
mycustom2.js
I am not crazy about dumping everything inside the same folders (Content & Scripts), including my custom files in between some official libraries. I know using directly the File Explorer is probably not the best way to go, but then what would be the official way of configuring these... and actually does my structure make sense into ASP MVC4?
EDITMy question is more related to why after creating and moving the files like jquery and others into a Scripts/lib folder, my Solution Explorer is still showin these files under Scripts but with an exclamation marks as saying file not found (of course since I moved them). Why it doesn't reflect exactly what I see in File Explorer? Apart from editing the Bundles is there anything else I'm suppose to do so that my Solution Explorer is up to date with reality??? and why are my created folders not showing in Solution Explorer, why do I have to click on Show All Files to see them? The commmand Create New Folder is not even enable as an available command, that's why I have done these folders directly in File Explorer...but why?
Frankly, you can organize your MVC project however you see fit. If there's anything close to an "official" way to organize your web files, it would be how the default Visual Studio MVC4 template organizes them:
Content (CSS files and related image files)
Images (general image files)
Scripts (JavaScript files)
If you're more familiar with another sort of organization or are part of a team that would prefer another organization, then go for it. (Though in that team scenario, make sure all the team members follow the same organization rules!).
Edit:
To alter the folder structure that the MVC template provides using the Solution Explorer, right-click on the folder in which you want to add a subfolder (this includes the project name, for project-level folders), and then select Add and then Add Folder from the pop-up menu that appears.
If you want to move around files that are already in your solution to another location within the solution, you should move them around using the Solution Explorer, not Windows Explorer, as you'll otherwise get the behavior you are experiencing, where Visual Studio does not know where you moved them. You can click and drag files around, right-click and copy and paste, etc.
If you need to add pre-existing files to your solution (say, to include a set of custom scripts), you can copy the files to the appropriate project folder using Windows Explorer. Then, in Visual Studio, highlight the project that corresponds to where you moved them, and press the Show All Files button in the Solution Explorer toolbar - this will show the files you copied in Windows Explorer, which otherwise won't be listed in Solution Explorer tab. Lastly, highlight the new files, right-click, and select the Include in Project option from the pop-up menu.
One final pointer: if you need to add a specific JavaScript library to your project, the easiest way to do so would be to use the NuGet package manager, rather than to download and add the files in Windows Explorer. This option is found in Visual Studio in the Tools menu, under Library Project Manager --> Manage NuGet Packages for Solution. Not all JavaScript libraries will be available this way, but the most popular ones are.

Using WiX to generate an installer for an ASP.Net MVC website

Has anyone used WiX to generate an installer for an ASP.Net MVC website? Do you harvest files from the web project? I can’t find any good examples of this being done. There doesn’t seem to be a documented way to include all the right files, only the right files and put them in the right place.
If you add the website project as a reference in the installer project, and set harvest=True in the properties, then all the website files are captured, but there are issues:
Some files that should not be copied are included, e.g. packages.config, Web.Debug.config There doesn’t seem to be any clear or simple way to exclude them (as per this discussion).
The .website dll file is in the wrong place, in the root rather than the bin folder (as per this discussion)
However if you do not use harvesting, you have a lot of files to reference manually (e.g. Under \Content\ alone I have 58 files in 5 folders. Most of that is jQuery UI) and they change from time to time, and errors and omissions could easily be missed from a WiX file list. So it really should be kept in sync automatically.
I disagree with the idea that the list of files should be specified explicitly in WiX and not generated dynamically (which is what seems to be suggested at the first link, the wording isn't very clear). If I need to remove a file I will remove if from the source control system, there is no need to do the extra work of maintaining two parallel but different catalogues – one set of files in source control, and the same files listed in WiX. there should be one version of the truth. All files in the website's source tree (with certain known exceptions that are not used at runtime e.g. packages.config) should be included in the deployment.
For corporate reasons I don't have much choice about using WiX for this project
In our MVC 3 project we use Paraffin to harvest files for the installer. For example, you can use "-ext " to ignore the files with extension , use "regExExclude " to ignore the file name matching the regular expression, etc.
Paraffin also keeps the proper structure, all your files would be in the correct folder as they appear in your project.
I use a program that I wrote called ISWIX that makes authoring wxs merge modules a simple drag and drop operation like InstallShield. I then consume that merge module in an installer that handles the UI and IIS configuration.
I also have postbuild automation that extracts the content of the MSI and compares it against what the project published. If there is a delta I fail the build and you have to either a) add it to the wxs or b) remove it from the publish.
I find that the file count churn from build to build is minimal and that this system is not difficult to maintain. The upside is everything remains 100% intentionally authored and files don't ever magically add or remove from the installer unless you intended them to. Dynamic installer generation isn't worth the risk and most people who argue that it is don't even know what those risks are.

Resources