Sıfırdan Asp.Net Core 2.2 Web Api CRUD İşlemleri

Merhaba arkadaşlar, bugün Visual Studio ortamında Asp.Net Core 2.2 ile Web Api uygulaması yapacağız. Şimdi boş bir Asp.Net Core 2.2 projesi oluşturalım.




















































Controller , Modeller ve Repositorylerimiz için Infrastructure klasörlerimizi oluşturalım.



















Kategoriye ait ürünlerin olduğu model sınıflarımızı oluşturalım.

    public class BaseEntity
    {
        public int Id { get; set; }
        public bool IsActive { get; set; }
        public string Description { get; set; }
    }

   public class Product:BaseEntity
    {
        public string Name { get; set; }
        public int Stock { get; set; }
        public double Price { get; set; }
        public int CategoryId { get; set; }
        public virtual Category Category { get; set; }
    }

 public class Category:BaseEntity
    {
        public Category()
        {
            Products = new HashSet<Product>();
        }

        public string CategoryName { get; set; }
        public virtual ICollection<Product> Products { get; set; }
    }



Modellerimiz için Context Sınıfımızı oluşturalım ve içlerine ilk değerlerini girelim.

public class CoreDbContext : DbContext
    {
        public CoreDbContext(DbContextOptions<CoreDbContext> options) : base(options)
        {

        }
        public DbSet<Product> Product { get; set; }
        public DbSet<Category> Category { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {


modelBuilder.Entity<Category>().HasData(
       new Category { Id = 1, CategoryName = "Çorbalar", Description = "Anadolu mutfağı. ", IsActive = true },
       new Category { Id = 2, CategoryName = "Kebaplar", Description = "Anadolu mutfağı. ", IsActive = true },
       new Category { Id = 3, CategoryName = "Salatalar", Description  = "Anadolu mutfağı. ", IsActive = true },
       new Category { Id = 4, CategoryName = "İçecekler", Description = "Anadolu mutfağı. ", IsActive = true },
       new Category { Id = 5, CategoryName = "Balıklar", Description = " Anadolu mutfağı. ", IsActive = true },
       new Category { Id = 6, CategoryName = "Sulu Yemekler", Description = "Anadolu mutfağı. ", IsActive = true },
       new Category { Id = 7, CategoryName = "Meyveler", Description = "Anadolu mutfağı. ", IsActive = true },
       new Category { Id = 8, CategoryName = "Tatlılar", Description = "Anadolu mutfağı. ", IsActive = true },
       new Category { Id = 9, CategoryName = "Kuru Yemiş", Description = "Anadolu mutfağı. ", IsActive = true } );

modelBuilder.Entity<Product>().HasData(
       new Product { Id = 1, CategoryId = 1, Name = "Mercimek", IsActive = true, Price = 5, Stock = 100 },
       new Product { Id = 2, CategoryId = 1, Name = "Ezogelin", IsActive = true, Price = 5, Stock = 95 },
       new Product { Id = 3, CategoryId = 2, Name = "İskender", IsActive = true, Price = 25, Stock = 70 },
       new Product { Id = 4, CategoryId = 2, Name = "Adana", IsActive = true, Price = 25, Stock = 80 },
       new Product { Id = 5, CategoryId = 3, Name = "Mevsim", IsActive = true, Price = 8, Stock = 100 },
       new Product { Id = 6, CategoryId = 3, Name = "Havuç", IsActive = true, Price = 6, Stock = 40 },
       new Product { Id = 7, CategoryId = 4, Name = "Kola", IsActive = true, Price = 4, Stock = 150 },
       new Product { Id = 8, CategoryId = 4, Name = "Ayran", IsActive = true, Price = 3, Stock = 200 },
       new Product { Id = 9, CategoryId = 5, Name = "Kuru Fasülye", IsActive = true, Price = 12, Stock = 90 },
       new Product { Id = 10, CategoryId = 5, Name = "Bezelye", IsActive = true, Price = 10, Stock = 70 },
       new Product { Id = 11, CategoryId = 6, Name = "Uskumru", IsActive = true, Price = 25, Stock = 25 },
       new Product { Id = 12, CategoryId = 6, Name = "Hamsi Tava", IsActive = true, Price = 25, Stock = 40 },
       new Product { Id = 13, CategoryId = 7, Name = "Portakal", IsActive = true, Price = 1, Stock = 300 },
       new Product { Id = 14, CategoryId = 7, Name = "Elma", IsActive = true, Price = 1, Stock = 275 },
       new Product { Id = 15, CategoryId = 8, Name = "Baklava", IsActive = true, Price = 10, Stock = 100 },
       new Product { Id = 16, CategoryId = 8, Name = "Sütlaç", IsActive = true, Price = 8, Stock = 100 },
       new Product { Id = 17, CategoryId = 9, Name = "Fındık", IsActive = true, Price = 5, Stock = 1000 },
       new Product { Id = 18, CategoryId = 9, Name = "Fıstık", IsActive = true, Price = 5, Stock = 1000 }
   );
 }
}

Asp.Net Core da Dependency Injection kavramına önem vermişler ve kendi metotlarını
yazmışlar. Bizde bu uygulamada DI kullanacağız. bunun için Repository patern oluşturacağız.

Şimdi GenericRepository dizayn için ilk önce arayüzlerimizi oluşturalım.

Temel Interface IRepository


 public interface IRepository<TEntity> where TEntity:class
    {
        Task<ICollection<TEntity>> GetAllAsync();
        Task<TEntity> GetByIdAsync(int id);
        void Add(TEntity entity);
        void Update(TEntity entity);
        void Delete(TEntity entity);
        Task SaveChangesAsync();
    }


IProductRepository arayüzünü oluşturalım ve IRepository arayüzünü implement edelim.

public interface IProductRepository:IRepository<Product>
    {
    }


ICategoryRepository arayüzünü oluşturalım ve IRepository arayüzünü implement edelim.

 public interface ICategoryRepository:IRepository<Category>
    {
    }


Şimdi oluşturduğumuz arayüzlerimizi implement edecek sınıflarımızı oluşturalım.
Repository sınıfına IRepository arayüzünü implement edip Generic Repositorimizi hazırlıyoruz.

 public class Repository<TEntity>:IRepository<TEntity>,IDisposable where TEntity:class
    {
        private readonly CoreDbContext _context;
        private readonly DbSet<TEntity> _dbSet;
        private bool disposed = false;

        public Repository(CoreDbContext context)
        {
            _context = context;
            _dbSet = _context.Set<TEntity>();
        }

        public virtual void Add(TEntity entity)
        {
            _dbSet.Add(entity);
        }

        public virtual void Delete(TEntity entity)
        {
            if (_context.Entry(entity).State == EntityState.Detached)
            {
                _context.Attach(entity);
            }
            _context.Remove(entity);
        }


        public async Task<ICollection<TEntity>> GetAllAsync()
        {
            return await _dbSet.ToListAsync();
        }

        public async Task<TEntity> GetByIdAsync(int id)
        {
            return await _dbSet.FindAsync(id);
        }

        public async Task SaveChangesAsync()
        {
            await _context.SaveChangesAsync();
        }

        public virtual void Update(TEntity entity)
        {
            _context.Attach(entity);
            _context.Entry(entity).State = EntityState.Modified;
        }

     
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    _context.Dispose();
                }
                this.disposed = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }


ProductRepository sınıfımızı oluşturalım ve Repository ile IProductRepositoryi ekleyelim. Repository sınıfını eklerken bizden TEntiy olarak tanımladığımız bir sınıf isteyecektir ve
buraya Product model sınıfımızın ismini yazıyoruz.

   public class ProductRepository : Repository<Product>, IProductRepository
    {
        public ProductRepository(CoreDbContext context) : base(context)
        {
        }
    }

Repository sınıfını miras verdiğimizde bizi uyaracaktır üst sınıf Repositroy nin Constructorını ezmemiz isteyecek ve ProductRepository Constructor kullanarak override ediyoruz.


Şimdi CategoryRepository sınıfımızı oluşturalım ve Repository ile IProductRepositoryi ekleyelim.

  public class CategoryRepository : Repository<Category>, ICategoryRepository
    {
        public CategoryRepository(CoreDbContext context) : base(context)
        {
        }
    }

Repository sınıflarımızı da oluşturduk. Şimdi appsettings.json dosyasını düzenleyelim ve
buraya connectionstring parametrelerini girelim.

  "ConnectionStrings": {
    "CoreDbContext": "server=.; database=CoreDB; integrated security=true;"
  },



Şimdi Startup.cs dosyasını düzenleyelim aşağıdaki kodları ekleyelim.

 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.AddScoped<IProductRepository, ProductRepository>();
            services.AddScoped<ICategoryRepository, CategoryRepository>();
            services.AddDbContext<CoreDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("CoreDbContext")));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }
      
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {              
                app.UseHsts();
            }

            InitializeDatabase(app);
            app.UseStatusCodePages();
            app.UseHttpsRedirection();
            app.UseMvc();
        }

  private void InitializeDatabase(IApplicationBuilder app)
  {
       using (var scope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
       {
            scope.ServiceProvider.GetRequiredService<CoreDbContext>().Database.Migrate();
       }
   }
}


Şimdi sıra Code First Migration ile veri tabanımızı oluşturmaya geldi.

Package Manager Console açıyoruz ve aşağıdaki kodları yazıyoruz. add-migration yapalım.


-Context ile Context Sınıfımızın yolunu yazıyoruz 
-OutputDir ile Migration işlemlerinin oluşmasını istediğimiz klasör yolunu giriyoruz.

update-database komutu ile veri tabanımızı oluşturalım.


Geldik gerçek işimize  Apiler için Controller oluşturmaya. 


























Oluşturduğumuz boş ProductController sınıfını aşağıdaki gibi düzenleyelim.


    [Route("api/[controller]")]
    [ApiController]
    public class ProductController : ControllerBase
    {
        // Dependency Injection
        private readonly IProductRepository _productRepository;
        public ProductController(IProductRepository productRepository)
        {
            _productRepository = productRepository;
        }

        // GET: api/Product
        [HttpGet]
        public async Task<IActionResult> GetProduct()
        {
            var products = await _productRepository.GetAllAsync();
            return Ok(products);
        }

        // GET: api/Product/5
        [HttpGet("{id}", Name = "GetProductById")]
        public async Task<IActionResult> GetProduct(int id)
        {
            var product = await _productRepository.GetByIdAsync(id);
            if (product == null)
            {
                return NotFound("Ürün Bulunamadı.");
            }
            return Ok(product);
        }

        // POST: api/Product
        [HttpPost]
        public async Task<IActionResult> PostProduct([FromBody] Product product)
        {
            try
            {
                if (product == null)
                {
                    return BadRequest("Geçersiz istek.");
                }
                _productRepository.Add(product);
                await _productRepository.SaveChangesAsync();
                return CreatedAtAction("GetProduct", new { id = product.Id }, product);
            }
            catch (Exception)
            {
                return StatusCode(500, "Internal server error");
            }
        }

        // PUT: api/Product/5
        [HttpPut("{id}")]
        public async Task<IActionResult> PutProduct(int id, [FromBody] Product product)
        {
            try
            {
                if (product == null)
                {
                    return BadRequest("Geçersiz istek.");
                }

                _productRepository.Update(product);
                await _productRepository.SaveChangesAsync();
                return NoContent();

            }
            catch (Exception)
            {
                return StatusCode(500, "Internal server error");
            }
        }

        //DELETE: api/Product/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteProduct(int id)
        {
            try
            {
                var product = await _productRepository.GetByIdAsync(id);
                if (product == null)
                {
                    return NotFound("Ürün bulunamadı.");
                }

                _productRepository.Delete(product);
                await _productRepository.SaveChangesAsync();
                return NoContent();
            }
            catch (Exception)
            {
                return StatusCode(500, "Internal server error");
            }
        }
    }



CategoryController sınıfını aşağıdaki gibi düzenleyelim.


 [Route("api/[controller]")]
    [ApiController]
    public class CategoryController : ControllerBase
    {
        private readonly ICategoryRepository _categoryRepository;

        public CategoryController(ICategoryRepository categoryRepository)
        {
            _categoryRepository = categoryRepository;
        }

        // GET: api/Category
        [HttpGet]
        public async Task<ActionResult> GetCategory()
        {
            var categories = await _categoryRepository.GetAllAsync();
            return Ok(categories);
        }

        // GET: api/Category/5
        [HttpGet("{id}", Name = "GetCategory")]
        public async Task<ActionResult> GetCategory(int id)
        {
            var category = await _categoryRepository.GetByIdAsync(id);
            if (category == null)
            {
                return NotFound("Kategori bulunamadı.");
            }
            return Ok(category);
        }

        // POST: api/Category
        [HttpPost]
        public async Task<ActionResult> PostCategory([FromBody] Category category)
        {
            try
            {
                if (category == null)
                {
                    return BadRequest("Geçersiz istek.");
                }

                _categoryRepository.Add(category);
                await _categoryRepository.SaveChangesAsync();
                return CreatedAtAction("GetCategory", new { id = category.Id }, category);
            }
            catch (Exception)
            {
                return StatusCode(500, "Internal server error");
            }
        }

        //PUT: api/Category/5
        [HttpPut("{id}")]
        public async Task<ActionResult> PutCategory(int id, [FromBody] Category category)
        {
            try
            {
                if (category == null)
                {
                    return BadRequest("Geçersiz istek");
                }
             
                _categoryRepository.Update(category);
                await _categoryRepository.SaveChangesAsync();
                return NoContent();
            }
            catch (Exception)
            {
                return StatusCode(500, "Internal server error");
            }
        }

        // DELETE: api/Category/5
        [HttpDelete("{id}")]
        public async Task<ActionResult> DeleteCategory(int id)
        {
            try
            {
                var category = await _categoryRepository.GetByIdAsync(id);
                if (category==null)
                {
                    return NotFound("Kategori bulunamadı.");
                }
                _categoryRepository.Delete(category);
                await _categoryRepository.SaveChangesAsync();
                return NoContent();
            }
            catch (Exception)
            {
                return StatusCode(500, "Internal server error");
            }
        }
    }


Projemizin klasör ve dosya yapısının son hali.








































Şimdi geldi Test Etmeye.

Test etmek için Postman programını kullanacağız. Projemizi çalıştırıyoruz.




























Yeşil çizgi ile belirttiğim kısımlardan sol taraftan yapmak istediğimiz olayı sağ tarafa ise Url yi yazıp
Get işleminin başarıyla çalıştığını görüyoruz.

Şimdi yeni bir kayıt oluşturup POST edelim.






























Web Apimizin Post metodu da başarıyla çalıştığını görmekteyiz.

Var olan kayıtın "Stok" adedini değiştirerek PUT metodumuzu test edelim. Burada dikkat etmemiz gereken kısım Url sonuna id eklemeyi unutmuyoruz (https://localhost44386/api/Product/1).






























GET işlemini kullanarak değişikliği kontrol ediyoruz ve PUT işlemininde başarıyla gerçekleştiğini görüyoruz.
































Son olarak DELETE metodu ile silme işleminin testini yapıyoruz. Burada da Url ye id vermeyi unutmuyoruz.






























DELETE metodumuzun da başarıyla çalıştığını görüyoruz.

Projenin kodları  AspNet_Core_WA1

Başka bir makalede görüşmek üzere.

Yorumlar

Bu blogdaki popüler yayınlar

İç İçe Bağımlı DropdownListFor (Cascading)

Asp.Net Core View Components Kullanımı

Partial - RenderPartial - Html.Action - Html.RenderAction Kullanımı