Accesarea folderelor partajate de pe alte servere dintr-o aplicație ASP.NET Core (versiunea Network Connected Program)

Pagina actualizată :
Data creării paginii :

Mediul de verificare a funcționării

Visual Studio
  • Visual Studio 2022
ASP.NET Nucleul
  • 8 (Pagini de ras, MVC)
Windows Server
  • 2022 (ASP.NET cerințe de bază ale sistemului)
  • 2019 (Server de implementare foldere partajate)
IIS
  • 10.0

Mediu de operare

Nu l-am testat în toate cazurile, dar ar trebui să funcționeze în general în următoarele condiții:

Visual Studio
  • Orice poate dezvolta un proiect ASP.NET Core
ASP.NET Nucleul
  • Orice versiune (MVC, Razor Pages, API)
Windows Server
  • Windows Server 2008 sau o versiune ulterioară
IIS
  • 7.0 sau o versiune ulterioară

Condiție prealabilă

  • ASP.NET aplicații de bază sunt destinate să se execute pe IIS.
  • Deoarece utilizează API-uri Windows pentru autentificare, nu funcționează pe non-Windows.

mediu

Se verifică în următorul mediu.

Scopul utilizării PC-urilor și serverelor
Windows 11 (local) Un mediu pentru dezvoltarea programelor.
SV2022Test Un mediu care execută IIS și ASP.NET Core. Accesați folderul partajat SV2019Test de aici
SV2019Test Servere cu foldere partajate

În plus, diferitele setări sunt după cum urmează.

Valoarea numelui parametrului
Nume utilizator Access Utilizator partajat
Nume folder partajat SharedFolder

Construirea unui server de foldere partajate

Crearea unui utilizator

Creați un utilizator pentru a accesa folderul comun. În acest caz, vom crea un cont local, dar dacă aveți de-a face cu servere și conturi într-un domeniu precum Active Directory, îl puteți folosi și pe acesta.

Procesul de creare a unui utilizator depășește domeniul de aplicare al acestor sfaturi, așa că nu vom intra în prea multe detalii.

SharedUser În acest caz, îl vom crea cu numele . Deoarece acest utilizator nu operează ecranul sau nu modifică setările, parola nu poate fi modificată.

Dacă lăsați implicit, vă puteți conecta cu acest utilizator cu Desktop la distanță etc., așa că vă rugăm să eliminați din grup Users .

Crearea unui dosar partajat

Nu contează unde îl creați. Acest lucru se datorează faptului că altor servere nu le pasă de locația folderului fizic. În acest caz, vom crea un folder numit direct sub SharedFolder unitatea C și îl vom partaja.

Deschideți proprietățile și configurați setările de partajare.

Numele folderului partajat ar trebui să SharedFolder fie . Acest nume va fi vizibil pentru alte servere. Adăugați SharedUser permisiunile.

Everyone Ștergeți fișierul . existent

Confirmați cu permisiunea "Modificare".

Deoarece am adăugat doar permisiuni care pot fi accesate din exterior, îl vom seta intern SharedUser , astfel încât să poată funcționa în acest folder.

Confirmați cu permisiunea "Modificare".

Creați un fișier pentru a verifica operațiunea. În acest program, codificarea este procesată în UFT-8, așa că vă rugăm să o salvați în UTF-8.

Este OK dacă puteți accesa Explorer de pe \\<サーバー名>\ un alt PC, vă puteți conectaSharedUser cu , și puteți vizualiza fișierul.

Crearea unui program pentru citirea și scrierea fișierelor dintr-un folder partajat dintr-o aplicație ASP.NET Core

Operația Mr./Ms. este să faceți clic pe buton.

  • Încărcați fișierele într-un dosar partajat și afișați-le pe ecran
  • Scrierea unui fișier nou într-un dosar partajat

proces.

Razor Pages și codul MVC sunt exemple în acest sens, dar programul care accesează folderul partajat este același pentru ambele. Același lucru este valabil și pentru API-urile web. Dacă este ceva, ar trebui să funcționeze și în programul client.

Un proces care se conectează la o rețea pe durata unui anumit proces

Creați următorul cod oriunde în proiect. Numele clasei este SharedFolderAccessor , dar numele este arbitrar. SharedFolderAccessor Puteți accesa folderul partajat până când creați o Dispose instanță de . using vă permite să specificați perioada de timp în care accesul poate fi accesat într-un domeniu de aplicare explicit.

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,
  }
}

