[ASP.NET Core][EntityFramework Core]Try Azure 1
Tags: aspnetcore, azure, entityframeworkcore
Published: 2021-04-03 01:24:48

## Intro
This time, I will try deploying a web application on Azure.

### Environments
* ASP.NET Core ver.5.0.103
* Npgsql.EntityFrameworkCore.PostgreSQL ver.5.0.2
* Microsoft.EntityFrameworkCore ver.5.0.4
* Microsoft.EntityFrameworkCore.Design ver.5.0.4
* NLog.Web.AspNetCore ver.4.12.0

## Create App on Azure App Service
First, I will register your ASP.NET Core app with Azure App Service according to the documentation.

* [Quickstart: Deploy an ASP.NET web app - Azure App Service | Microsoft Docs](https://docs.microsoft.com/en-us/azure/app-service/quickstart-dotnetcore?tabs=netcore31&pivots=development-environment-vs)

### Create an ASP.NET Core application
I create a simple ASP.NET Core application.

#### Startup.cs
```cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AzureWebAppSample.Books;
using AzureWebAppSample.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace AzureWebAppSample
{
    public class Startup
    {
        private readonly IConfiguration configuration;
        public Startup(IConfiguration configuration)
        {
            this.configuration = configuration;
        }
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddRazorPages();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseStaticFiles();
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}
```
#### HomeController.cs
```cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace AzureWebAppSample.Controllers
{
    public class HomeController: Controller
    {
        private readonly ILogger<HomeController> logger;
        public HomeController(ILogger<HomeController> logger)
        {
            this.logger = logger;
        }
        [Route("")]
        public IActionResult Index()
        {
            return View("Views/MainPage.cshtml");
        }
    }
}
```
#### MainPage.cshtml
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Main Page</title>
</head>
<body>
    <h1>Hello Azure!</h1>
</body>
</html>
```

### Register Azure App Service
Though I can create on the portal site, because the document recommends, and I also feel more convenient, I create an app by Azure CLI.

I execute this command on the project directory.

```
az webapp up --sku F1 --name {AppName}　--location "Japan West" --os-type　linux
```

* Default location is "Central US"
* Because default OS type is "windows" and I can't chagne after creating it, so I must add "--os-type" when I want to use "linux".
* I can update the application by the command. Some options can be omitted.

### Result
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wza4dw25q217y7qdaap6.jpg)

## Use PostgreSQL
For using Database from the application, I create a server on Azure Database for PostgreSQL from the portal site.

* [Quickstart: Create server - Azure portal - Azure Database for PostgreSQL - single server | Microsoft Docs](https://docs.microsoft.com/en-us/azure/postgresql/quickstart-create-server-database-portal)

### Allow access from my own IP Address
After creating, I must change "Connection Security" because the server isn't public.
So I must set it allow my own access.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4hbzkeq5c7mc3l0d9w2o.png)
Before I add my own IP Address, I can click the text in the red square.

### Connection strings
I can get the connection strings in "Connection strings" page.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xoik7t00kz2g8hpowrxn.jpg)

I can access from PgAdmin, EntityFramework Core, etc.

### Update projects
#### Startup.cs
```cs
...
    public class Startup
    {
        private readonly IConfiguration configuration;
        public Startup(IConfiguration configuration)
        {
            this.configuration = configuration;
        }
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddDbContext<AzureWebAppContext>(options =>
            {
                options.UseNpgsql(configuration["DbConnection"]);
            });
            services.AddRazorPages();
            services.AddScoped<IBookService, BookService>();
        }
...
```
#### appsettings.Production.json
```json
{
    "Logging": {
        "LogLevel": {
        "Default": "Debug",
        "Microsoft": "Warning",
        "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "DbConnection": "Server=azure-postgres-sample.postgres.database.azure.com;Database=BookStore;Port=5432;User Id={UserName};Password={Password};Ssl Mode=Require;"
}
```
#### IBookService.cs
```cs
using System.Collections.Generic;
using System.Threading.Tasks;
using AzureWebAppSample.Models;

namespace AzureWebAppSample.Books
{
    public interface IBookService
    {
        Task<List<Genre>> GetAllGenresAsync();
    }
}
```
#### BookService.cs
```cs
using System.Collections.Generic;
using System.Threading.Tasks;
using AzureWebAppSample.Models;
using Microsoft.EntityFrameworkCore;

namespace AzureWebAppSample.Books
{
    public class BookService: IBookService
    {
        private readonly AzureWebAppContext context;
        public BookService(AzureWebAppContext context)
        {
            this.context = context;
        }
        public async Task<List<Genre>> GetAllGenresAsync()
        {
            return await context.Genres.ToListAsync();
        }
    }
}
```
#### MainPage.cshtml
```html
@using AzureWebAppSample.Books;
@inject IBookService books;
@{
    var genres = await books.GetAllGenresAsync();
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Main Page</title>
</head>
<body>
    <h1>Hello Azure!</h1>
    <div>
        @foreach (var item in genres)
        {
            <div>ID: @item.Id Name: @item.Name</div>
        }
    </div>
</body>
</html>
```

### Result
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vqw812xawmni9j2j4rdu.jpg)

## Output log
How to output logs on Azure?

I think I shall not write them into text files.
This time, I try outputting them into console.

#### HomeController.cs
```cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace AzureWebAppSample.Controllers
{
    public class HomeController: Controller
    {
        private readonly ILogger<HomeController> logger;
        public HomeController(ILogger<HomeController> logger)
        {
            this.logger = logger;
        }
        [Route("")]
        public IActionResult Index()
        {
            logger.LogDebug("Open MainPage");
            return View("Views/MainPage.cshtml");
        }
    }
}
```

I can get the logs in "Log stream" page.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypuluv0omynjsy4cekf5.png)