Asp.Net Core 2.2 to 3.1 Migration and Autofac Configuration

Asp .Net Core hayatımıza gireli epeyce bir süre oldu ve Microsoft hızlı ve emin adımlarla declare ettiği milestone'larını geliştirmeye devam etmekte. Öncelikle v1.x ardından v2.x sürümlerini kullanmıştık ve son olarak ise en güncel kararlı sürüm olan v3.x çıktı. Yakşalık 1.5 yıldır gerek kendi projelerimde gerekse iş yerinde geliştirdiğimiz bütün projelerde 3.0'dan önceki en stabil versiyon olan asp.net core 2.2 kullanıyorduk. v3.0 ve peşinden v3.1 çıkalı çok fazla olmasada artık 2.2 ile develop ettiğimiz bu projeleri v3.1'e migrate etme zamanı gelmiş oldu. v3.1'i microsoft bizlere şu makale ile duyurmuş oldu, yeniliklerle ilgili detayları bu makalede bulabilirsiniz.

Bu yazımızda mevcutta 2.2 ile geliştirilmiş olan bir WebApi projemizi v3.1'e nasıl migrate ederiz, ne gibi yenilikler var inceliyor olacağız. 

Öncelikle .net core 3.x uygulamaları geliştirebilmek için bilgisayarınızda en az Visual Studio 16.3 versiyonu ve SDK 3.x bulunmak zorunda. Bilgisayarında kurulu olmayanlar için visual studio download sayfası ve .netCore SDK için ise bu download sayfasına giderek kurulumlarını yapabilirler.

Kurulumları tamamladıktan sonra aşağıdaki gibi dotnet --info komutu ile birlikte kurulu olan sdk'leri görüntüleyebilirler ve ayrıca vs'da target framework bilgisi olarak yine 3.1 versiyonunu görebiliyor olmamız gerekir.

Proje üzerinde yapacağımız değişikliklere gelecek olursak; öncelikle kullanmakta olduğumuz projede 3rd party dependency injection tool'u olarak Autofac ve ORM tool'u olarakda Entity.Framework.Core bulunmakta. 

Solution'da yer alan Api projemize gelip Edit Project File'a tıkladığımızda aşağıdaki gibi v2.2 için ilgili bilgileri ve reference'ları görüntüleyebiliriz.

 Öncelikle yapmamız gereken ilk iş TargetFramework bilgisini 3.1'e çekmek.

<!--Before-->
<TargetFramework>netcoreapp2.2</TargetFramework> 

<!--After-->
<TargetFramework>netcoreapp3.1</TargetFramework>

Packages section'a bakacak olursak; 2.2 uygulamalar için kullandığımız Microsoft.AspNetCore.App artık .netCore sdk'in bir parçası ve uygulamalarımız reference'larına eklememiz gereken bir dll değil ve aynı zamanda EntityFrameworkCore'da doğrudan full paket olarak projelere eklemek yerine daha küçük dll'lere bölünmüş olarak kullanıma sunulmakta. 

<!--Before-->
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.0" />
<PackageReference Include="Autofac" Version="4.9.2" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.4.0" />

<!--After-->
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.3" />
<PackageReference Include="Autofac" Version="5.1.2" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="6.0.0" />

.csproj dosyasının son halina bakacak olursak;

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
	<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.3" />
	<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.3" />
	<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.3" />
	<PackageReference Include="Autofac" Version="5.1.2" />
	<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="6.0.0" />
  </ItemGroup>
  <ItemGroup>
    <Content Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
</Project>

Diğer bazı önemli değişiklikler ise Program.cs ve Startup.cs sınıfları için geçerli. 

Program.cs 

Program.cs de ki değişikler için doğrusu söylemek gerekirse gözle börülebilir major bir update yok gibi duruyor ancak Microsoft'un performance için değindiği bir kaç değişiklik var. Bunlardan biri IWebHostBuilder interface'i yerine IHostBuilder interface'inin kullanılmasını önermesi. IWebHostBuilder IWebHost build ederken, IHostBuilder IHost build etmekte ve MS bunun daha performanslı olduğu söylenmekte. IHost, Microsoft.Extensions.Hosting paketine, IWebHostBuilder ise Microsoft.AspNetCore.Hosting paketine aittir.

Bir diğer değişiklik ise uygulama içerisinde kullandığımız third party dependency injection tool'unun kullanılcağı yine host'u build ederken program.cs içerisinde UseServiceProviderFactory() metodunu kullanarak belirtilmesi gerekmekte. Bizde projemizde Autofac kullandığımızdan host.Build()'dan önce bu metodu call etmemiz gerekmekte.

