2

I have several MVC projects in one solution.

Following this accepted answer: "Add as Link" for folders in Visual Studio projects, I am attempting to reuse .cshtml views across these proejcts by placing reusable views in a base project. So far, I have set up location formats in the "consuming" projects for the view-engine like this:

var locationFormats = new string[]
{
    "~/Views/{1}/{0}.cshtml",
    "~/Views/Shared/{0}.cshtml",
    "~/Views/Common/{1}/{0}.cshtml",
    "~/Views/Common/Shared/{0}.cshtml"
};

I have set up a recursive, linked directory in consuming projects' .csproj files to include common views like this:

<ItemGroup>
    <Content Include="..\..\..\common.cms\CommonViews\**\*.*">
        <Link>\Views\Common\%(RecursiveDir)%(FileName)%(Extension)</Link>
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
</ItemGroup>

...and all the views are appearing in the consuming projects with the linked-file/cshtml(@) icon, so the paths are correct. For example, the following file is very clearly present in my test consuming project:

\Views\Common\Home\Index.cshtml

But when I run the project, I'm getting:

The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Index.cshtml
~/Views/Shared/Index.cshtml
~/Views/Common/Home/Index.cshtml
~/Views/Common/Shared/Index.cshtml

Question
So I am wondering: is it even possible to link views in this way? What is missing, or what could be inhibiting this from working?

More generally, what about any non-compiled files I'd like to share? Is this technique never going to work?

Community
  • 1
  • 1
Faust
  • 13,751
  • 9
  • 48
  • 107

1 Answers1

1

I've found that this as a known bug in visual studio: Linked files in Web Application projects are not deployed properly. This goes back to VS-2008 but still affects VS-2010 and 2012 (not sure about 2013).

A workaround is detailed in this blog-post: Using Linked Files with Web Application Projects.

If you just want the fix wihtout the explanation, you just need to paste the code below at the end of the .csproj file for your project (just before the closeing </project> tag). This will fix the problem for any linked, un-compiled files:

 <!--
  ============================================================
  _CopyWebApplication
  MODIFIED: Ignores linked files as part of normal deployment logic.

  This target will copy the build outputs along with the
  content files into a _PublishedWebsites folder.

  This Task is only necessary when $(OutDir) has been redirected
  to a folder other than ~\bin such as is the case with Team Build.
  ============================================================
  -->
  <Target Name="_CopyWebApplication" Condition="'$(OutDir)' != '$(OutputPath)'">
    <!-- Log tasks -->
    <Message Text="Copying Web Application Project Files for $(MSBuildProjectName)" />
    <!-- Create the _PublishedWebsites\app\bin folder -->
    <MakeDir Directories="$(WebProjectOutputDir)\bin" />
    <!-- Copy build outputs to _PublishedWebsites\app\bin folder -->
    <Copy SourceFiles="@(IntermediateAssembly)"
      DestinationFolder="$(WebProjectOutputDir)\bin"
      SkipUnchangedFiles="true" />
    <Copy SourceFiles="@(AddModules)"
      DestinationFolder="$(WebProjectOutputDir)\bin"
      SkipUnchangedFiles="true" />
    <Copy SourceFiles="$(IntermediateOutputPath)$(_SGenDllName)"
      DestinationFolder="$(WebProjectOutputDir)\%(Content.SubFolder)%(Content.RecursiveDir)"
      SkipUnchangedFiles="true"
      Condition="'$(_SGenDllCreated)'=='true'" />
    <Copy SourceFiles="$(IntermediateOutputPath)$(TargetName).pdb"
      DestinationFolder="$(WebProjectOutputDir)\bin"
      SkipUnchangedFiles="true"
      Condition="'$(_DebugSymbolsProduced)'=='true'" />
    <Copy SourceFiles="@(DocFileItem)"
      DestinationFolder="$(WebProjectOutputDir)\bin"
      SkipUnchangedFiles="true"
      Condition="'$(_DocumentationFileProduced)'=='true'" />
    <Copy SourceFiles="@(IntermediateSatelliteAssembliesWithTargetPath)"
      DestinationFiles="@(IntermediateSatelliteAssembliesWithTargetPath->'$(WebProjectOutputDir)\bin\%(Culture)\$(TargetName).resources.dll')"
      SkipUnchangedFiles="true" />
    <Copy SourceFiles="@(ReferenceComWrappersToCopyLocal); @(ResolvedIsolatedComModules); @(_DeploymentLooseManifestFile); @(NativeReferenceFile)"
      DestinationFolder="$(WebProjectOutputDir)\bin"
      SkipUnchangedFiles="true" />
    <!-- copy any referenced assemblies to _PublishedWebsites\app\bin folder -->
    <Copy SourceFiles="@(ReferenceCopyLocalPaths)"
      DestinationFolder="$(WebProjectOutputDir)\bin"
      SkipUnchangedFiles="true" />
    <!-- MODIFICATION HERE: Copy local content files (i.e. non-linked files) recursively to _PublishedWebsites\app\ folder -->
    <Copy Condition=" '%(Content.Link)' == '' "
      SourceFiles="%(Content.Identity)"
      DestinationFolder="$(WebProjectOutputDir)\%(Content.RelativeDir)" />
  </Target>



  <!--
  ============================================================
  CopyLinkedContentFiles

  A new target to copy any linked content files into the
  web application output folder.

  NOTE: This is necessary even when '$(OutDir)' has not been redirected.
  ============================================================
  -->
  <Target Name="CopyLinkedContentFiles">
    <!-- Remove any old copies of the files -->
    <Delete Condition=" '%(Content.Link)' != '' AND Exists('$(WebProjectOutputDir)\%(Content.Link)') "
        Files="$(WebProjectOutputDir)\%(Content.Link)" />
    <!-- Copy linked content files recursively to the project folder -->
    <Copy Condition=" '%(Content.Link)' != '' "
      SourceFiles="%(Content.Identity)"
      DestinationFiles="$(WebProjectOutputDir)\%(Content.Link)" />
  </Target>
  <!-- Override the default target dependencies to -->
  <!-- include the new _CopyLinkedContentFiles target. -->
  <PropertyGroup>
    <PrepareForRunDependsOn>
      $(PrepareForRunDependsOn);
      _CopyWebApplication;
      CopyLinkedContentFiles;
      _BuiltWebOutputGroupOutput
    </PrepareForRunDependsOn>
  </PropertyGroup>
Faust
  • 13,751
  • 9
  • 48
  • 107
  • unfortunately this does not help in visualstudio 2017 for asp.net core 2.0 mvc problematic as described here: https://stackoverflow.com/questions/50386941/share-same-layout-cshtml-within-different-projects-of-one-solution-with-asp-net – misanthrop May 17 '18 at 08:48