スキップしてメイン コンテンツに移動

Upgrade from ASP.NET Core 2.2 to 3.0

Conguratulations on the releasing .NET Core 3.0 and ASP.NET Core 3.0!
Today's theme is about upgrading ASP.NET Core from ver.2.2 to ver.3.0.

What I did

  1. Creating an empty ASP.NET Core project(ver.2.2.402)
  2. Adding EntityFrameworkCore by NuGet
  3. Adding some codes
  4. Upgrading to ver.3.0.100
  5. Fixing some problems

Setup

Environments

  • .NET Core : ver.2.2.402, ver.3.0.100
  • Microsoft.EntityFrameworkCore : ver.2.2.6, ver.3.0.0
  • Npgsql.EntityFrameworkCore.PostgreSQL : ver.2.2.4, ver.3.0.1
  • Windows10 : ver.1903
  • Rider : ver.2019.2.3
  • PostgreSQL : ver.12.0

Creating the base project

UpgradeSample.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>netcoreapp2.2</TargetFramework>
        <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.App" />
        <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.6" />
        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.2.4" />
    </ItemGroup>

</Project>

Program.cs

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace UpgradeSample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

using Newtonsoft.Json.Serialization;
using UpgradeSample.Models;
using UpgradeSample.Products;

namespace UpgradeSample
{
    public class Startup
    {
        private IConfigurationRoot Configuration { get; }

        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", false, true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", false, true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }
        public void ConfigureServices(IServiceCollection services)
        {
            // DB Connect
            services.AddDbContext<UpgradeSampleContext>(options =>
                options.UseNpgsql(Configuration["DbConnect"]));
            // for setting JSON parameter names pascal case.
            services.AddMvc()
                .AddJsonOptions(options =>
                {
                    options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                });
            // DI
            services.AddScoped<IProductDao, Productdao>();
            services.AddScoped<IProductService, ProductService>();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseStaticFiles();
            app.UseMvc();
        }
    }
}

For routing

ApiController.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using UpgradeSample.Models;
using UpgradeSample.Products;

namespace UpgradeSample.Controllers
{
    public class ApiController: Controller
    {
        private readonly IProductService _productService;
        public ApiController(IProductService productService)
        {
            _productService = productService;
        }
        [Route("/")]
        [Route("/Home")]
        public string Index()
        {
            return "hello";
        }
        [HttpGet]
        [Route("/products")]
        public async Task<List<Product>> GetProducts()
        {
            return await _productService.GetProductsAsync();
        }
    }
}

For DB accessing

UpgradeSampleContext.cs

using Microsoft.EntityFrameworkCore;

namespace UpgradeSample.Models
{
    public class UpgradeSampleContext: DbContext
    {
        public UpgradeSampleContext(DbContextOptions<UpgradeSampleContext> options)
            :base(options)
        {
        }
        public DbSet<Product> Products { get; set; }
    }
}

Product.cs

using System.ComponentModel.DataAnnotations.Schema;

namespace UpgradeSample.Models
{
    [Table("Product")]
    public class Product
    {
        [Column("ProductId")]
        public int? ProductId { get; set; }
        [Column("ProductName")]
        public string ProductName { get; set; }
    }
}

IProductService.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using UpgradeSample.Models;

namespace UpgradeSample.Products
{
    public interface IProductService
    {
        Task<List<Product>> GetProductsAsync();
    }
}

ProductService.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using UpgradeSample.Models;

namespace UpgradeSample.Products
{
    public class ProductService: IProductService
    {
        private readonly IProductDao _productDao;
        public ProductService(IProductDao productDao)
        {
            _productDao = productDao;
        }
        public async Task<List<Product>> GetProductsAsync()
        {
            return await _productDao.GetProductsAsync();
        }
    }
}

IProductDao.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using UpgradeSample.Models;

namespace UpgradeSample.Products
{
    public interface IProductDao
    {
        Task<List<Product>> GetProductsAsync();
    }
}

ProductDao.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using UpgradeSample.Models;

namespace UpgradeSample.Products
{
    public class ProductDao: IProductDao
    {
        private readonly UpgradeSampleContext _context;
        public ProductDao(UpgradeSampleContext context)
        {
            _context = context;
        }
        public async Task<List<Product>> GetProductsAsync()
        {
            return await _context.Products.ToListAsync();
        }
    }
}

DB

SQL


CREATE TABLE "Product"(
 "ProductId" serial PRIMARY KEY,
 "ProductName" text NOT NULL
);
INSERT INTO "Product"(
 "ProductName"
)
VALUES
(
 'Nykee Running Shoes'
);
INSERT INTO "Product"(
 "ProductName"
)
VALUES
(
 'South Face Jacket'
);


Upgrade to ver.3.0.100

I changed 2 files and restored.

global.json

{
  "sdk": {
    "version": "3.0.100"
  }
}

UpgradeSample.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.0.1" />
    </ItemGroup>
</Project>

Fix problems

After upgrading, I found 3 warnings.

