Mengakses folder bersama di server lain dari aplikasi ASP.NET Core (versi Network Connected Program)

Halaman Diperbarui :
Tanggal pembuatan halaman :

Lingkungan verifikasi operasi

Visual Studio
  • Visual Studio 2022
ASP.NET Inti
  • 8 (Halaman Razor, MVC)
Windows Server
  • 2022 (ASP.NET Persyaratan Sistem Inti)
  • 2019 (Server Penyebaran Folder Bersama)
IIS
  • 10.0

Lingkungan operasi

Kami belum mengujinya dalam semua kasus, tetapi harus bekerja secara umum dalam kondisi berikut:

Visual Studio
  • Apa pun yang dapat mengembangkan proyek ASP.NET Core
ASP.NET Inti
  • Versi apa pun (MVC, Razor Pages, API)
Windows Server
  • Windows Server 2008 atau yang lebih baru
IIS
  • 7.0 atau yang lebih baru

Prasyarat

  • ASP.NET Aplikasi inti dimaksudkan untuk berjalan di IIS.
  • Karena menggunakan API Windows untuk otentikasi, itu tidak berfungsi pada non-Windows.

lingkungan

Ini diverifikasi di lingkungan berikut.

Tujuan penggunaan PC dan server
Windows 11 (Lokal) Lingkungan untuk mengembangkan program.
SV2022Tes Lingkungan yang menjalankan IIS dan ASP.NET Core. Akses folder bersama SV2019Test dari sini
SV2019Uji Server dengan folder bersama

Selain itu, berbagai pengaturan adalah sebagai berikut.

Nilai Nama Parameter
Akses Nama Pengguna Pengguna Bersama
Nama Folder Bersama Folder Bersama

Membangun Server Folder Bersama

Membuat pengguna

Buat pengguna untuk mengakses folder umum. Dalam hal ini, kami akan membuat akun lokal, tetapi jika Anda berurusan dengan server dan akun di domain seperti Active Directory, Anda juga dapat menggunakannya.

Proses pembuatan pengguna berada di luar cakupan tips ini, jadi kami tidak akan membahas terlalu banyak detail.

SharedUser Dalam hal ini, kita akan membuatnya dengan nama . Karena pengguna ini tidak mengoperasikan layar atau mengubah pengaturan, kata sandi tidak dapat diubah.

Jika Anda meninggalkan default, Anda dapat masuk dengan pengguna ini dengan Remote Desktop, dll., Jadi harap hapus dari grup Users .

Membuat Folder Bersama

Tidak masalah di mana Anda membuatnya. Ini karena server lain tidak peduli dengan lokasi folder fisik. Dalam hal ini, kami akan membuat folder bernama langsung di bawah SharedFolder drive C dan membagikannya.

Buka properti dan konfigurasikan pengaturan berbagi.

Nama folder bersama harus SharedFolder . Nama ini akan terlihat oleh server lain. Tambahkan SharedUser izin.

Everyone Hapus file .

Konfirmasikan dengan izin "Ubah".

Karena kami hanya menambahkan izin yang dapat diakses dari luar, kami akan mengaturnya secara SharedUser internal sehingga dapat beroperasi di folder ini.

Konfirmasikan dengan izin "Ubah".

Buat file untuk memeriksa operasi. Dalam program ini, pengkodean diproses dalam UFT-8, jadi harap simpan dalam UTF-8.

Tidak apa-apa jika Anda dapat mengakses Explorer dari \\<サーバー名>\ PC lain, masukSharedUser dengan , dan melihat file.

Membuat program untuk membaca dan menulis file dari folder bersama dari aplikasi ASP.NET Core

Operasi Mr./Ms. adalah mengklik tombol.

  • Muat file dalam folder bersama dan tampilkan di layar
  • Menulis file baru ke folder bersama

proses.

Razor Pages dan kode MVC adalah contohnya, tetapi program yang mengakses folder bersama sama untuk keduanya. Hal yang sama berlaku untuk API Web. Jika ada, itu harus bekerja dalam program klien juga.

Suatu proses yang terhubung ke jaringan selama durasi proses tertentu

