สร้างโปรเจ็กส์ Web API ติดต่อ MySQL

  1. สร้างโปรเจ็กส์ด้วย Visual Studio 2019
  2. ไฟล์ต่างๆในโปรเจ็กส์
  3. เพิ่มคลาส Movie
  4. สร้างคอนโทรลเลอร์ MovieController
  5. ติดตั้ง Pomelo.EntityFrameworkCore.MySql
  6. สร้างตารางที่ MySQL
  7. ทดสอบ API

1.สร้างโปรเจ็กส์ด้วย Visual Studio 2019

สร้างโปรเจ็กส์ใหม่ เลือก Create a new project

เลือกภาษา C#

เลือก ASP.NET Core Web Application

ตั้งชื่อโปรเจ็กส์ WebApiDemo เสร็จแล้วกด Create

เลือก template เป็น API และที่ด้านบนเลือกเป็น .NET Core และ ASP.NET Core 3.0

รันทดสอบ จะไปที่ http://localhost:52744/weatherforecast และได้ค่า

[
    {
        "date": "2019-11-09T15:36:53.0790529+07:00",
        "temperatureC": 29,
        "temperatureF": 84,
        "summary": "Cool"
    },
    {
        "date": "2019-11-10T15:36:53.0814444+07:00",
        "temperatureC": 23,
        "temperatureF": 73,
        "summary": "Chilly"
    },
    {
        "date": "2019-11-11T15:36:53.0814498+07:00",
        "temperatureC": 6,
        "temperatureF": 42,
        "summary": "Cool"
    },
    {
        "date": "2019-11-12T15:36:53.0814502+07:00",
        "temperatureC": 6,
        "temperatureF": 42,
        "summary": "Chilly"
    },
    {
        "date": "2019-11-13T15:36:53.0814502+07:00",
        "temperatureC": -11,
        "temperatureF": 13,
        "summary": "Balmy"
    }
]

2.ไฟล์ต่างๆในโปรเจ็กส์

ไฟล์ WeatherForecast.cs

คลาส WeatherForecast

using System;

namespace WebApiDemo
{
    public class WeatherForecast
    {
        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

        public string Summary { get; set; }
    }
}

ไฟล์ Controllers/WeatherForecastController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace WebApiDemo.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

ไฟล์ Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace WebApiDemo
{
    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.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
        }

        // 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();
            }

            app.UseRouting();

            app.UseAuthorization();

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

ไฟล์ Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

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

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

ไฟล์ appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

ไฟล์ Properties/launchSettings.json

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:52744",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "WebApiDemo": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

3.เพิ่มคลาส Movie

สร้างโฟลเดอร์ Models

สร้างไฟล์ Models/Movie.cs

using System;
using System.ComponentModel.DataAnnotations;

namespace WebApiDemo.Models
{
    public class Movie
    {
        public int Id { get; set; }
        public string Title { get; set; }

        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}

4.สร้างคอนโทรลเลอร์ MovieController

คลิกขวาที่โฟลเดอร์ Controllers เลือก Add | Controller…

เลือก API Controller with actions, using Entity Framework

Model class เลือก Movie
Data context class สร้างใหม่ชื่อ MovieContext

กด Add

เสร็จแล้วจะได้ไฟล์ Data/MovieContext.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace WebApiDemo.Models
{
    public class MovieContext : DbContext
    {
        public MovieContext (DbContextOptions<MovieContext> options)
            : base(options)
        {
        }

        public DbSet<WebApiDemo.Models.Movie> Movie { get; set; }
    }
}

และได้ไฟล์ Controllers/MoviesController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using WebApiDemo.Models;

namespace WebApiDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class MoviesController : ControllerBase
    {
        private readonly MovieContext _context;

        public MoviesController(MovieContext context)
        {
            _context = context;
        }

        // GET: api/Movies
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Movie>>> GetMovie()
        {
            return await _context.Movie.ToListAsync();
        }

        // GET: api/Movies/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Movie>> GetMovie(int id)
        {
            var movie = await _context.Movie.FindAsync(id);

            if (movie == null)
            {
                return NotFound();
            }

            return movie;
        }

        // PUT: api/Movies/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.
        [HttpPut("{id}")]
        public async Task<IActionResult> PutMovie(int id, Movie movie)
        {
            if (id != movie.Id)
            {
                return BadRequest();
            }

            _context.Entry(movie).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!MovieExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        // POST: api/Movies
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.
        [HttpPost]
        public async Task<ActionResult<Movie>> PostMovie(Movie movie)
        {
            _context.Movie.Add(movie);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetMovie", new { id = movie.Id }, movie);
        }

        // DELETE: api/Movies/5
        [HttpDelete("{id}")]
        public async Task<ActionResult<Movie>> DeleteMovie(int id)
        {
            var movie = await _context.Movie.FindAsync(id);
            if (movie == null)
            {
                return NotFound();
            }

            _context.Movie.Remove(movie);
            await _context.SaveChangesAsync();

            return movie;
        }

        private bool MovieExists(int id)
        {
            return _context.Movie.Any(e => e.Id == id);
        }
    }
}

และเมื่อกลับไปดูที่ไฟล์ appsettings.json จะเห็นว่ามีการเพิ่ม ConnectionStrings

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MovieContext": "Server=(localdb)\\mssqllocaldb;Database=MovieContext-325717dc-d87d-4e13-9f43-362cef94252e;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

แก้ไขจาก MS SQL เป็น MySQL ดังนี้

  "ConnectionStrings": {
    "MovieContext": "server=localhost;port=3306;database=mydbname;uid=myusername;password=mypassword"
  }

และที่ไฟล์ Startup.cs มีโค๊ดเชื่อมต่อ MS SQL เข้ามา

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

            services.AddDbContext<MovieContext>(options =>
                  options.UseSqlServer(Configuration.GetConnectionString("MovieContext")));
        }

5.ติดตั้ง Pomelo.EntityFrameworkCore.MySql

PM> Install-Package Pomelo.EntityFrameworkCore.MySql -Version 3.0.0-rc3.final

แก้ไขเป็นเชื่อมต่อไปที่ MySql แทน

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

            services.AddDbContext<MovieContext>(options =>
                    options.UseMySql(Configuration.GetConnectionString("MovieContext")));
        }

6.สร้างตารางที่ MySQL

CREATE TABLE `movie` (
  `Id` int(11) NOT NULL,
  `Title` longtext DEFAULT NULL,
  `ReleaseDate` datetime(6) NOT NULL,
  `Genre` longtext DEFAULT NULL,
  `Price` decimal(65,30) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `movie`
  ADD PRIMARY KEY (`Id`);
COMMIT;

เพิ่มข้อมูลตัวอย่าง

INSERT INTO `movie` (`Id`, `Title`, `ReleaseDate`, `Genre`, `Price`) VALUES
(0, 'X-Men', '2019-11-01 00:00:00.000000', 'Action', '1.000000000000000000000000000000');

7.ทดสอบ API

เรียกไปที่ http://localhost:52744/api/movies จะได้

[
    {
        "id": 0,
        "title": "X-Men",
        "releaseDate": "2019-11-01T00:00:00",
        "genre": "Action",
        "price": 1.0000000000000000000000000000
    }
]