ASP.NET Core MVC - ビューの基底クラスを変更する

ASP.NET Core MVCのビュー全体で、プロジェクト独自のプロパティやメソッドを追加して利用したいことがあるかなと思います。

デフォルトでは、ビューはMicrosoft.AspNetCore.Mvc.Razor.RazorPage<TModel>を継承しています。このクラスを派生したクラスを用意することで実現できます。

詳しくはこのあたり。

ASP.NET Core の Razor 構文リファレンス | Microsoft Docs

上記ドキュメントそのままなんですが、覚え書きとしてメモしておきます。

まずRazorPage<TModel>を継承した独自のRazorページクラスを用意します。

// プロジェクト独自のRazorページクラス
public abstract class CustomRazorPage<TModel> : RazorPage<TModel> {
    // 独自のプロパティやメソッドを追加したい
    public int CustomValue { get; set; }
}

つぎに@inheritsディレクティブを使って、用意したRazorページクラスを継承するようにします。プロジェクト全体でビューの基底クラスを変えるには、Viewsフォルダ直下の_ViewImports.cshtmlで指定します。

@* _ViewImports.cshtml *@
@* ビューの基底クラスを変更する *@
@inherits CustomRazorPage<TModel>

すると、各cshtmlでカスタムRazorページのプロパティやメソッドが使えるようになります。

@* 各cshtml *@
@* 独自のプロパティが使えるようになる *@
@CustomValue

ASP.NET Core MVC - 生成されるURLを小文字にする

ASP.NET Core MVCを勉強し始めたので、その記録というかメモというか小ネタを残していきたいと思います。

まずはタグヘルパーやHTMLヘルパー(URLヘルパー)を使って生成するURLを小文字にする方法です。CoreじゃないASP.NET MVCでは、RouteCollection.LowercaseUrlsをtrueに設定していましたが、CoreではRouteOptions.LowercaseUrlsにtrueを設定するようです。

public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        // MVCをサービスに追加
        services.AddMvc();

        services.Configure<RouteOptions>(options => {
            // URLを小文字にする
            options.LowercaseUrls = true;
        });
    }
}

RouteOptions.LowercaseUrls Property (Microsoft.AspNetCore.Routing) | Microsoft Docs

Dropbox.NETを試す

DropboxAPIを使ってみようとふと思いました。公式のドキュメントを見てみるとDropbox.NETというライブラリがあったので、チュートリアルを参考にしながら試してみました。

.NET - Developers - Dropbox

準備

コンソールアプリプロジェクトを作って、NuGetでDropbox.Apiをインストールします。

Install-Package Dropbox.Api

NuGet Gallery | Dropbox.Api 4.7.0

Dropbox APIを使うために、App Consoleでアプリを登録して、OAuth2のアクセストークンを生成しておきます。(手順は省略。公式ドキュメントを見てください。)

https://www.dropbox.com/developers/apps

基本的な操作を試す

フォルダの追加・削除やファイルのアップロード・ダウンロードなど基本的な操作を試していきますが、まずはエントリポイントです。

// Program.cs
class Program {
    static void Main(string[] args) {
        const string token = "ここにアクセストークン";

        // アクセストークンを使ってDropboxクライアントを生成
        using (var client = new DropboxClient(token)) {
            // Dropboxサンプルを実行
            new DropboxSample(client).RunAsync().Wait();
        }
    }
}

// DropboxSample.cs
// Dropboxサンプル
class DropboxSample {
    // Dropboxクライアント
    private readonly DropboxClient _client;

    public DropboxSample(DropboxClient client) {
        _client = client;
    }

    // サンプルを実行
    public async Task<bool> RunAsync() {
        // todo: ここに以下のコードがある体で
        return true;
    }
}

ここからのコードはDropboxSample.RunAsyncメソッドの中身です。コードの順番もそのままで実行できるはず。

フォルダを作成
// "/Temp/sample"フォルダを作成
await _client.Files.CreateFolderV2Async("/Temp/sample");
ファイルをアップロード

作成したフォルダにテキストファイルを2つアップロードします。streamはファイルの中身です。

// "text1.txt"
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("file1 content"))) {
    await _client.Files.UploadAsync("/Temp/sample/text1.txt", body: stream);
}

// "text2.txt"
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("file2 content"))) {
    await _client.Files.UploadAsync("/Temp/sample/text2.txt", body: stream);
}
ファイル一覧を取得

ListFolderAsyncメソッドを使ってファイル一覧を取得します。結果のListFolderResult.HasMoreプロパティがtrueの場合は、ListFolderContinueAsyncメソッドを使ってファイル一覧の続きを取得します。