Program.cs'in son haline bakacak olursak;

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateWebHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())
            .ConfigureWebHostDefaults(webHostBuilder => { webHostBuilder.UseStartup<Startup>(); });
}

Startup.cs 

Startup.cs de ki değişiklere bakacak olursak; Startup sınıfı default constructor ile geliyor ancak kullanmak zorunda değiliz.

//you don't have to use it if it's not necessary
public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

Bir diğer değişiklik IConfiguration. Microsoft v2.2'de IConfigurationRoot'un kullanılmasını öneriyordu, v3.1 ile default IConfiguration const. inject edilmiş olarak gelmekte ancak kullanma mecburiyetiniz tabikide yok ihtiyaca göre IConfigurationRoot'u da kullanabilirsiniz.

//Before
public IConfigurationRoot Configuration { get; }

//After
public IConfiguration Configuration { get; }

3rd Party DI Container Conf.

Bir diğer önemli değişiklik ise ConfigureServices metodu ile ilgili. v2.2'de ConfigureServices metodu default void olarak tanımlıydı ancak projelerimizde 3rd party dependency injection tool'u kullanmak istersek return type'ını IServiceProvider interface'ine dönüştürüp ilgili DI tool'unun instane'ını dönerek bu tool'u kullanıma sokabiliyorduk.

v3.x ile birlikte ConfigureServices metodu void olmaya zorlanmış ve herhangi bir geri dönüş değeri almamakta. Peki ya yazımızın başındada belirttiğimiz gibi projemizde Autofac kullanıyoruz ve autofac'i bir şekilde gerekli konfigurasyonlarla birlikte ayağa kaldırmamız gerekiyorsa? Bunun için Autofac'in dökümanlarında da belrtildiği üzre Startup.cs içerisinde görünürde olmasada ConfigureContainer metodu bulunmakta. Bu metod runtime'da build edilen bir metod ve autofac için ilgili registration'ları bu metod içerisinde yapabileceğimiz söylenmekte.

  // ConfigureContainer is where you can register things directly
  // with Autofac. This runs after ConfigureServices so the things
  // here will override registrations made in ConfigureServices.
  // Don't build the container; that gets done for you by the factory.
  public void ConfigureContainer(ContainerBuilder builder)
  {
    // Register your own things directly with Autofac, like:
    builder.RegisterModule(new MyApplicationModule());
  }

ContainerBuilder build-in-time'da kendisi otomatik olarak .Build() metodunu call eder ve uygulama için geçerli olan ILifeTimeScope'u ayağa kaldırır. 

ConfigureContainer metodunu Startup.cs içerisinde kullanmak yerine Program.cs içerisinde de kullanabiliriz.

.UseServiceProviderFactory().ConfigureContainer<ContainerBuilder>(builder => { builder.RegisterModule(new MyApplicationModule()); })

diyerekte parantez içinde DI tanımlamalarımızı yapabiliriz.

AddControllers()

WebApi projeleri için bazı Mvc özelliklerini kullanabilmemize olanak sağlayan AddMvc() metodu yerine çok daha lightweight bir versiyon olan AddControllers() metodu gelmekte ve AddMvc() hiç kullanmasakta bir sürü extra referansı projelerimize eklemekteydi dolayısıyla bundan kurtulmuş olduk güzel bir yenilik. 

services.AddControllers(options => options.Filters.Add(typeof(ValidateModelAttribute)))
    .AddNewtonsoftJson(options =>
        options.SerializerSettings.ContractResolver = new DefaultContractResolver());

UseRouting() 

v2.2'de Routing tanımlamalarını UseMvc() metodunu kullanarak yapabilmekteydik. v3.1 ile birlikte UseRouting() ve UseEndpoints() metodlarını kullanarak conf. edebilmemizi sağlamakta.

//Before
 app.UseMvc(routes =>
            {
                routes.MapRoute("DefaultApi", "api/{controller}/{id}");
            });
			
//After
  app.UseRouting();
  app.UseEndpoints(endpoints =>
  {
      endpoints.MapControllerRoute("DefaultApi", "api/{controller}/{id}");
      endpoints.MapHealthChecks("/health");
  });

Bu ve bunu gibi irili ufaklı bir çok yenilikle v3.1 hayatımıza girmiş bulunmakta. v2.1'den v2.2'ye geçiş yaparkenkinden biraz daha fazla ama implement etmesi oldukça basit yeniliklerle 2.2'den 3.1'e geçiş yapabilmekteyiz. Çok daha detaylı bilgiye microsoft'un bu sayfasındaki makalesinde bulabilirsiniz.

Add comment