There are 2 ASP.NET MVC5 projects. Some представления are the same, so I decided to keep them in the same file and in the projects to refer to them (Add existing item -> Add as link).

It would seem that everything is very simple, but such представлений files included in the link seem to be missing in the project: there are errors throughout the file, starting with @model The name model is does not exist in the current context , but at startup it says that view not found.

In the file properties of the file set the values Brouse to URL , Build action by analogy with others.

Can I include a .cshtml link and how to do it?

1 answer 1

The problem is that there are 3 different agents that need these types - and they are all configured differently. Microsoft did a lot of work so that they all worked with the same files - but they didn’t provide reference files.

You have to explain everything to them yourself. And so, in order.

1. Visual Studio Editor

Visual Studio Editor simply cannot edit files outside the project folder. You need to make a separate project for shared files - and open these files only in it.

2. Local server

The local server hosts files directly from the project folder without reading the project file. Since there is really no file in this place, an error occurs.

To "train" the server to give files based on their presence in the project, and not on the disk - you can use the following class:

 class ProjectFileProvider : VirtualPathProvider { private readonly string applicationVirtualPath = HostingEnvironment.ApplicationVirtualPath; private readonly string applicationPhysicalPath = HostingEnvironment.ApplicationPhysicalPath; private readonly Dictionary<string, ProjectFile> projectFiles; public ProjectFileProvider(string projectFile) { if (!applicationVirtualPath.EndsWith("/")) applicationVirtualPath = applicationVirtualPath + "/"; var project = XDocument.Load(Path.Combine(applicationPhysicalPath, projectFile)); var ns = project.Root.Name.Namespace; projectFiles = (from item in project.Root.Elements(ns + "ItemGroup").Elements() where item.Name.LocalName == "None" || item.Name.LocalName == "Content" let virtualPath = (string)item.Element(ns + "Link") ?? (string)item.Attribute("Include") let physicalPath = (string)item.Attribute("Include") select new ProjectFile(applicationVirtualPath + virtualPath, Path.Combine(applicationPhysicalPath, physicalPath))) .ToDictionary(file => file.VirtualPath, StringComparer.InvariantCultureIgnoreCase); } public override VirtualFile GetFile(string virtualPath) { if (virtualPath.StartsWith("~/")) virtualPath = applicationVirtualPath + virtualPath.Substring(2); ProjectFile file; projectFiles.TryGetValue(virtualPath, out file); return file; } public override bool FileExists(string virtualPath) { if (virtualPath.StartsWith("~/")) virtualPath = applicationVirtualPath + virtualPath.Substring(2); return projectFiles.ContainsKey(virtualPath); } public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) { long hash = 0; foreach (string filepath in virtualPathDependencies) unchecked { hash = hash * 31 + filepath.GetHashCode(); var file = GetFile(filepath) as ProjectFile; if (file != null) { hash = hash * 31 + file.GetFileInfo().LastWriteTimeUtc.GetHashCode(); } } return hash.ToString("x"); } public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) { var files = virtualPathDependencies.Cast<string>().Select(GetFile).Cast<ProjectFile>().Where(file => file != null).Select(file => file.PhysicalPath).ToArray(); return new CacheDependency(files, utcStart); } } private class ProjectFile : VirtualFile { public ProjectFile(string virtualPath, string physicalPath) : base(virtualPath) { PhysicalPath = physicalPath; } public string PhysicalPath { get; } public override Stream Open() => File.OpenRead(PhysicalPath); public FileInfo GetFileInfo() => new FileInfo(PhysicalPath); } 

It simply connects:

 if (HostingEnvironment.VirtualPathProvider.FileExists("~/Foo.csproj")) HostingEnvironment.RegisterVirtualPathProvider(new ProjectFileProvider("Foo.csproj")); 

Important note This method works only for those files that are needed by ASP.NET. That is, all sorts of .aspx, .cshtml, .svc and other similar files fall here.

But the scripts and pictures are given to IIS directly, so this trick is not applicable to them.

3. Publication

When publishing your application, the build system collects all the files together to transfer them to the server. Here I wanted to write how to manually edit the csproj file for embedding in the publication pipeline - but suddenly it turned out that the publication system already supports links.

But there is a subtlety associated with the previous item. The fact is that the project file is not published. That is why in the last paragraph, I put a check on its availability.

  • I understand correctly, 2. Is the local server the case whose solution is offered by mattperdeck.com/post/… ? - Ildar
  • @Ildar yes, but there it is crooked (when using the version control system, garbage will appear in it, plus changes in the files will no longer be picked up on the fly). - Pavel Mayorov
  • Clause 2 works, it is really convenient, than copy files when rebuilding, as indicated in the link given by me. With item 1, while you have to accept - Ildar