2008-08-21 12 views
48

別々のアセンブリをプラグインできるようにしたいWebアプリケーションを作成しようとしています。私は、プラグインアセンブリからコントローラを作成するために使用する依存性注入のために、Unityと組み合わされたMVCプレビュー4を使用しています。私はビューエンジンとしてWebForms(デフォルトのaspx)を使用しています。ASP.NET MVCの別のアセンブリでのビュー

ビューを使用したい場合は、ASPXパーツの動的コンパイルのために、コアプロジェクトで定義されているビューに固執しています。 ASPXファイルを別のアセンブリで囲む適切な方法を探しています。展開のステップ全体を実行する必要はありません。私は明白な何かを欠いていますかまたは、プログラムによるビューの作成に頼るべきですか?


更新:私は受け入れられた答えを変更しました。 Daleの答えは非常に徹底していますが、別の仮想パスプロバイダを使用して解決策を検討しました。それは魅力のように機能し、コード内で約20行しか取りません。

+0

のようなものを使って共有ビューを起動する必要があり、強い型付けを取り戻すために、型なしオブジェクトとして扱われるのですか? – jmcd

+0

@jmcd:それはそうであるように見えます。 –

+0

これを達成するために投稿できるサンプルコードはありますか? –

答えて

15

これは、WebFormsのユーザーがUserControl ASCXファイルをDLLにコンパイルしようとしたときと同じ問題です。あなたのために働くかもしれないこのhttp://www.codeproject.com/KB/aspnet/ASP2UserControlLibrary.aspxも見つかりました。私は見つけることに少し近づくました:

12
protected void Application_Start() 
{ 
    WebFormViewEngine engine = new WebFormViewEngine(); 

    engine.ViewLocationFormats = new[] { "~/bin/Views/{1}/{0}.aspx", "~/Views/Shared/{0}.aspx" }; 
    engine.PartialViewLocationFormats = engine.ViewLocationFormats; 

    ViewEngines.Engines.Clear(); 
    ViewEngines.Engines.Add(engine); 

    RegisterRoutes(RouteTable.Routes); 
} 

Webformsビューエンジンにあまり馴染んでいないのであれば、

私は最近Sparkビューエンジンを試しました。私が脅かされても、Webformsに戻ってしまうのではなく、アプリケーションのモジュール性のための素晴らしいフックを提供します。彼らのドキュメントの例では、WindsorをIoCコンテナとして使用していますが、別の方法を採用したい場合は、それほど難しいとは思いません。

+0

WebFormviewEngineを作成する代わりに、次のようにRazorViewEngineを取得しても同じことができます。RazorViewEngine engine = ViewEngines.Engines.OfType ()。First();追加されたパスを前述のプロパティに連結するだけです。 – CSharpie

2

すべてまだ聖杯を探しているあなたをすることに加え「常にコピー」へのビューの「コピー出力に」プロパティを設定し

29

さまざまな部分サンプルから適切に機能するには時間がかかりすぎたので、共有ライブラリのViewsフォルダからビューを取得するために必要なコードは、通常のViewsフォルダと同じですが、組み込みリソースとして構築する。通常のファイルが存在しない場合は、埋め込みファイルのみを使用します。

のApplication_Startの最初の行:

HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedViewPathProvider()); 

VirtualPathProvider

public class EmbeddedVirtualFile : VirtualFile 
{ 
    public EmbeddedVirtualFile(string virtualPath) 
     : base(virtualPath) 
    { 
    } 

    internal static string GetResourceName(string virtualPath) 
    { 
     if (!virtualPath.Contains("/Views/")) 
     { 
      return null; 
     } 



     var resourcename = virtualPath 
      .Substring(virtualPath.IndexOf("Views/")) 
      .Replace("Views/", "OrangeGuava.Common.Views.") 
      .Replace("/", "."); 

     return resourcename; 

    } 


