Asp.net MVC VirtualPathProvider查看解析错误

时间:2010-08-17 21:36:58

标签: asp.net asp.net-mvc asp.net-mvc-2 virtualpathprovider

我正在为Asp.net MVC 2开发一个插件系统。我有一个包含控制器和视图的dll作为嵌入式资源。

我使用StructureMap扫描控制器的插件dll然后我可以将它们拉出来并在请求时实例化它们。这很好用。然后我有一个VirtualPathProvider,我改编自this post

public class AssemblyResourceProvider : VirtualPathProvider
{
    protected virtual string WidgetDirectory
    {
        get 
        { 
            return "~/bin";
        }
    }

    private bool IsAppResourcePath(string virtualPath)
    {
        var checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
        return checkPath.StartsWith(WidgetDirectory, StringComparison.InvariantCultureIgnoreCase);
    }

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

    public override VirtualFile GetFile(string virtualPath)
    {
        return IsAppResourcePath(virtualPath) ? new AssemblyResourceVirtualFile(virtualPath) : base.GetFile(virtualPath);
    }

    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies,
                                                       DateTime utcStart)
    {
        return IsAppResourcePath(virtualPath) ? null : base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
    }
}

internal class AssemblyResourceVirtualFile : VirtualFile
{
    private readonly string path;

    public AssemblyResourceVirtualFile(string virtualPath)
        : base(virtualPath)
    {
        path = VirtualPathUtility.ToAppRelative(virtualPath);
    }

    public override Stream Open()
    {
        var parts = path.Split('/');
        var resourceName = Path.GetFileName(path);

        var apath = HttpContext.Current.Server.MapPath(Path.GetDirectoryName(path));
        var assembly = Assembly.LoadFile(apath);
        return assembly != null ? assembly.GetManifestResourceStream(assembly.GetManifestResourceNames().SingleOrDefault(s => string.Compare(s, resourceName, true) == 0)) : null;
    }
}

VPP似乎也运作良好。找到视图并将其拉出到流中。然后我收到一个解析错误Could not load type 'System.Web.Mvc.ViewUserControl<dynamic>'.,我在前面的可插入视图示例中找不到这个错误。为什么我的观点在这个阶段不能编译?

感谢您的帮助,

伊恩

修改

更接近答案,但不清楚为什么事情没有编译。根据评论,我检查了版本,一切都在V2,我相信动态是在V2引入,所以这很好。我甚至没有安装V3,所以不能这样。然而,如果我完全删除<dynamic>,我有了渲染的视图。

所以VPP可以工作,但前提是视图不是强类型或动态的

这对强类型场景有意义,因为类型在动态加载的dll中,因此即使dll位于bin中,viewengine也不会意识到它。有没有办法在app start加载类型?考虑使用MEF而不是我的定制Structuremap解决方案。你觉得怎么样?

3 个答案:

答案 0 :(得分:2)

允许解析强类型视图的设置在〜/ Views / Web.Config中。当视图引擎使用虚拟路径提供程序时,它不在视图文件夹中,因此不会加载这些设置。

如果将Views / Web.Config的pages节点中的所有内容复制到根Web.Config,则可以正确解析强类型视图。

答案 1 :(得分:1)

尝试将Views / Web.config的内容直接添加到特定位置下的主web.config中,例如用于处理〜/ page / xxx等虚拟路径。在此处查看更多详细信息:http://blog.sergkazakov.com/2011/01/aspnet-strongly-typed-view-and-virtual.html

答案 2 :(得分:0)

  

有没有办法在app start加载类型?

是的,您可以使用BuildManager.AddReferencedAssembly(assembly),其中assembly是包含所请求类型的PreApplicationStartMethodAttribute。所以,一旦你使用MEF,最后一个应该很容易,但要注意,一切都应该在Application_Start之前完成,所以你可能希望使用Fisher Yates shuffle