Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

asp.net mvc 3 - Using custom VirtualPathProvider to load embedded resource Partial Views

I wrote custom VirtualFile and VirtualPathProvider implementations that are successfully obtaining embedded resources that are Partial Views.

However, when I attempt to render them it produces this error:

The view at '~/Succeed.Web/Succeed.Web.Controls.SImporter._SImporter.cshtml' must derive from WebViewPage, or WebViewPage<TModel>.

When rendering the partial view, inside of a regular View, it looks like the following:

Html.RenderPartial("~/Succeed.Web/Succeed.Web.Controls.SImporter._SImporter.cshtml");

What is causing it to believe this isn't a partial view?

EDIT: I Posted my code for both the virtual file & virtual file provider implementations for anyone who stumbles upon this looking for solution on getting that component working. This question will also serve well for those based upon the question title.

ere is the VirtualFile implementation for reference:

public class SVirtualFile : VirtualFile
{
    private string m_path;

    public SVirtualFile(string virtualPath)
        : base(virtualPath)
    {
        m_path = VirtualPathUtility.ToAppRelative(virtualPath);
    }

    public override System.IO.Stream Open()
    {
        var parts = m_path.Split('/');
        var assemblyName = parts[1];
        var resourceName = parts[2];

        assemblyName = Path.Combine(HttpRuntime.BinDirectory, assemblyName);
        var assembly = System.Reflection.Assembly.LoadFile(assemblyName + ".dll");

        if (assembly != null)
        {
            return assembly.GetManifestResourceStream(resourceName);
        }
        return null;
    }
}

VirtualPathProvider:

public class SVirtualPathProvider : VirtualPathProvider
{
    public SVirtualPathProvider() 
    { 

    }

    private bool IsEmbeddedResourcePath(string virtualPath)
    {
        var checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
        return checkPath.StartsWith("~/Succeed.Web/", StringComparison.InvariantCultureIgnoreCase);
    }

    public override bool FileExists(string virtualPath)
    {
        return IsEmbeddedResourcePath(virtualPath) || base.FileExists(virtualPath);
    }

    public override VirtualFile GetFile(string virtualPath)
    {
        if (IsEmbeddedResourcePath(virtualPath))
        {
            return new SVirtualFile(virtualPath);
        }
        else
        {
            return base.GetFile(virtualPath);
        }
    }

    public override CacheDependency GetCacheDependency( string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
    {
        if (IsEmbeddedResourcePath(virtualPath))
        {
            return null;
        }
        else
        {
            return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
        }
    }
}

And of course, don't forget to register this new provider in the Global.asax file of your project in the Application_Start() event

System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new SVirtualPathProvider());
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Because now you are serving your views from some unknown location there is no longer the ~/Views/web.config file which applies and indicates the base class for your razor views (<pages pageBaseType="System.Web.Mvc.WebViewPage">). So you could add an @inherits directive at the top of each embedded view to indicate the base class.

@inherits System.Web.Mvc.WebViewPage
@model ...

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...