Accesso a cartelle condivise su altri server da un'applicazione ASP.NET Core (versione Network Connected Program)

Pagina aggiornata :
Data di creazione della pagina :

Ambiente di verifica del funzionamento

Visual Studio
  • Visual Studio 2022
ASP.NET Core
  • 8 (Pagine Razor, MVC)
Windows Server
  • 2022 (ASP.NET requisiti di sistema principali)
  • 2019 (server di distribuzione cartelle condivise)
IIS (Sistema Scientifico Italiano
  • 10.0

Ambiente operativo

Non l'abbiamo testato in tutti i casi, ma dovrebbe funzionare generalmente nelle seguenti condizioni:

Visual Studio
  • Tutto ciò che può sviluppare un progetto ASP.NET Core
ASP.NET Core
  • Qualsiasi versione (MVC, Razor Pages, API)
Windows Server
  • Windows Server 2008 o versione successiva
IIS (Sistema Scientifico Italiano
  • 7.0 o versioni successive

precondizione

  • ASP.NET Le applicazioni principali sono destinate all'esecuzione in IIS.
  • Poiché usa le API di Windows per l'autenticazione, non funziona su sistemi non Windows.

ambiente

Viene verificato nel seguente ambiente.

Scopo dell'utilizzo di PC e server
Windows 11 (locale) Un ambiente per lo sviluppo di programmi.
SV2022Test Un ambiente che esegue IIS e ASP.NET Core. Accedi alla cartella condivisa SV2019Test da qui
SV2019Test Server con cartelle condivise

Inoltre, le varie impostazioni sono le seguenti.

Valore del nome del parametro
Accedi al nome utente Utente condiviso
Nome cartella condivisa Cartella condivisa

Creazione di un server di cartelle condivise

Creare un utente

Creare un utente per accedere alla cartella comune. In questo caso, creeremo un account locale, ma se hai a che fare con server e account in un dominio come Active Directory, puoi utilizzare anche quello.

Il processo di creazione di un utente esula dallo scopo di questi suggerimenti, quindi non entreremo troppo nei dettagli.

SharedUser In questo caso, lo creeremo con il nome . Poiché l'utente non utilizza lo schermo né modifica le impostazioni, la password non può essere modificata.

Se lasci l'impostazione predefinita, puoi accedere con questo utente con Desktop remoto, ecc., quindi rimuovi dal gruppo Users .

Creazione di una cartella condivisa

Non importa dove lo crei. Ciò è dovuto al fatto che gli altri server non si preoccupano della posizione della cartella fisica. In questo caso, creeremo una cartella denominata direttamente sotto SharedFolder l'unità C e la condivideremo.

Aprire le proprietà e configurare le impostazioni di condivisione.

Il nome della cartella condivisa deve SharedFolder essere . Questo nome sarà visibile agli altri server. Aggiungi SharedUser le autorizzazioni.

Everyone Eliminare il file .

Confermare con l'autorizzazione "Modifica".

Poiché abbiamo aggiunto solo autorizzazioni a cui è possibile accedere dall'esterno, lo imposteremo internamente SharedUser in modo che possa funzionare in questa cartella.

Confermare con l'autorizzazione "Modifica".

Creare un file per controllare l'operazione. In questo programma, la codifica viene elaborata in UFT-8, quindi salvala in UTF-8.

Va bene se è possibile accedere a Esplora risorse da \\<サーバー名>\ un altro PC, accedereSharedUser con e visualizzare il file.

Creare un programma per leggere e scrivere file da una cartella condivisa da un'applicazione ASP.NET Core

L'operazione Mr./Ms. consiste nel fare clic sul pulsante.

  • Caricare i file in una cartella condivisa e visualizzarli sullo schermo
  • Scrivere un nuovo file in una cartella condivisa

processo.

Razor Pages e il codice MVC sono esempi di questo, ma il programma che accede alla cartella condivisa è lo stesso per entrambi. Lo stesso vale per le API Web. Semmai, dovrebbe funzionare anche nel programma client.

Processo che si connette a una rete per la durata di un processo specifico

Creare il codice seguente in un punto qualsiasi del progetto. Il nome della classe è SharedFolderAccessor , ma il nome è arbitrario. SharedFolderAccessor È possibile accedere alla cartella condivisa fino a quando non si crea un'istanza Dispose di . using Consente di specificare il periodo di tempo durante il quale è possibile accedere all'accesso in un ambito esplicito.

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

Poiché utilizza le API Win32 e WNetAddConnection2 WNetCancelConnection2 , funziona solo in ambiente Windows. Ho un commento per il momento, ma se volete saperne di più, cercatelo su Internet. Oltre alle cartelle condivise, è anche possibile eseguire operazioni per accedere alle risorse di rete.

È facile da usare e, se si scrive quanto segue, è possibile using accedere alla cartella condivisa durante l'ambito.

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

Tuttavia, in realtà WNetCancelConnection2 , la connessione non viene immediatamente disconnessa al momento della chiamata, quindi using è possibile accedere alla cartella condivisa anche dopo l'ambito.

Testare il codice usando SharedFolderAccessor

Poiché il processo di accesso alla cartella condivisa non dipende dal framework, viene creato un metodo comune per i test che legge e scrive i file. Pazor Pages e MVC dovrebbero essere chiamati allo stesso modo.

Il contenuto è un processo che scrive il testo passato all'argomento nella cartella condivisa, legge il file di testo già presente nella cartella condivisa e restituisce il testo.

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

Pagine Razor

In Razor Pages si inserisce un pulsante in Index.cshtml, si fa clic su di esso, si esegue il codice di test e si visualizzano i risultati sullo schermo. In alcuni casi, la cartella condivisa potrebbe non essere accessibile, quindi è racchiusa in un 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();
      }
    }
  }
}

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