Buat kode berikut di mana saja dalam proyek Anda. Nama kelasnya adalah SharedFolderAccessor , tetapi namanya sewenang-wenang. SharedFolderAccessor Anda dapat mengakses folder bersama hingga Anda membuat Dispose contoh . using Memungkinkan Anda menentukan periode waktu di mana akses dapat diakses dalam cakupan eksplisit.

using System.ComponentModel;
using System.Net;
using System.Runtime.InteropServices;

/// <summary>
/// 共有フォルダにユーザー名とパスワードでアクセスするためのクラスです。
/// using を使用すればそのスコープの間、共有フォルダにアクセスできます。
/// </summary>
public class SharedFolderAccessor : IDisposable
{
  private readonly string _networkName;

  /// <summary>
  /// コンストラクタです。
  /// </summary>
  /// <param name="networkName">共有フォルダのあるサーバーを「\\&lt;サーバー名&gt;」形式で指定します。</param>
  /// <param name="credentials">共有フォルダにアクセスするための資格情報です。</param>
  /// <exception cref="Win32Exception"></exception>
  public SharedFolderAccessor(string networkName, NetworkCredential credentials)
  {
    _networkName = networkName;

    // 接続するネットワークの情報を設定
    var netResource = new NetResource
    {
      Scope = ResourceScope.GlobalNetwork,
      ResourceType = ResourceType.Disk,
      DisplayType = ResourceDisplaytype.Share,
      RemoteName = networkName,
    };

    // ドメインがある場合はドメイン名も指定、ない場合はユーザー名のみ
    var userName = string.IsNullOrEmpty(credentials.Domain)
        ? credentials.UserName
        : $@"{credentials.Domain}\{credentials.UserName}";

    // 共有フォルダにユーザー名とパスワードで接続
    var result = WNetAddConnection2(netResource, credentials.Password, userName, 0);

    if (result != 0)
    {
      throw new Win32Exception(result, $"共有フォルダに接続できませんでした。(エラーコード:{result})");
    }

    // 正常に接続できれば WNetCancelConnection2 を呼び出すまではプログラムで共有フォルダにアクセス可能
  }

  ~SharedFolderAccessor()
  {
    // Dispose を呼び忘れたときの保険
    WNetCancelConnection2(_networkName, 0, true);
  }

  public void Dispose()
  {
    WNetCancelConnection2(_networkName, 0, true);
    GC.SuppressFinalize(this);  // Dispose を明示的に呼んだ場合はデストラクタの処理は不要
  }

  /// <summary>
  /// ネットワーク リソースへの接続を確立し、ローカル デバイスをネットワーク リソースにリダイレクトできます。
  /// </summary>
  /// <param name="netResource">ネットワーク リソース、ローカル デバイス、ネットワーク リソース プロバイダーに関する情報など。</param>
  /// <param name="password">ネットワーク接続の作成に使用するパスワード。</param>
  /// <param name="username">接続を確立するためのユーザー名。</param>
  /// <param name="flags">接続オプションのセット。</param>
  /// <returns></returns>
  [DllImport("mpr.dll")]
  private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags);

  /// <summary>
  /// 既存のネットワーク接続を取り消します。
  /// </summary>
  /// <param name="name">リダイレクトされたローカル デバイスまたは切断するリモート ネットワーク リソースの名前。</param>
  /// <param name="flags">接続の種類。</param>
  /// <param name="force">接続に開いているファイルまたはジョブがある場合に切断を行う必要があるかどうか。</param>
  /// <returns></returns>
  [DllImport("mpr.dll")]
  private static extern int WNetCancelConnection2(string name, int flags, bool force);

  /// <summary>
  /// NETRESOURCE 構造体を定義しています。
  /// </summary>
  [StructLayout(LayoutKind.Sequential)]
  private class NetResource
  {
    public ResourceScope Scope;
    public ResourceType ResourceType;
    public ResourceDisplaytype DisplayType;
    public int Usage;
    public string LocalName = "";
    public string RemoteName = "";
    public string Comment = "";
    public string Provider = "";
  }

  /// <summary>
  /// ネットワークリソースのスコープ。
  /// </summary>
  private enum ResourceScope : int
  {
    /// <summary>ネットワークリソースへの現在の接続。</summary>
    Connected = 1,
    /// <summary>すべてのネットワークリソース。</summary>
    GlobalNetwork = 2,
    Remembered = 3,
    Recent = 4,
    /// <summary>ユーザーの現在および既定のネットワークコンテキストに関連付けられているネットワークリソース。</summary>
    Context = 5,
  };

  /// <summary>
  /// リソースの種類。
  /// </summary>
  private enum ResourceType : int
  {
    /// <summary>印刷リソースとディスクリソースの両方のコンテナー、または印刷またはディスク以外のリソースなど。</summary>
    Any = 0,
    /// <summary>共有ディスクボリューム。</summary>
    Disk = 1,
    /// <summary>共有プリンター。</summary>
    Print = 2,
    Reserved = 8,
  }

  /// <summary>
  /// ユーザーインターフェイスで使用する必要がある表示の種類。
  /// </summary>
  private enum ResourceDisplaytype : int
  {
    /// <summary>リソースの種類を指定しないネットワークプロバイダーによって使用されます。</summary>
    Generic = 0x0,
    /// <summary>サーバーのコレクション。</summary>
    Domain = 0x01,
    /// <summary>サーバー。</summary>
    Server = 0x02,
    /// <summary>共有ポイント。</summary>
    Share = 0x03,
    File = 0x04,
    Group = 0x05,
    /// <summary>ネットワークプロバイダー。</summary>
    Network = 0x06,
    Root = 0x07,
    Shareadmin = 0x08,
    /// <summary>ディレクトリ。</summary>
    Directory = 0x09,
    Tree = 0x0a,
    Ndscontainer = 0x0b,
  }
}

