- PVSM.RU - https://www.pvsm.ru -
Эта статья является переводом справочного руководства по переносу приложений из ASP.NET в ASP.NET Core 2.0. Ссылка на оригинал [1]
В силу некоторых причин, у нас возникла необходимость перейти с ASP.NET в ASP.NET Core 1.1., о том, как это у нас получилось, читайте тут [2].
• .NET Core 2.0.0 SDK или более поздняя версия.
Для работы с ASP.NET Core 2.0 проектом, разработчику предстоит сделать выбор – использовать .NET Core, .NET Framework или использовать сразу оба варианта. В качестве дополнительной информации можно использовать руководство Choosing between .NET Core and .NET Framework for server apps [3] (вкратце можно сказать что .NET core является кроссплатформенной библиотекой, в отличие от .NET Framework) для того чтобы понять, какой Фреймворк для вас окажется наиболее предпочтительным.
После выбора нужного Фреймворка в проекте необходимо указать ссылки на пакеты NuGet.
Использование .NET Core позволяет устранить многочисленные явные ссылки на пакеты, благодаря объединенному пакету [4] (мета пакету) ASP.NET Core 2.0. Так выглядит установка мета пакета Microsoft.AspNetCore.All
в проект:
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
Структура файла проекта .csproj была упрощена в ASP.NET Core. Вот некоторые значительные изменения:
• Явное указание файлов является необязательным для добавления их в проект. Таким образом, уменьшается риск конфликтов в процессе слияния XML, если над проектом работает большая команда
• Больше нет GUID ссылок на другие проекты, что улучшает читаемость
• Файл можно редактировать без его выгрузки из Visual Studio:
Точкой входа для ASP.NET приложений является Global.asax файл. Такие задачи, как конфигурация маршрута и регистрация фильтров и областей, обрабатываются в файле Global.asax
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Этот подход тесно связывает приложение и сервер, на котором развернуто приложение. Для уменьшения связности был представлен OWIN [5]как средство, обеспечивающее более правильный путь совместного использования нескольких фреймворков вместе.
OWIN позволяет добавить в конвейер запроса только необходимые модули. Среда выполнения использует Startup [6] для конфигурации сервисов и конвейера запросов.
Startup
регистрирует набор промежуточных сервисов (middleware) вместе с приложением. Для каждого запроса приложение вызывает поочередно каждый из набора промежуточных сервисов, имеющих указатель на первый элемент связанного списка обработчиков.
Каждый компонент промежуточного сервиса может добавить один или несколько обработчиков в конвейер обработки запросов. Это происходит с помощью возврата ссылки на обработчик, который находится в начале списка.
И обработчик, закончив свою работу, вызывает следующий обработчик из очереди.
В ASP.NET Core, точкой входа в приложении является класс Startup
, с помощью которого мы нивелируем зависимость от Global.asax.
Если изначально был выбран .NET Framework то при помощи OWIN мы можем сконфигурировать конвейер запросов как в следующем примере:
using Owin;
using System.Web.Http;
namespace WebApi
{
// Заметка: По умолчанию все запросы проходят через этот конвейер OWIN. В качестве альтернативы вы можете отключить это, добавив appSetting owin: AutomaticAppStartup со значением «false».
// При отключении вы все равно можете использовать приложения OWIN для прослушивания определенных маршрутов, добавив маршруты в файл global.asax с помощью MapOwinPath или расширений MapOwinRoute на RouteTable.Routes
public class Startup
{
// Вызывается один раз при запуске для настройки вашего приложения.
public void Configuration(IAppBuilder builder)
{
HttpConfiguration config = new HttpConfiguration();
//Здесь настраиваем маршруты по умолчанию,
config.Routes.MapHttpRoute("Default", "{controller}/{customerID}", new { controller = "Customer", customerID = RouteParameter.Optional });
//Указываем на то что в качестве файла конфигурации мы будем использовать xml вместо json
config.Formatters.XmlFormatter.UseXmlSerializer = true;
config.Formatters.Remove(config.Formatters.JsonFormatter);
// config.Formatters.JsonFormatter.UseDataContractJsonSerializer = true;
builder.UseWebApi(config);
}
}
}
Также при необходимости здесь мы можем добавить другие промежуточные сервисы в этот конвейер (загрузка сервисов, настройки конфигурации, статические файлы и т.д.).
Что касается версии фреймворка .NET Core, то здесь используется подобный подход, но не без использования OWIN для определения точки входа. В качестве альтернативы используется метод Main
в Program.cs (по аналогии с консольными приложениям), где и происходит загрузка Startup
:
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
namespace WebApplication2
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}
Startup должен включать метод Configure. В Configure определяется, какие сервисы будут использоваться в конвейере запроса. В следующем примере (взятом из стандартного шаблона web-сайта), несколько методов расширения используются для настройки конвейера с поддержкой:
• BrowserLink
• Error pages
• Static files
• ASP.NET Core MVC
• Identity
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentity();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
В итоге мы имеем разделение среды выполнения и приложения, что дает нам возможность осуществить переход на другую платформу в будущем.
Заметка: Для более глубокого понимания ASP.NET Core Startup и Middleware, можно изучить Startup in ASP.NET Core [6]
ASP.NET поддерживает сохранение настроек. Например, это настройки, которые используются средой выполнения, где было развернуто приложение. Сам подход заключался в том, что для хранение пользовательских key-value пар использовалась секция <appSettings>
в файле Web.config:
<appSettings>
<add key="UserName" value="User" />
<add key="Password" value="Password" />
</appSettings>
Приложение получало доступ к этим настройкам с помощью коллекции ConfigurationManager.AppSettings из пространства имен System.Configuration :
string userName = System.Web.Configuration.ConfigurationManager.AppSettings["UserName"];
string password = System.Web.Configuration.ConfigurationManager.AppSettings["Password"];
В ASP.NET Core мы можем хранить конфигурационные данные для приложения в любом файле и загружать их с помощью сервисов на начальном этапе загрузки.
Файл, используемый по умолчанию в новом шаблонном проекте appsettings.json:
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
// Здесь можно указать настраиваемые параметры конфигурации. Поскольку это JSON, все представлено в виде пар символов: значение
// Как назвать раздел, определяет сам разработчик
"AppConfiguration": {
"UserName": "UserName",
"Password": "Password"
}
}
Загрузка этого файла в экземпляр IConfiguration
для приложения происходит в Startup.cs:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
А вот так приложение использует Configuration для получения этих настроек:
string userName = Configuration.GetSection("AppConfiguration")["UserName"];
string password = Configuration.GetSection("AppConfiguration")["Password"];
Есть другие способы, основанные на данном подходе, которые позволяют сделать процесс более надежным, например Dependency Injection (DI).
Подход DI обеспечивает доступ к строго типизированному набору объектов конфигурации.
// Предположим, AppConfiguration - это класс, который представляет строго типизированную версию раздела AppConfiguration
services.Configure<AppConfiguration>(Configuration.GetSection("AppConfiguration"));
Заметка: Для более глубокого понимания конфигураций ASP.NET Core, можно ознакомится с Configuration in ASP.NET Core [7].
Важной целью при создании больших масштабируемых приложений является ослабление связи между компонентами и сервисами. Dependency Injection [8]– распространенная техника для решения данной проблемы и ее реализация является встроенным в ASP.NET Core компонентом.
В приложениях ASP.NET разработчики использовали сторонние библиотеки для внедрения Injection Dependency. Примером такой библиотеки является Unity [9].
Пример настройки Dependency Injection с Unity — это реализация UnityContainer
, обернутая в IDependencyResolver
:
using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
container.Dispose();
}
}
Создаем экземпляр своего UnityContainer
, регистрируем свою службу и устанавливаем разрешение зависимости для HttpConfiguration
в новый экземпляр UnityResolver
для нашего контейнера:
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
// Опустим остальную часть реализации
}
Далее производим инъекцию IProductRepository
там, где это необходимо:
public class ProductsController : ApiController
{
private IProductRepository _repository;
public ProductsController(IProductRepository repository)
{
_repository = repository;
}
}
Поскольку Dependency Injection является частью ядра ASP.NET Core, мы можем добавить свой сервис в метод ConfigureServices
внутри Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
//Добавляем сервис приложения
services.AddTransient<IProductRepository, ProductRepository>();
}
И далее инъекцию репозитория можно осуществить в любом месте, как и в случае с Unity.
Заметка: Подробности можно посмотреть в Dependency Injection in ASP.NET Core [10]
Важной частью веб-разработки является возможность обслуживания статики. Самые распространенные примеры статики — это HTML, CSS, JavaScript и картинки.
Эти файлы нужно сохранять в общей папке приложения (или например в CDN) чтобы в дальнейшем они были доступны по ссылке. В ASP.NET Core был изменен подход для работы с статикой.
В ASP.NET статика хранится в разных каталогах.
А в ASP.NET Core статические файлы по умолчанию хранятся в «web root» (/ wwwroot). И доступ к этим файлам осуществляется с помощью метода расширения UseStaticFiles
из Startup.Configure:
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
}
К примеру, изображения находящееся в папке wwwroot/images будет доступно из браузера по адресу http://<app-address>/images/<imageFileName>
.
Заметка: Если был выбран .NET Framework, то дополнительно нужно будет установить NuGet пакет Microsoft.AspNetCore.StaticFiles
.
Заметка: Для более подробной ссылки на обслуживание статических файлов в ядре ASP.NET см. Introduction to working with static files in ASP.NET Core [11].
Автор: IT-компания Wellsoft
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/c-2/264349
Ссылки в тексте:
[1] Ссылка на оригинал: https://docs.microsoft.com/ru-ru/aspnet/core/migration/proper-to-2x/#storing-configurations
[2] тут: http://wellsoft.pro/article/perehod-s-aspnet-k-aspnet-core-11?utm_source=habr&utm_medium=pr&utm_campaign=zhenya
[3] Choosing between .NET Core and .NET Framework for server apps: https://docs.microsoft.com/dotnet/standard/choosing-core-framework-server
[4] объединенному пакету: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/metapackage
[5] OWIN : http://owin.org/
[6] Startup: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup
[7] Configuration in ASP.NET Core: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration
[8] Dependency Injection : https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection
[9] Unity : https://github.com/unitycontainer/unity
[10] Dependency Injection in ASP.NET Core: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection#replacing-the-default-services-container
[11] Introduction to working with static files in ASP.NET Core: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files
[12] Источник: https://habrahabr.ru/post/338298/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.