Search code examples
asp.net-mvc-3asp.net-mvc-3-areas

How to specify route to shared views in MVC3 when using Areas


I have an MVC3/Razor app using Areas such that my views are in the following location:

/Areas/Areaname/Views/ControllerName/view.cshtml

Right now, for any shared partials, I have to put them here:

/Views/Shared/_sharedview.cshtml

I would prefer to have my shared views here:

/Areas/Shared/Views/_sharedvew.cshtml

Is there a way to tell the view engine to look somewhere other than the default location for shared views?

I am thinking something like this:

routes.MapRoute("Shared", "Areas/Shared/Views/{id}");

Thanks!


Solution

  • I usually descend a class from VirtualPathProvider

    Have a look here for more:

    http://coderjournal.com/2009/05/creating-your-first-mvc-viewengine/

    then register it in the startup:

    HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedViewPathProvider());
    

    You do not have to deal with paths that are outside of your scope as you can pass the function on the the base definition as I do here in this embedded view path provider:

      public class EmbeddedViewPathProvider: VirtualPathProvider
        {
            static EmbeddedViewPathProvider()
            {
                ResourcePaths = new Dictionary<string, ViewResource>();
                foreach (var resource in SettingsManager.Get<CoreSettings>().Assemblies.Select(assembly => new ViewResource
                                                                                                               {
                                                                                                                   VirtualPath = "/views/embedded/" + assembly.ToLower(), AssemblyName = assembly
                                                                                                               }))
                {
                    AddResource(resource);
                }
            }
    
            public static void AddResource(ViewResource assemblyResource)
            {
                ResourcePaths.Add(assemblyResource.VirtualPath, assemblyResource);
            }
            private static Dictionary<string, ViewResource> ResourcePaths { get; set; }
    
            public bool IsAppResourcePath(string virtualPath)
            {
    
                var checkPath = VirtualPathUtility.ToAppRelative(virtualPath).ToLower();
                return ResourcePaths.Any(resourcePath => checkPath.Contains(resourcePath.Key) && ResourceExists(resourcePath.Value, checkPath));
            }
    
            private static bool ResourceExists(ViewResource assemblyResource, string path)
            {
                var name = assemblyResource.GetFullyQualifiedTypeFromPath(path);
                return Assembly.Load(assemblyResource.AssemblyName).GetManifestResourceNames().Any(s => s.ToLower().Equals(name));
            }
    
    
            public ViewResource GetResource(string virtualPath)
            {
                var checkPath = VirtualPathUtility.ToAppRelative(virtualPath).ToLower();
                return (from resourcePath in ResourcePaths where checkPath.Contains(resourcePath.Key) select resourcePath.Value).FirstOrDefault();
            }
    
            public override bool FileExists(string virtualPath)
            {
                var exists = base.FileExists(virtualPath);
                return exists || IsAppResourcePath(virtualPath);
            }
    
            public override VirtualFile GetFile(string virtualPath)
            {
                if (IsAppResourcePath(virtualPath) && !base.FileExists(virtualPath))
                {
                    var resource = GetResource(virtualPath);
                    return new ViewResourceVirtualFile(virtualPath, resource);
                }
                return base.GetFile(virtualPath);
    
            }
    
            public override CacheDependency
                GetCacheDependency(string virtualPath,
                                   IEnumerable virtualPathDependencies,
                                   DateTime utcStart)
            {
                if (IsAppResourcePath(virtualPath))
                {
                    return null;
                }
                var dependencies = virtualPathDependencies.OfType<string>().Where(s => !s.ToLower().Contains("/views/embedded")).ToArray();
                return base.GetCacheDependency(virtualPath, dependencies, utcStart);
    
            }
    
            public override string GetCacheKey(string virtualPath)
            {
                return null;
            }
    
        }