ASP.NET Coreのコラムは、ウクライナのUbranians会社の責任者であるDmitry Sikorsky( DmitrySikorsky )からの別の出版物で続けています。 Dmitryは彼の記事で、ASP.NET Coreのメインプロジェクトアセンブリ以外のリソースの形で静的コンテンツを操作した経験について語っています。 このコラムの以前の記事は、 #aspnetcolumn -Vladimir Yunevでいつでも読むことができます。静的コンテンツ(JS、CSSファイル、画像など)を、たとえばWebアプリケーションのメインアセンブリの外部にリソースの形で配置する必要がある場合があります。 この短い記事では、この問題を解決する2つのアプローチについて説明します。
リソースを含むプロジェクトの準備
まず、リソースを備えたプロジェクトが必要です。 たとえば、リソースに1つのCSSファイル(ページ上のすべてのテキストを赤にする)と1つの画像を追加します。 これを行うには、プロジェクト自体のproject.jsonファイルの次の行だけでなく、ファイル自体も必要です。
"resource": [ "Styles/**", "Images/**" ]
以上で、プロジェクトのビルド後、Styles and Imagesフォルダーのコンテンツ全体がリソースになります(必要に応じて、フォルダー全体ではなく、実際に特定のファイルを指定できることは明らかです)。
アドバイス! すべてを試すか、GitHub https://github.com/DmitrySikorsky/AspNet5Resourcesからソースコードをダウンロードしてください 。ところで、リソースにファイルを追加すると、その場所の「ツリーのような」性質が「フラット」になり、ファイルパス内のすべての「\」文字がドットに変わります。 つまり、元の場所に関する情報は失われます(ファイル名にピリオドが含まれている場合があるため)。 たとえば、AspNet5Resources.Resourcesプロジェクトのリソースに追加されたファイル\ Styles \ test.cssは、次の名前になります(大文字と小文字は区別されます)。
AspNet5Resources.Resources.Styles.test.css
幸いなことに、リソースからコンテンツを取得するときに、毎回アセンブリ名(この場合はAspNet5Resources.Resources)を記述する必要はありません。 これを行うには、EmbeddedFileProviderを作成するときに、ベースネームスペースとして指定します(以下を参照)。
リソースの使用
プロジェクトに追加されたコンテンツをリソースの形で、少なくとも2つの方法で使用できます。すべてを自分で実装するか、既製の実装を使用します。 どちらの方法も非常に簡単です。
すべてを自分で実装するには、リソースのコンテンツを使用するプロジェクト(リソースがこのアセンブリまたは別の場所にあるかどうかは関係ありません)、名前で要求されたリソースを抽出し、出力ストリームに書き込むコントローラーに追加する必要があります:
public class ResourceController : Controller { public ActionResult Index(string name) { Assembly assembly = Assembly.Load(new AssemblyName("AspNet5Resources.Resources")); string fullName = assembly.GetName().Name + "." + name; if (assembly.GetManifestResourceNames().Contains(fullName)) { Stream stream = assembly.GetManifestResourceStream(fullName); return this.Stream(stream); } return this.HttpNotFound(); } }
出力ストリームでの作業を簡素化するために、ここではActionResultから継承した独自のStreamResultクラスを使用します。
public class StreamResult : ActionResult { private Stream stream; public StreamResult(Stream stream) { this.stream = stream; } public async override Task ExecuteResultAsync(ActionContext actionContext) { HttpResponse httpResponse = actionContext.HttpContext.Response; await this.stream.CopyToAsync(httpResponse.Body); } }
これは、この方法でリソースから画像を表示するのに十分です:
<img src="/resource?name=Images.test.png" />
次に、すぐに使用できる既製の実装を使用します。
まず、IFileProviderインターフェイスを実装して、結果としてクラス(CompositeFileProviderと呼びましょう)がいくつかの異なるプロバイダーを結合できるようにする必要があります。 クラス全体をソースで見ることができます(記事の最後にあるリンク)が、重要な点は次のとおりです。
public IFileInfo GetFileInfo(string subpath) { foreach (IFileProvider fileProvider in this.fileProviders) { IFileInfo fileInfo = fileProvider.GetFileInfo(subpath); if (fileInfo != null && fileInfo.Exists) return fileInfo; } return new NonexistentFileInfo(subpath); }
つまり、実際には、ファイルを検索するときのクラスは、このファイルが存在するプロバイダーを検索するために使用可能なすべてのプロバイダーを単純に反復処理します。
アプリケーションが物理的に既存のファイルとリソースのファイルの両方を使用できるように、次のようにしてCompositeFileProviderのインスタンスを作成します。
public IFileProvider GetFileProvider(string path) { IEnumerable<IFileProvider> fileProviders = new IFileProvider[] { new PhysicalFileProvider(path) }; return new CompositeFileProvider( fileProviders.Concat( new Assembly[] { Assembly.Load(new AssemblyName("AspNet5Resources.Resources")) }.Select(a => new EmbeddedFileProvider(a, a.GetName().Name)) ) ); }
次に、Startupクラスでアプリケーションを起動するときにプロバイダーを「登録」する必要があります。
public Startup(IApplicationEnvironment applicationEnvironment, IHostingEnvironment hostingEnvironment) { this.applicationBasePath = applicationEnvironment.ApplicationBasePath; hostingEnvironment.WebRootFileProvider = this.GetFileProvider(this.applicationBasePath); }
その後、リソースのコンテンツをより馴染みのある方法で使用できます。
<link href="/Styles.test.css" rel="stylesheet" />
結論
個人的には、(ファイルがリソースから抽出されるという事実にもかかわらず)通常のファイルの使用を連想させるため、2番目のオプションを好みます。 たとえば、ファイル名にピリオドを使用しない場合、リソース名の最後のポイントを除くすべてのポイントを「\」記号に置き換えて元の場所を「復元」し、より視覚的なURLを使用することもできますが、これはそれほど重要ではありません。
いつものように、すべてをすぐに開始して自分の目で見ることができるように、小さなテストプロジェクトを準備しました: github.com/DmitrySikorsky/AspNet5Resources 。
著者向け
ご友人、ご自身の資料でコラムをサポートすることに興味がある場合は、すべての詳細を議論するためにvyunev@microsoft.comまでご連絡ください。 ASP.NETおよびその他のトピックについて興味深い話ができる著者を探しています。
著者について
シコルスキー・ドミトリー・アレクサンドロヴィチ
Ubrainians Company(http://ubrainians.com/)
オーナー、マネージャー
ドミトリーシコルスキー