// ファイルの一覧を取得
// ListFolderContinueAsyncを試したいのでlimitを1にする
var result = await _client.Files.ListFolderAsync("/Temp/sample", limit: 1);
foreach (var entry in result.Entries) {
    Console.WriteLine(entry.Name);
    // text1.txt
}

while (result.HasMore) {
    result = await _client.Files.ListFolderContinueAsync(result.Cursor);

    foreach (var entry in result.Entries) {
        Console.WriteLine(entry.Name);
        // text2.txt
    }
}
ファイルをダウンロード
// ファイルをダウンロード
// "text1.txt"
using (var response = await _client.Files.DownloadAsync("/Temp/sample/text1.txt")) {
    Console.WriteLine(await response.GetContentAsStringAsync());
    // file1 content
}

// "text2.txt"
using (var response = await _client.Files.DownloadAsync("/Temp/sample/text2.txt")) {
    Console.WriteLine(await response.GetContentAsStringAsync());
    // file2 content
}
ファイルを削除
// ファイルを削除
// "text1.txt"
await _client.Files.DeleteV2Async("/Temp/sample/text1.txt");

// "text2.txt"
await _client.Files.DeleteV2Async("/Temp/sample/text2.txt");
フォルダを削除
// "/Temp/sample"フォルダを削除
await _client.Files.DeleteV2Async("/Temp/sample");

こんなところかなと。

ソース全体はこちらに。

Dropbox.NETを試す · GitHub

.NET CoreでAzure Queueを試したサンプルコード

.NET Core 2.0のコンソールアプリでAzureのQueueを使ってみました。

上記ドキュメントを参考にして

  • キューの作成と削除
  • メッセージの追加、取得、削除

を試しています。

準備

コンソール アプリ (.NET Core)プロジェクトを作成して、NuGetでWindowsAzure.Storageをインストールします。

Install-Package WindowsAzure.Storage

NuGet Gallery | WindowsAzure.Storage 9.1.0

Queueサンプルを実行するエントリ(Program.cs)

接続文字列からストレージアカウントを作成してQueueサンプルを実行します。

Queueを試す(QueueSample.cs)

QueueSampleクラスです。

CloudQueueClientを使ってQueueを作成・削除できます。あとはQueueにメッセージを追加したり、Queueからメッセージを取得したり、削除したり。

なるほどねと思ったのは、CloudQueue.GetMessageAsyncメソッドやCloudQueue.GetMessagesAsyncメソッドで取得したメッセージが一時的に参照できなくなることです。同じメッセージを二重で処理しないようにするためですね。

.NET CoreでAzure Blobを試したサンプルコード

.NET Core 2.0のコンソールアプリでAzureのBlobを試しました。

このあたりのドキュメントを参考にしながら書いてみたサンプルコードを残しておきます。

ミニマムかなと思う次のことを試しましたが、ほとんど躓かずにできたかなと思います。ドキュメントがわかりやすくてありがたいです。

  • Blobコンテナの作成と削除
  • Blobの追加、更新、削除
  • Blobの取得
  • Blob一覧の取得

準備

コンソール アプリ (.NET Core)プロジェクトを作成して、NuGetでWindowsAzure.Storageをインストールします。

Install-Package WindowsAzure.Storage

NuGet Gallery | WindowsAzure.Storage 9.1.0

Blobサンプルを実行するエントリ(Program.cs)

接続文字列からストレージアカウントを作成してBlobサンプルを実行しています。

Blobを試す(BlobSample.cs)

実際のBlobサンプル部分です。

流れとしてはまずストレージアカウントからBlobクライアントを作成して、次にBlobクライアントからBlobコンテナを取得(作成)します。そして、Blobコンテナが持っているBlobを操作するメソッドを使ってごにょごにょする感じです。

Blobの追加もBlobの更新も要するにアップロードなので、どちらの場合もCloudBlockBlob.UploadTextAsyncメソッドやCloudBlockBlob.UploadFromStreamAsyncメソッドなどを使うみたいです。

// 追加も更新も同じ
var blob = container.GetBlockBlobReference("Blobの名前");
await blob.UploadTextAsync("Blobの中身");

Blobの一覧を取得するにはCloudBlobContainer.ListBlobsSegmentedAsyncメソッドを使いますが、デフォルトの動きでは1回に取得できるのは5,000個までとのことです。それ以上の場合は、BlobContinuationTokenを使って取得を繰り返すようにするみたいです。

この部分。

var token = default(BlobContinuationToken);
do {
    // Blobの一覧を取得
    var segment = await container.ListBlobsSegmentedAsync(token);

    token = segment.ContinuationToken;

    foreach (var blob in segment.Results.OfType<CloudBlockBlob>()) {
        // blobを使って何かする
    }
} while (token != null); // トークンがnullでないとまだ一覧取得できる

おわり。