Analogamente, nel caso di MVC, Index.cshtml un pulsante viene inserito in , e quando viene selezionato, chiama il codice di test della cartella condivisa.

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

    // 省略
  }
}

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

Conferma dell'operazione

Eseguire il debug e verificare che sia possibile accedere correttamente alla cartella condivisa.

Creazione di un server applicazioni

Poiché abbiamo confermato che è possibile accedere alla cartella condivisa eseguendo il programma, il passaggio successivo non è necessario. Se si desidera controllare il funzionamento sul server IIS, è possibile farlo seguendo i passaggi seguenti.

Da qui, è un supplemento, quindi non lo spiegherò troppo in dettaglio, ma spiegherò principalmente l'immagine.

Installazione di IIS

Installarlo per impostazione predefinita da Server Manager. Non entrerò nei dettagli della procedura.

Non sono necessarie funzionalità aggiuntive.

Al momento non sono necessari servizi IIS aggiuntivi.

ASP.NET Installazione del bundle di hosting runtime principale

Poiché stiamo usando ASP.NET Core 8, dobbiamo installare il runtime di conseguenza. Scaricalo dal seguente URL:

Per eseguire ASP.NET Core in IIS, è necessario qualcosa chiamato "Hosting Bundle". Scaricare l'"Hosting Bundle" dal ASP.NET Core Runtime.

Una volta scaricato, eseguilo sul server.

Segui la procedura guidata per installarlo.

Pubblica il tuo programma

Restituire il programma che si desidera distribuire in IIS come file da Visual Studio.

Modificalo per Windows.

Pubblica quando hai finito.

Se si fa clic sulla posizione di destinazione, è possibile aprire la cartella in cui si trova il file pubblicato.

Non devi portarli tutti, ma se non sei sicuro, puoi prenderli tutti per ora. A questo punto, tutto ciò che devi fare è assicurarti che il file esista.

Creazione e distribuzione di applicazioni Web

Da Strumenti di amministrazione di Windows, aprire Gestione Internet Information Services (IIS).

Creeremo un sito, ma questa volta utilizzeremo il "Sito Web predefinito" che è presente fin dall'inizio.

Con l'opzione Sito Web predefinito selezionata, fare clic su Esplora risorse per aprire la cartella. Copia qui il programma pubblicato. È possibile eliminare il file originale.

Aprire la pagina dal collegamento IIS e verificare se viene visualizzata la schermata. È possibile aprire prima un browser Web e immettere direttamente l'URL.

Conferma dell'operazione

Fare clic sul pulsante per verificare che funzioni senza problemi. In quanto sopra, è possibile accedervi dall'interno del server Web, ma poiché si tratta di un server Web, dovrebbe essere possibile gestirlo da altri PC.