    public override Stream Open() 
    { 
     Assembly assembly = Assembly.GetExecutingAssembly(); 


     var resourcename = GetResourceName(this.VirtualPath); 
     return assembly.GetManifestResourceStream(resourcename); 
    } 




} 

public class EmbeddedViewPathProvider : VirtualPathProvider 
{ 


    private bool ResourceFileExists(string virtualPath) 
    { 

     Assembly assembly = Assembly.GetExecutingAssembly(); 


     var resourcename = EmbeddedVirtualFile.GetResourceName(virtualPath); 
     var result = resourcename != null && assembly.GetManifestResourceNames().Contains(resourcename); 
     return result; 
    } 

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


    public override VirtualFile GetFile(string virtualPath) 
    { 

     if (!base.FileExists(virtualPath)) 
     { 
      return new EmbeddedVirtualFile(virtualPath); 
     } 
     else 
     { 
      return base.GetFile(virtualPath); 
     } 

    } 

} 

最後のステップ、それは作業を取得するためには、ルートのWeb.Configが強く型付けされたMVCを解析するために正しい設定を含んでいなければならないということですビューフォルダのビューは使用されません。

<pages 
    validateRequest="false" 
    pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" 
    pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" 
    userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> 
    <controls> 
    <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" /> 
    </controls> 
</pages> 

Monoで作業するには、いくつかの追加ステップが必要です。まず、あなたが必要なアプリが起動するのではなく時にビューのフォルダ内のすべてのファイルがロードされるため、GetDirectoryを実装する必要があります。

public override VirtualDirectory GetDirectory(string virtualDir) 
    { 
     Log.LogInfo("GetDirectory - " + virtualDir); 
     var b = base.GetDirectory(virtualDir); 
     return new EmbeddedVirtualDirectory(virtualDir, b); 
    } 

public class EmbeddedVirtualDirectory : VirtualDirectory 
{ 
    private VirtualDirectory FileDir { get; set; } 

    public EmbeddedVirtualDirectory(string virtualPath, VirtualDirectory filedir) 
     : base(virtualPath) 
    { 
     FileDir = filedir; 
    } 

    public override System.Collections.IEnumerable Children 
    { 
     get { return FileDir.Children; } 
    } 

    public override System.Collections.IEnumerable Directories 
    { 
     get { return FileDir.Directories; } 
    } 

    public override System.Collections.IEnumerable Files 
    { 
     get { 

      if (!VirtualPath.Contains("/Views/") || VirtualPath.EndsWith("/Views/")) 
      { 
       return FileDir.Files; 
      } 

      var fl = new List<VirtualFile>(); 

      foreach (VirtualFile f in FileDir.Files) 
      { 
       fl.Add(f); 
      } 


      var resourcename = VirtualPath.Substring(VirtualPath.IndexOf("Views/")) 
.Replace("Views/", "OrangeGuava.Common.Views.") 
.Replace("/", "."); 

      Assembly assembly = Assembly.GetExecutingAssembly(); 

      var rfl = assembly.GetManifestResourceNames() 
       .Where(s => s.StartsWith(resourcename)) 
       .Select(s => VirtualPath + s.Replace(resourcename, "")) 
       .Select(s => new EmbeddedVirtualFile(s)); 
      fl.AddRange(rfl); 

      return fl; 
     } 
    } 
} 

最後に、強く型付けされたビューはほとんどなく、かなり完璧に動作します。モデルはまだmvc.net内のルーティングと連携する仮想パスプロバイダーを使用していますので、

<% var Model2 = Model as IEnumerable<AppModel>; %> 
+2

また、ビューのビルドアクションを「組み込みリソース」に設定することも忘れないでください。ビューのフォルダもWebプロジェクトに存在する必要があります。私の場合は、アセンブリプロジェクトのフォルダViews/Shared/Dynamic.cshtmlにビューを配置し、アセンブリを参照するWebプロジェクトでViews/Sharedを作成する必要があります。 –

関連する問題