Toegang tot gedeelde mappen op andere servers vanuit een ASP.NET Core-toepassing (versie van het Network Connected Program)

Pagina bijgewerkt :
Aanmaakdatum van pagina :

Omgeving voor bedrijfsverificatie

Visual Studio
  • Visual Studio 2022
ASP.NET kern
  • 8 (Razor Pagina's, MVC)
Windows Server
  • 2022 (ASP.NET kernsysteemvereisten)
  • 2019 (implementatieserver voor gedeelde mappen)
IIS (Engelstalig)
  • 10.0

Werkomgeving

We hebben het niet in alle gevallen getest, maar het zou over het algemeen moeten werken onder de volgende omstandigheden:

Visual Studio
  • Alles wat een ASP.NET Core-project kan ontwikkelen
ASP.NET kern
  • Elke versie (MVC, Razor Pages, API)
Windows Server
  • Windows Server 2008 of hoger
IIS (Engelstalig)
  • 7.0 of hoger

voorwaarde

  • ASP.NET Core-toepassingen zijn bedoeld om op IIS te worden uitgevoerd.
  • Omdat het Windows-API's gebruikt voor authenticatie, werkt het niet op niet-Windows.

milieu

Het wordt geverifieerd in de volgende omgeving.

Doel van het gebruik van pc's en servers
Windows 11 (lokaal) Een omgeving voor het ontwikkelen van programma's.
SV2022Test Een omgeving waarin IIS en ASP.NET Core worden uitgevoerd. Open hier de gedeelde map SV2019Test
SV2019Test Servers met gedeelde mappen

Daarnaast zijn de verschillende instellingen als volgt.

Parameternaam Waarde
Toegang tot gebruikersnaam Gedeelde gebruiker
Naam van gedeelde map Gedeelde map

Een server voor gedeelde mappen bouwen

Maak een gebruiker aan

Maak een gebruiker aan om toegang te krijgen tot de gemeenschappelijke map. In dit geval maken we een lokaal account aan, maar als je te maken hebt met servers en accounts in een domein zoals Active Directory, kun je daar ook gebruik van maken.

Het proces van het aanmaken van een gebruiker valt buiten het bestek van deze tips, dus we zullen niet te veel in detail treden.

SharedUser In dit geval maken we het met de naam . Aangezien deze gebruiker het scherm niet bedient of de instellingen wijzigt, kan het wachtwoord niet worden gewijzigd.

Als u de standaard verlaat, kunt u met deze gebruiker inloggen met Remote Desktop, enz., dus verwijder uit de groep Users .

Een gedeelde map maken

Het maakt niet uit waar je het maakt. Dit komt omdat andere servers zich niet bekommeren om de locatie van de fysieke map. In dit geval maken we een map met de naam direct onder SharedFolder de C-schijf en delen deze.

Open de eigenschappen en configureer de instellingen voor delen.

De naam van de gedeelde map moet SharedFolder zijn: . Deze naam is zichtbaar voor andere servers. Voeg de machtigingen toe SharedUser .

Everyone Verwijder de bestaande .

Bevestig met de machtiging "Wijzigen".

Aangezien we alleen machtigingen hebben toegevoegd die van buitenaf toegankelijk zijn, zullen we deze intern SharedUser zo instellen dat kan in deze map werken.

Bevestig met de machtiging "Wijzigen".

Maak een bestand om de bewerking te controleren. In dit programma wordt de codering verwerkt in UFT-8, dus sla deze op in UTF-8.

Het is OK als u in Verkenner vanaf \\<サーバー名>\ een andere pc toegang hebt, inlogtSharedUser met en het bestand kunt bekijken.

Een programma maken voor het lezen en schrijven van bestanden uit een gedeelde map vanuit een ASP.NET Core-toepassing

De bewerking Mr./Ms. is om op de knop te klikken.

  • Laad bestanden in een gedeelde map en geef ze weer op het scherm
  • Een nieuw bestand naar een gedeelde map schrijven

proces.

Razor Pages en MVC-code zijn hier voorbeelden van, maar het programma dat toegang heeft tot de gedeelde map is voor beide hetzelfde. Hetzelfde geldt voor web-API's. Als er iets is, zou het ook in het clientprogramma moeten werken.

Een proces dat verbinding maakt met een netwerk voor de duur van een specifiek proces

Maak de volgende code overal in uw project. De naam van de klasse is SharedFolderAccessor , maar de naam is willekeurig. SharedFolderAccessor Je hebt toegang tot de gedeelde map totdat je een Dispose exemplaar van maakt. using Hiermee kunt u de periode opgeven waarin toegang kan worden verkregen in een expliciet bereik.

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

Omdat het de Win32-API's gebruikt en WNetAddConnection2 WNetCancelConnection2 , werkt het alleen in de Windows-omgeving. Ik heb voorlopig een opmerking, maar als je meer wilt weten, zoek het dan op internet op. Naast gedeelde mappen kunt u ook bewerkingen uitvoeren om toegang te krijgen tot netwerkbronnen.

Het is gemakkelijk te gebruiken en als u het volgende schrijft, hebt u using tijdens het bereik toegang tot de gedeelde map.

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

In werkelijkheid WNetCancelConnection2 wordt de verbinding echter niet onmiddellijk verbroken op het moment van bellen , zodat using u zelfs na het bereik toegang hebt tot de gedeelde map.

Code testen met SharedFolderAccessor

Aangezien het proces van toegang tot de gedeelde map niet afhankelijk is van het framework, creëren we een gemeenschappelijke testmethode die bestanden leest en schrijft. Pazor Pages en MVC moeten hetzelfde worden genoemd.

De inhoud is een proces dat de tekst die aan het argument is doorgegeven, naar de gedeelde map schrijft, het tekstbestand leest dat al in de gedeelde map staat en de tekst retourneert.

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

Razor Pagina's

In Razor Pages plaatsen we een knop in Index.cshtml, klikken erop, voeren de testcode uit en geven de resultaten weer op het scherm. In sommige gevallen is de gedeelde map mogelijk niet toegankelijk, dus wordt deze ingesloten in een 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();
      }
    }
  }
}

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

