36 votes

Utilisation de VirtualPathProvider personnalisé pour charger les vues partielles des ressources intégrées

J'ai écrit personnalisé VirtualFile et VirtualPathProvider des implémentations réussir à obtenir les ressources intégrées qui sont des Vues Partielles.

Cependant, lorsque je tente de la rendre, il produit cette erreur:

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

Lors du rendu de la vue partielle, à l'intérieur d'un Affichage normal, il ressemble à la suivante:

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

Ce qui est à l'origine de croire que ce n'est pas une vue partielle?

EDIT: j'ai Posté mon code pour le fichier virtuel & de fichiers virtuel fournisseur d'implémentation de quelqu'un qui tombe sur cette recherche de solution sur l'obtention de ce composant de travail. Cette question sera aussi bien servir pour ceux basés sur la question du titre.

ere est la VirtualFile mise en œuvre pour la référence:

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);
        }
    }
}

Et bien sûr, n'oubliez pas d'enregistrer ce nouveau fournisseur dans le monde.asax fichier de votre projet dans le Application_Start() de l'événement

System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new SVirtualPathProvider());

44voto

Darin Dimitrov Points 528142

Parce que maintenant vous servez vos vues à partir d'un endroit inconnu il n'y a plus le fichier qui s'applique et indique la classe de base pour vos vues de rasoir ( ). Ainsi, vous pouvez ajouter une directive @inherits en haut de chaque vue intégrée pour indiquer la classe de base.

7voto

Max Schilling Points 1389

J'ai utilisé de la Fpo réponse comme une base, mais il s'est étendu sur un peu et intégré la réponse à la question dans ma solution.

Cela semble quelque peu fréquemment posées question ici et je n'ai pas vu de réponse complète, donc j'ai pensé qu'il pourrait être utile de partager ma solution de travail.

Je charge mes ressources à partir d'une base de données et je les ai mis en cache dans le Cache par défaut (Système d'.Web.La mise en cache.Cache).

Ce que j'ai fait était de créer un personnalisé CacheDependency sur la TOUCHE que j'utilise pour la recherche de la ressource. De cette façon, chaque fois que mon code invalide qui cache (sur une édition, etc.) la dépendance de cache sur cette clé est retirée, et le VirtualPathProvider à son tour invalide le cache et le VirtualFile obtient reloaded.

J'ai aussi modifié le code pour qu'il ajoute automatiquement hérite de déclaration, de sorte qu'il n'a pas besoin d'être stockés dans ma base de données de ressources et j'ai aussi automatiquement ajouter un peu par défaut à l'aide des déclarations comme cette "vue" n'est pas chargé par la voie normale, de sorte que rien par défaut inclut dans votre site web.config ou viewstart ne sont pas utilisables.

CustomVirtualFile:

public class CustomVirtualFile : VirtualFile
{
    private readonly string virtualPath;

    public CustomVirtualFile(string virtualPath)
        : base(virtualPath)
    {
        this.virtualPath = VirtualPathUtility.ToAppRelative(virtualPath);
    }

    private static string LoadResource(string resourceKey)
    {
        // Load from your database respository or whatever here...
        // Note that the caching is disabled for this content in the virtual path
        // provider, so you must cache this yourself in your repository.

        // My implementation using my custom service locator that sits on top of
        // Ninject
        var contentRepository = FrameworkHelper.Resolve<IContentRepository>();

        var resource = contentRepository.GetContent(resourceKey);

        if (String.IsNullOrWhiteSpace(resource))
        {
            resource = String.Empty;
        }

        return resource;
    }

    public override Stream Open()
    {
        // Always in format: "~/CMS/{0}.cshtml"
        var key = virtualPath.Replace("~/CMS/", "").Replace(".cshtml", "");

        var resource = LoadResource(key);

        // this automatically appends the inherit and default using statements 
        // ... add any others here you like or append them to your resource.
        resource = String.Format("{0}{1}", "@inherits System.Web.Mvc.WebViewPage<dynamic>\r\n" +
                                           "@using System.Web.Mvc\r\n" +
                                           "@using System.Web.Mvc.Html\r\n", resource);

        return resource.ToStream();
    }
}

CustomVirtualPathProvider:

public class CustomVirtualPathProvider : VirtualPathProvider
{
    private static bool IsCustomContentPath(string virtualPath)
    {
        var checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
        return checkPath.StartsWith("~/CMS/", StringComparison.InvariantCultureIgnoreCase);
    }

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

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

    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
    {
        if (IsCustomContentPath(virtualPath))
        {
            var key = VirtualPathUtility.ToAppRelative(virtualPath);

            key = key.Replace("~/CMS/", "").Replace(".cshtml", "");

            var cacheKey = String.Format(ContentRepository.ContentCacheKeyFormat, key);

            var dependencyKey = new String[1];
            dependencyKey[0] = string.Format(cacheKey);

            return new CacheDependency(null, dependencyKey);
        }

        return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
    }

    public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies)
    {
        if (IsCustomContentPath(virtualPath))
        {
            return virtualPath;
        }

        return base.GetFileHash(virtualPath, virtualPathDependencies);
    }
}

Espérons que cette aide!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X