Startup.cs(15, 24): [CS0618] 'IHostingEnvironment'is obsolete ('This type is obsolete and will be removed in a future version. The recommended alternative is Microsoft.AspNetCore.Hosting.IWebHostEnvironment.')
Startup.cs(35, 56): [CS0618] 'IHostingEnvironment'is obsolete ('This type is obsolete and will be removed in a future version. The recommended alternative is Microsoft.AspNetCore.Hosting.IWebHostEnvironment.')
Startup.cs(42, 13): [MVC1005] Using 'UseMvc' to configure MVC is not supported while using Endpoint Routing. To continue using 'UseMvc', please set 'MvcOptions.EnableEndpointRouting = false' inside 'ConfigureServices'.

IHostingEnvironment and UseMvc had been changed.(Thank you for teaching me alternatives:) )
I changed only one class, Startup.cs.

Startup.cs


using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using UpgradeSample.Models;
using UpgradeSample.Products;

namespace UpgradeSample
{
    public class Startup
    {
        private IConfigurationRoot Configuration { get; }
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", false, true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", false, true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }
        public void ConfigureServices(IServiceCollection services)
        {
            // DB Connect
            services.AddDbContext<UpgradeSampleContext>(options =>
                options.UseNpgsql(Configuration["DbConnect"]));
            
            // for setting JSON parameter names pascal case.
            services.AddControllers()
                .AddJsonOptions(options =>
                    options.JsonSerializerOptions.PropertyNamingPolicy = null);
                    
            // DI
            services.AddScoped<IProductDao, Productdao>();
            services.AddScoped<IProductService, ProductService>();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseStaticFiles();
            
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                // for attribute-routing.
                endpoints.MapControllers();
            });
        }
    }
}


Endpoint Routing

I thought the main reason of this change was caused by using Endpoint Routing.

It separated middleware systems(for example MVC, Razor Pages, etc.) like below code.

Startup.cs


        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddRazorPages();
        }


Furthermore, it separated routing from endpoint.

Startup.cs


        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }


UseEndpoints required routing.

So this caused an exception.

Startup.cs


        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            // Exception was occurred at the runtime.
            // app.UseRouting(); 

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }


But if there ware no endpoints, no exceptions were occurred and the white page was shown;P.

Next time, I will try login/logout by ASP.NET Core Identity.

Resources

コメント

このブログの人気の投稿

[TypeScript] Try React 1

Intro This time I tried React. First, I referred Documents and Tutorial. React – A JavaScript library for building user interfaces GitHub - facebook/react: A declarative, efficient, and flexible JavaScript library for building user interfaces. Getting started with React - Learn web development | MDN Create a project To create a new React project, I used "Create React App". GitHub - facebook/create-react-app: Set up a modern web app by running one command. It created these files. .git node_modules public L favicon.ico L index.html L logo192.png L logo512.png L manifest.json L robots.txt src L App.css L App.test.tsx L App.tsx L index.css L index.test.tsx L index.tsx L logo.svg L react-app-env.d.ts L serviceWorker.ts L setupTests.ts .gitignore package.json package-lock.json README.md tsconfig.json Make the page work with IE11 I could view the page by "npm start" or "npm run start".   ...

[PostgreSQL] Play with TypeORM 1

Intro This time, I tried accessing Database by TypeORM. Because I wanted to manage Database tables by ORM, I created a table first.  GitHub - typeorm/typeorm   TypeORM - Amazing ORM for TypeScript and JavaScript (ES7, ES6, ES5). Installation and creating a project Installation TypeORM needed "reflect-metadata" and database driver. npm install --save typeorm reflect-metadata pg typescript tsc npm install --save-dev @types/node And I also installed "ts-node" to skip compiling. npm install --save ts-node Preparing References I could generate a TypeORM project by TypeORM command. npx typeorm init --name gen-typeorm-sample --database postgres I refered Most of all settings from it. Adding files and folders First, I added tsconfig.json. npx tsc --init And I edited like below. tsconfig.json { "compilerOptions": { /* Basic Options */ "incremental": true, "target": "es5", "module": "comm...

[Angular 10 + NgRx + Nest.js] Create project

Intro This time, I added server-side. I choosed Nest.js because I love TypeScript and I had been interested in using TypeScript in server-side programming. Environments Angular ver.10.0.2 @ngrx/store ver.9.2.0 @ngrx/effects ver.9.2.0 @nestjs/ng-universal ver.2.0.1 Couldn't add @ngrx/store into the Angular 10 project First, I created an Angular project and tried adding @ngrx/store into it. And I got an error. Installing packages for tooling via npm. Installed packages for tooling via npm. The package that you are trying to add does not support schematics. You can try using a different version of the package or contact the package author to add ng-add support. According to the issue below, I should add "@latest". npx ng add @ngrx/store@latest Because if I didn't add it, the @ngrx/store version was too low.    cannot use ng add to install ngrx store · Issue #2604 · ngrx/platform · GitHub Though I didn't know I should add "@latest" into ...