Op dezelfde manier wordt in het geval van MVC Index.cshtml een knop geplaatst in , en wanneer erop wordt geklikt, wordt de testcode van de gedeelde map aangeroepen.

Controllers/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>
@* ここまで追加 *@

Bevestiging van de werking

Fouten opsporen en controleren of u met succes toegang hebt tot de gedeelde map.

Een applicatieserver bouwen

Aangezien we hebben bevestigd dat de gedeelde map toegankelijk is door het programma uit te voeren, is de volgende stap niet nodig. Als u de bewerking op de IIS-server wilt controleren, kunt u dit doen door de onderstaande stappen te volgen.

Vanaf hier is het een aanvulling, dus ik zal het niet te gedetailleerd uitleggen, maar vooral de afbeelding uitleggen.

IIS installeren

Installeer het standaard vanuit de Server Manager. Ik zal niet ingaan op de details van de procedure.

Er zijn geen extra functies vereist.

Er zijn op dit moment geen aanvullende IIS-services vereist.

ASP.NET Core Runtime Hosting Bundle Installatie

Aangezien we ASP.NET Core 8 gebruiken, moeten we de runtime dienovereenkomstig installeren. Download het van de volgende URL:

Om ASP.NET Core in IIS te kunnen draaien, heb je iets nodig dat "Hosting Bundle" wordt genoemd. Download de "Hosting Bundle" van de ASP.NET Core Runtime.

Eenmaal gedownload, voert u het uit op de server.

Volg de wizard om het te installeren.

Publiceer uw programma

Voer het programma dat u wilt implementeren in IIS uit als een bestand vanuit Visual Studio.

Wijzig het voor Windows.

Publiceer als je klaar bent.

Als u op de doellocatie klikt, kunt u de map openen waarin het gepubliceerde bestand zich bevindt.

Je hoeft ze niet allemaal mee te nemen, maar als je het niet zeker weet, kun je ze voorlopig allemaal meenemen. Op dit punt hoeft u er alleen maar voor te zorgen dat het bestand bestaat.

Webapplicaties maken en implementeren

Open IIS-beheer (Internet Information Services) in Windows Systeembeheer.

We zullen een site maken, maar deze keer zullen we de "Standaardwebsite" gebruiken die er vanaf het begin is.

Selecteer Standaardwebsite en klik op Verkenner om de map te openen. Kopieer het gepubliceerde programma hier. U kunt het oorspronkelijke bestand verwijderen.

Open de pagina via de IIS-koppeling en kijk of het scherm wordt weergegeven. U kunt eerst een webbrowser openen en de URL rechtstreeks invoeren.

Bevestiging van de werking

Klik op de knop om te controleren of het zonder problemen werkt. In het bovenstaande is het toegankelijk vanuit de webserver, maar aangezien het een webserver is, zou het mogelijk moeten zijn om het vanaf andere pc's te bedienen.