#c# #asp.net-core #blazor-server-side #static-files #fileshare
Вопрос:
Мое приложение хранит и извлекает фотоизображения из общего сетевого ресурса. Моя машина разработки-Windows 2018 под управлением Visual Studio 2019 на VMware.
Изображения отлично подходят при первом открытии приложения. Затем, примерно через 1 минуту (или около того), изображения 404.
В принципе, я пытаюсь реализовать что-то вроде классического asp.net виртуальный каталог в IIS. Это позволяет читать/записывать файлы через общий сетевой ресурс. Насколько я понимаю, это asp.net ядро разбивает виртуальные каталоги старой школы…
Я пробовал много вещей, таких как изменение расположения изображений в сети (разные физические машины). Не повезло. Я также пробовал различные реализации NetworkConnection (см. Код ниже). Nada.
Я также попытался использовать UseStaticFiles вместо UseFileServer:
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine("\\DESKTOP-QRDNRCJ\Images\Photos2")),
RequestPath = new PathString("/Photos2")
});
И, наконец, я попробовал IP-адрес вместо сетевого имени машины.
Чтобы упростить отладку для stackoverflow, я создал совершенно новое решение Blazor с одной страницей, на которой отображаются только 3 изображения. Он также выходит из строя примерно через 1 минуту.
Интересно: иногда 2 из 3 изображений визуализируются в течение некоторого времени. Но в конце концов все 3 идут по 404.
Кроме того, иногда, когда я сохраняю файл по сети (используя мое полное приложение, которого нет ниже), оно сохраняет имя файла, но размер файла = 0 к.
Это расстраивает, потому что приложение вроде как работает в течение короткого времени. Поэтому я не допускаю опечатки или другой ошибки (насколько мне известно).
Вот несколько рекомендаций, которые помогли мне начать:
https://www.c-sharpcorner.com/article/virtual-directory-inside-of-asp-net-core-app-in-iis/
И вот мой код:
Простая страница с 3 изображениями:
@page "/index"
@page "/"
<img src="Photos2/birthday.gif" /><img src="Photos2/bo.jpg" /><img src="Photos2/dotnet.png" />
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebApplication2.Data;
using System.Net;
using Microsoft.Extensions.FileProviders;
using System.IO;
using Microsoft.AspNetCore.Http;
namespace WebApplication2
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
var sourceCredentials = new NetworkCredential { Domain = "192.168.1.162", UserName = "ImageManager", Password = "qwer1234)" };
using (new NetworkConnection("\\192.168.1.162\Images\Photos2", sourceCredentials))
{
app.UseFileServer(new FileServerOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine("\\192.168.1.162\Images\Photos2")),
RequestPath = new PathString("/Photos2"),
EnableDirectoryBrowsing = true
});
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}
Класс для подключения к сети.
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Net;
public class NetworkConnection : IDisposable
{
readonly string _networkName;
public NetworkConnection(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
: string.Format(@"{0}{1}", credentials.Domain, credentials.UserName);
var result = WNetAddConnection2(
netResource,
credentials.Password,
userName,
0);
if (result != 0)
{
throw new Win32Exception(result, "Error connecting to remote share");
}
}
~NetworkConnection()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
WNetCancelConnection2(_networkName, 0, true);
}
[DllImport("mpr.dll")]
private static extern int WNetAddConnection2(NetResource netResource,
string password, string username, int flags);
[DllImport("mpr.dll")]
private static extern int WNetCancelConnection2(string name, int flags,
bool force);
[StructLayout(LayoutKind.Sequential)]
public 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;
}
public enum ResourceScope : int
{
Connected = 1,
GlobalNetwork,
Remembered,
Recent,
Context
};
public enum ResourceType : int
{
Any = 0,
Disk = 1,
Print = 2,
Reserved = 8,
}
public enum ResourceDisplaytype : int
{
Generic = 0x0,
Domain = 0x01,
Server = 0x02,
Share = 0x03,
File = 0x04,
Group = 0x05,
Network = 0x06,
Root = 0x07,
Shareadmin = 0x08,
Directory = 0x09,
Tree = 0x0a,
Ndscontainer = 0x0b
}
}
Комментарии:
1. Переход от одного пути к другому. Объединять бессмысленно
2. Да, лол, замечание принято. Теперь о моем фактическом вопросе/проблеме …
Ответ №1:
Я думаю, что решил. Публикую на случай, если кто-нибудь споткнется о что-то подобное…
Мне нужно было удалить «использование». Итак, это …
using (new NetworkConnection("\\192.168.1.162\Images\Photos2",sourceCredentials))
{
app.UseFileServer(new FileServerOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine("\\192.168.1.162\Images\Photos2")),
RequestPath = new PathString("/Photos2"),
EnableDirectoryBrowsing = true
});
}
стало это:
new NetworkConnection("\\192.168.1.162\Images\Photos2", sourceCredentials);
app.UseFileServer(new FileServerOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine("\\192.168.1.162\Images\Photos2")),
RequestPath = new PathString("/Photos2"),
EnableDirectoryBrowsing = true
});
Единственное различие заключается в том, что «использование» и скобки удалены.
Почему это работает? Я предполагаю, что объект NetworkConnection должен быть сохранен. Если я использовал «использование», это не так. Это была моя проблема, через 30-60 секунд мое сетевое соединение не работало.
Просто жаль, что я не понял это простое решение быстрее!