Karena menggunakan API Win32 dan WNetAddConnection2 WNetCancelConnection2 , ini hanya berfungsi di lingkungan Windows. Saya punya komentar untuk saat ini, tetapi jika Anda ingin tahu lebih banyak, silakan cari di Internet. Selain folder bersama, Anda juga dapat melakukan operasi untuk mengakses sumber daya jaringan.

Mudah digunakan, dan jika Anda menulis yang berikut ini, Anda using dapat mengakses folder bersama selama cakupan.

using (new SharedFolderAccessor($@"\\{serverName}", credentials))
{
  // この間は共有フォルダにアクセスできる
}

Namun, pada kenyataannya WNetCancelConnection2 , koneksi tidak segera terputus pada saat panggilan , sehingga using Anda dapat mengakses folder bersama bahkan setelah cakupan.

Uji kode menggunakan SharedFolderAccessor

Karena proses mengakses folder bersama tidak bergantung pada kerangka kerja, kami membuat metode umum untuk pengujian yang membaca dan menulis file. Pazor Pages dan MVC harus disebut sama.

Konten adalah proses yang menulis teks yang diteruskan ke argumen ke folder bersama, membaca file teks yang sudah ada di folder bersama, dan mengembalikan teks.

using System.Net;

public static class Util
{
  public static string ReadAndWrite(string text)
  {
    var serverName = "ServerName";
    var folderName = "SharedFolder";
    var inputFileName = "Input.txt";
    var outputFileName = "Output.txt";
    var username = "SharedUser";
    var password = "password";

    var credentials = new NetworkCredential(username, password);
    using (new SharedFolderAccessor($@"\\{serverName}", credentials))
    {
      // ファイルの書き出し
      System.IO.File.WriteAllText(Path.Combine($@"\\{serverName}\{folderName}", outputFileName), text);

      // ファイルの読み込み
      return System.IO.File.ReadAllText(Path.Combine($@"\\{serverName}\{folderName}", inputFileName));
    }
  }
}

Halaman Pisau Cukur

Di Razor Pages, kita menempatkan tombol di Index.cshtml, klik, jalankan kode pengujian, dan tampilkan hasilnya di layar. Dalam beberapa kasus, folder bersama mungkin tidak dapat diakses, sehingga terlampir dalam try-catch.

Index.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace SharedFolderAccessRazorPages.Pages
{
  public class IndexModel : PageModel
  {
    private readonly ILogger<IndexModel> _logger;
    public string Message { get; set; } = "";

    public IndexModel(ILogger<IndexModel> logger)
    {
      _logger = logger;
    }

    public void OnPost()
    {
      try
      {
        Message = Util.ReadAndWrite($"プログラムからの書き込み ({DateTime.Now})");
      }
      catch (Exception ex)
      {
        Message = ex.ToString();
      }
    }
  }
}

