36

パーシャルビューの埋め込みリソースを正常に取得しているカスタムVirtualFileおよびVirtualPathProvider実装を記述しました。カスタムVirtualPathProviderを使用して埋め込みリソースをロードする部分ビュー

私はそれらをレンダリングしようとしたときしかし、それはこのエラーを生成します。

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

部分ビューをレンダリングする場合、通常のビューの内部で、それは次のようになります。

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

これは部分的な見解ではないと信じる原因は何ですか?

EDIT:I仮想ファイル&の仮想ファイルプロバイダの実装で、このコンポーネントを動作させる上で解決策を探している人のためのコードを投稿しました。この質問は、質問のタイトルに基づいている人にとっても役立ちます。

EREは、参考のためにVirtualFile実装です:

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

そしてもちろん、あなたのプロジェクトのGlobal.asaxファイルでこの新しいプロバイダを登録することを忘れないでくださいApplication_Start()イベント

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

答えて

44

これであなたはserviです不明な場所からあなたのビューを削除しました。~/Views/web.configファイルがなくなり、あなたのかみそりビュー(<pages pageBaseType="System.Web.Mvc.WebViewPage">)の基本クラスが適用されます。 @inheritsディレクティブを各埋め込みビューの先頭に追加して、基本クラスを示すことができます。

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

ありがとうございました。私の唯一の後悔は、私が与えるべき投票を1つだけ持っているということです。 = Pアップ投票ダーリンディミトロフ@この回答 –

+3

私はあなたが私はときに私のdll内のビューとしてこれを治療するためのインテリセンスを奨励するために採用する可能性がトリックを知っていると仮定しないのですか?今のところ、私は私のdllの中に置いたビューでインテリセンスサポートをほとんど持っていません。 –

+0

@MatthewCox、私はビューでIntellisenseについてよく知らないです。私がそれに頼るのをやめたのはずっと前のことです。ファイルに '.cshtml'拡張がある場合、Intellisenseを取得しませんか? –

6

私はOPの答えをベースとして使用しましたが、それを少し拡張して私の解答に質問への回答を取り入れました。

これはやや一般的な質問ですが、私は完全な答えを見たことがないので、私の解決策を分かち合うと助けになると思いました。

データベースから自分のリソースをロードして、それらをデフォルトのキャッシュ(System.Web.Caching.Cache)にキャッシュしています。

私がやったことは、リソースを検索するために使用しているKEYにカスタムCacheDependencyを作成することでした。そうすれば、他のコードがそのキャッシュを無効にするたびに(そのキーのキャッシュ依存性は削除されます)、VirtualPathProviderはそのキャッシュを無効にし、VirtualFileがリロードされます。

また、データベースリソースに格納する必要がないように自動的に継承文が追加されるようにコードを変更しました。また、この「ビュー」が自動的にプリロードされます。通常のチャンネルなので、web.configやviewstartにデフォルトのものは含まれません。

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

・ホープ、このことができます!

0

私はOP内の情報だけでなく、プロジェクト全体MVCコンポーネントを共有するためのsimple prototypeを作成するためのダーリン・ディミトロフの答えに大きく身を乗り出しました。これらは非常に役に立ちましたが、@ modelの共有ビューを使用するようなプロトタイプで対処されているいくつかの追加の障壁にはまだ遭遇しました。

関連する問題