ASP.NET Core開発におけるよくある問題とその解決策

1. SingletonサービスがScopedサービスを解決できないエラー

「Cannot resolve scoped service 'AlgoTag.Models.AlgoContext' from root provider.」というエラーが発生することがあります。これは、ASP.NET Coreの依存関係の注入(DI)におけるライフサイクルの問題です。

通常、ライフサイクルが長いSingletonサービスが、ライフサイクルが短いScopedサービスに依存する場合に発生します。SingletonサービスがScopedサービスを参照すると、そのScopedサービスもSingletonのスコープに引き上げられてしまい、DIコンテナが正しく解決できなくなるためです。

2. IISからLinuxシステムの共有フォルダにアクセスする方法

IISでホストされているASP.NET CoreアプリケーションからLinuxシステムのSamba共有フォルダにアクセスするには、主に2つの方法があります。

一つは、SharpCifsなどのライブラリを利用する方法です。もう一つは、Windows APIを用いてユーザーを偽装する方法です。ここでは、後者の方法を実装するC#コードを示します。


using System;
using System.Runtime.InteropServices;

public class LinuxShareAccessor : IDisposable
{
    private IntPtr _tokenHandle;
    private bool _disposed = false;

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUser(string userName, string domain, string passWord, int logonType, int logonProvider, ref IntPtr tokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool ImpersonateLoggedOnUser(IntPtr tokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool RevertToSelf();

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool CloseHandle(IntPtr handle);

    public LinuxShareAccessor(string userName, string passWord, string serverAddress)
    {
        _tokenHandle = IntPtr.Zero;
        if (!LogonUser(userName, serverAddress, passWord, 9, 0, ref _tokenHandle))
        {
            throw new Exception($"LogonUser failed with error code: {Marshal.GetLastWin32Error()}");
        }

        if (!ImpersonateLoggedOnUser(_tokenHandle))
        {
            CloseHandle(_tokenHandle);
            throw new Exception($"ImpersonateLoggedOnUser failed with error code: {Marshal.GetLastWin32Error()}");
        }
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            RevertToSelf();
            if (_tokenHandle != IntPtr.Zero)
            {
                CloseHandle(_tokenHandle);
            }
            _disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

3. AJAXで取得した画像データをjQueryで表示する方法

バックエンドからAJAX経由でimage/jpegなどのバイナリ画像データを取得し、jQueryでページ上に表示するには、`responseType`を`'blob'`に設定する必要があります。取得したBlobオブジェクトを`FileReader`で読み込み、その結果を`background-image`のURLとして設定します。


function loadAndDisplayImage(imageIndex) {
    $.ajax({
        url: `/Home/GetNextImage/${imageIndex}`,
        type: "GET",
        xhrFields: {
            responseType: 'blob'
        },
        success: function(imageBlob) {
            const targetImageElement = imageIndex === 0 ? $("#topimg") : $("#bottomimg");
            const fileReader = new FileReader();
            fileReader.onload = function(event) {
                targetImageElement.css("background-image", `url(${event.target.result})`);
            };
            fileReader.readAsDataURL(imageBlob);
        },
        error: function(xhr, status, error) {
            console.error("Image load failed:", error);
        }
    });
}

もし``タグの`src`属性に直接設定する場合は、以下のようにします。


<img src="/Home/Image" style="background-position:-324px 0px;" width="1800" height="720" />

4. Excelで開くと文字化けするUTF-8 CSVファイルのダウンロード

UTF-8エンコーディングで生成されたCSVファイルをExcelで直接開くと、文字化けが発生することがあります。これは、ExcelがBOM(Byte Order Mark)なしのUTF-8を正しく認識できないためです。この問題を解決するには、ファイルの先頭にBOMを追加してからダウンロードする必要があります。


using System.Text;

public IActionResult DownloadCsvFile()
{
    var csvContent = Encoding.UTF8.GetBytes("some data");
    var bom = Encoding.UTF8.GetPreamble();
    var fileBytes = bom.Concat(csvContent).ToArray();

    return new FileContentResult(fileBytes, "text/csv;charset=utf-8")
    {
        FileDownloadName = "データ一覧.csv"
    };
}

タグ: ASP.NET Core Dependency Injection Windows API AJAX csv

5月19日 21:00 投稿