Deoarece folosește API-urile Win32 și WNetAddConnection2 WNetCancelConnection2 , funcționează numai în mediul Windows. Am un comentariu pentru moment, dar dacă doriți să aflați mai multe, vă rugăm să-l căutați pe Internet. În plus față de folderele partajate, puteți efectua și operațiuni pentru a accesa resursele de rețea.

Este ușor de utilizat și, dacă scrieți următoarele, puteți using accesa folderul partajat în timpul domeniului de aplicare.

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

Cu toate acestea, în realitate WNetCancelConnection2 , conexiunea nu este deconectată imediat în momentul apelării , astfel încât using să puteți accesa folderul partajat chiar și după domeniul de aplicare.

Cod de testare folosind SharedFolderAccessor

Deoarece procesul de accesare a folderului partajat nu depinde de cadru, creăm o metodă comună de testare care citește și scrie fișiere. Pazor Pages și MVC ar trebui să fie numite la fel.

Conținutul este un proces care scrie textul transmis argumentului în folderul partajat, citește fișierul text aflat deja în folderul partajat și returnează textul.

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));
    }
  }
}

Pagini de ras

În Razor Pages, plasăm un buton în Index.cshtml, facem clic pe el, rulăm codul de test și afișăm rezultatele pe ecran. În unele cazuri, este posibil ca folderul partajat să nu fie accesibil, deci este inclus într-o captură de încercare.

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();
      }
    }
  }
}

Index.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

În mod similar, în cazul MVC, Index.cshtml un buton este plasat în , iar când faceți clic, apelează codul de test al folderului partajat.

Controlere/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();
    }

    // 省略
  }
}

Index.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>
@* ここまで追加 *@

Confirmarea funcționării

Depanați și verificați dacă puteți accesa cu succes folderul partajat.

Construirea unui server de aplicații

Deoarece am confirmat că folderul partajat poate fi accesat rulând programul, următorul pas nu este necesar. Dacă doriți să verificați operațiunea pe serverul IIS, o puteți face urmând pașii de mai jos.

De aici, este un supliment, așa că nu îl voi explica prea detaliat, ci voi explica în principal imaginea.

Instalarea IIS

Instalați-l implicit din Server Manager. Nu voi intra în detaliile procedurii.

Nu sunt necesare caracteristici suplimentare.

Nu sunt necesare servicii IIS suplimentare în acest moment.

ASP.NET Core Runtime Hosting Bundle Instalare

Deoarece folosim ASP.NET Core 8, trebuie să instalăm runtime-ul în consecință. Descărcați-l de la următoarea adresă URL:

Pentru a rula ASP.NET Core în IIS, aveți nevoie de ceva numit "Pachet de găzduire". Descărcați "Pachetul de găzduire" din ASP.NET Core Runtime.

Odată descărcat, rulați-l pe server.

Urmați expertul pentru a-l instala.

Publicați-vă programul

Ieșire programul pe care doriți să implementați IIS ca fișier din Visual Studio.

Modificați-l pentru Windows.

Publicați când ați terminat.

Dacă faceți clic pe locația țintă, puteți deschide folderul în care se află fișierul publicat.

Nu trebuie să le aduceți pe toate, dar dacă nu sunteți sigur, le puteți lua pe toate pentru moment. În acest moment, tot ce trebuie să faceți este să vă asigurați că fișierul există.

Crearea și implementarea aplicațiilor web

Din Instrumente de administrare Windows, deschideți Internet Information Services (IIS) Manager.

Vom crea un site, dar de data aceasta vom folosi "Site-ul Web implicit" care este acolo de la început.

Cu opțiunea Site Web implicit selectată, faceți clic pe Explorer pentru a deschide folderul. Copiați programul publicat aici. Puteți șterge fișierul original.

Deschideți pagina din linkul IIS și vedeți dacă apare ecranul. Puteți deschide mai întâi un browser web și introduceți direct adresa URL.

Confirmarea funcționării

Faceți clic pe buton pentru a verifica dacă funcționează fără probleme. În cele de mai sus, este accesat din interiorul serverului web, dar, deoarece este un server web, ar trebui să fie posibil să îl operați de pe alte PC-uri.