Indeks.cshtml

@page
@model IndexModel
@{
  ViewData["Title"] = "Home page";
}

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

@* ここから追加 *@
<form method="post">
  <button type="submit">サブミット</button>
</form>

<div>
  @Model.Message
</div>
@* ここまで追加 *@

MVC

Demikian pula, dalam kasus MVC, Index.cshtml sebuah tombol ditempatkan di , dan ketika diklik, ia memanggil kode uji folder bersama.

Pengontrol/HomeController.cs

// 省略

namespace SharedFolderAccessMvc.Controllers
{
  public class HomeController : Controller
  {
    // 省略

    public IActionResult Index()
    {
      return View();
    }

    // ここから追加
    [HttpPost]
    public IActionResult Index(string dummy)
    {
      try
      {
        ViewData["Message"] = Util.ReadAndWrite($"プログラムからの書き込み ({DateTime.Now})");
      }
      catch (Exception ex)
      {
        ViewData["Message"] = ex.ToString();
      }
      return View();
    }
    // ここまで追加

    public IActionResult Privacy()
    {
      return View();
    }

    // 省略
  }
}

Indeks.cshtml

@{
  ViewData["Title"] = "Home Page";
}

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

@* ここから追加 *@
<form method="post">
  <button type="submit">サブミット</button>
</form>

<div>
  @ViewData["Message"]
</div>
@* ここまで追加 *@

Konfirmasi operasi

Debug dan verifikasi bahwa Anda berhasil mengakses folder bersama.

Membangun Server Aplikasi

Karena kami telah mengkonfirmasi bahwa folder bersama dapat diakses dengan menjalankan program, langkah selanjutnya tidak diperlukan. Jika Anda ingin memeriksa operasi di IIS server, Anda dapat melakukannya dengan mengikuti langkah-langkah di bawah ini.

Dari sini, ini adalah suplemen, jadi saya tidak akan menjelaskannya terlalu detail, tetapi terutama akan menjelaskan gambarnya.

Menginstal IIS

Instal secara default dari Manajer Server. Saya tidak akan membahas detail prosedurnya.

Tidak diperlukan fitur tambahan.

Tidak ada layanan IIS tambahan yang diperlukan saat ini.

ASP.NET Instalasi Paket Hosting Runtime Inti

Karena kita menggunakan ASP.NET Core 8, kita perlu menginstal runtime yang sesuai. Unduh dari URL berikut:

Untuk menjalankan ASP.NET Core di IIS, Anda memerlukan sesuatu yang disebut "Hosting Bundle". Unduh "Paket Hosting" dari ASP.NET Core Runtime.

Setelah diunduh, jalankan di server.

Ikuti wizard untuk menginstalnya.

Publikasikan program Anda

Output program yang ingin Anda sebarkan ke IIS sebagai file dari Visual Studio.

Ubah untuk Windows.

Publikasikan setelah selesai.

Jika Anda mengklik lokasi target, Anda dapat membuka folder tempat file yang diterbitkan berada.

Anda tidak harus membawa semuanya, tetapi jika Anda tidak yakin, Anda dapat mengambil semuanya untuk saat ini. Pada titik ini, yang perlu Anda lakukan adalah memastikan bahwa file tersebut ada.

Membuat dan Menyebarkan Aplikasi Web

Dari Alat administratif Windows, buka Manajer Layanan Informasi Internet (IIS).

Kita akan membuat situs, namun kali ini kita akan menggunakan "Default Web Site" yang sudah ada sejak awal.

Dengan situs Web default dipilih, klik Explorer untuk membuka folder. Salin program yang diterbitkan di sini. Anda dapat menghapus file asli.

Buka halaman dari tautan IIS dan lihat apakah layar muncul. Anda dapat membuka browser web terlebih dahulu dan memasukkan URL secara langsung.

Konfirmasi operasi

Klik tombol untuk memverifikasi bahwa itu berfungsi tanpa masalah. Di atas, itu diakses dari dalam server web, tetapi karena ini adalah server web, seharusnya dimungkinkan untuk mengoperasikannya dari PC lain.