简体   繁体   English

当应用程序根目录不同时,不会调用MVC VirtualPathProvider GetFile

[英]MVC VirtualPathProvider GetFile not called when app root is different

I have all views, scripts, styles compiled as a embedded resource in different DLL. 我将所有视图,脚本,样式编译为不同DLL中的嵌入式资源。 Iam using VirtualPathProvider to get the file. 我使用VirtualPathProvider来获取文件。 The web running fine when it's places in the web root -> www.XXX.com 放置在网站根目录-> www.XXX.com中的网站运行良好

The problem is when i place my website to www.XXX.com/YYY It checks files in the VirtualPathProvider if they exist and yes, my files are found. 问题是当我将网站放置到www.XXX.com/YYY时,它检查VirtualPathProvider中的文件是否存在,是的,找到了我的文件。 My controller function which returns a View is called, but GetFile in VirtualPathProvider is not called and website says Error 404. 我的返回视图的控制器函数被调用,但未调用VirtualPathProvider中的GetFile,并且网站显示错误404。

Routing: 路由:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(name: "Default", namespaces: new[] {"Merz.Ems.Core.Controllers"},
        url: "{controller}/{action}", defaults: new {controller = "Index", action = "Index"});

    routes.Add(new Route("Resources/{*url}", new EmbeddedResourceRouteHandler()));
}

The EmbeddedResourceRouteHandler handles scripts and styles. EmbeddedResourceRouteHandler处理脚本和样式。

VirtualPathProvider: VirtualPathProvider:

using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Web.Hosting;
using System.Web.Routing;

namespace Merz.Ems.Core.VirtualProviders
{
public class EmbeddedVirtualPathProvider : VirtualPathProvider
{
    public class EmbeddedVirtualFile : VirtualFile
    {
        private Stream _stream;

        public EmbeddedVirtualFile(string virtualPath, Stream stream) : base(virtualPath)
        {
            if (null == stream) throw new ArgumentNullException("stream");
            _stream = stream;
        }

        public override Stream Open()
        {
            return _stream;
        }
    }

    public override CacheDependency GetCacheDependency(string virtualPath,IEnumerable virtualPathDependencies,DateTime utcStart)
    {
        string embedded = _GetEmbeddedPath(virtualPath);

        try
        {
            if (string.IsNullOrEmpty(embedded))
                return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
        }
        catch
        {
            // ignored
        }

        return null;
    }

    public override bool FileExists(string virtualPath)
    {
        string embedded = _GetEmbeddedPath(virtualPath);
        bool reallyExists = File.Exists(HttpContext.Current.Server.MapPath(virtualPath));

        return reallyExists || base.FileExists(virtualPath) || !string.IsNullOrEmpty(embedded);
    }

    public override VirtualFile GetFile(string virtualPath)
    {
        string embedded = _GetEmbeddedPath(virtualPath);
        if (string.IsNullOrEmpty(embedded))
        {
            if (base.FileExists(virtualPath)) return base.GetFile(virtualPath);
            else
            {
                var path = HttpContext.Current.Server.MapPath(virtualPath);
                if (File.Exists(path))
                {
                    Stream s = File.OpenRead(path);
                    return new EmbeddedVirtualFile(virtualPath, s);
                }
            }
        }

        return new EmbeddedVirtualFile(virtualPath,GetType().Assembly.GetManifestResourceStream(embedded));
    }

    private string _GetEmbeddedPath(string path)
    {
        if (path.StartsWith("~/")) path = path.Substring(1);

        path = path.ToLowerInvariant();
        path = "Merz.Ems.Core" + path.Replace('/', '.');
        return GetType().Assembly.GetManifestResourceNames().FirstOrDefault(o => o.Equals(path, StringComparison.OrdinalIgnoreCase));
    }
}

So, why it's working if my page runs from www.xxx.com and not www.xxx.com/yyy ? 那么,如果我的网页是从www.xxx.com而不是www.xxx.com/yyy运行的,那为什么能正常工作呢? (yyy is a root of the application ) (yyy是应用程序的根)

Thanks :) 谢谢 :)

I solved my problem after lot of hours. 几个小时后,我解决了我的问题。

    private string _GetEmbeddedPath(string path)
    {
        if (path.StartsWith("~/")) path = path.Substring(1);

        if (HostingEnvironment.ApplicationVirtualPath != null)
        {
            if (path.StartsWith(HostingEnvironment.ApplicationVirtualPath)) path = path.Substring(HostingEnvironment.ApplicationVirtualPath.Length);
        }

        path = path.ToLowerInvariant();
        path = "Merz.Ems.Core" + path.Replace('/', '.');
        return GetType().Assembly.GetManifestResourceNames().FirstOrDefault(o => o.Equals(path, StringComparison.OrdinalIgnoreCase));
    }

In this function, i added 在此功能中,我添加了

if (HostingEnvironment.ApplicationVirtualPath != null)
{
      if (path.StartsWith(HostingEnvironment.ApplicationVirtualPath)) path = path.Substring(HostingEnvironment.ApplicationVirtualPath.Length);
}

to remove the subfolder, so it finds the file without any problem. 删除子文件夹,以便它找到文件没有任何问题。 My first attempt was to filter subfolder from the virtual path in FileExists function and that was the bad way. 我的第一次尝试是从FileExists函数的虚拟路径中过滤子文件夹,这是不好的方法。 Why ? 为什么呢 Who knows. 谁知道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM