- Добавил репозиторий и сервис для бренда.

- вынес логику в репозитории и сервисы из PhoneController.
- обернул try catch PoneController.
- дополнил мапперы, добавил проверку на null;
parent a5a0c3ef
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PhoneStore.Helpers;
using PhoneStore.Exceptions;
using PhoneStore.Mappers;
using PhoneStore.Models;
using PhoneStore.Services.Interfaces;
using PhoneStore.ViewModels;
using PhoneStore.ViewModels.Account;
using PhoneStore.ViewModels.PhoneViewModels;
namespace PhoneStore.Controllers
{
public class PhonesController : Controller
{
private readonly MobileContext _db;
private readonly IPhoneService _phoneService;
private readonly IBrandService _brandService;
public PhonesController(
MobileContext db,
IPhoneService phoneService)
IPhoneService phoneService, IBrandService brandService)
{
_db = db;
_phoneService = phoneService;
_brandService = brandService;
}
[HttpGet]
public IActionResult Index(int? brandId)
{
IEnumerable<Brand> brands = _db.Brands;
IQueryable<Phone> phones = _db.Phones.AsQueryable();
if (brandId is > 0)
phones = _db.Phones.Where(p => p.BrandId == brandId);
return View(new IndexViewModel
try
{
return View(_phoneService.GetIndexViewModel(brandId));
}
catch (EntityNotFoundException e)
{
Brands = brands,
Phones = phones.ToList()
});
return RedirectToAction("Error", "Errors", new {statusCode = 777});
}
catch (Exception e)
{
return RedirectToAction("Error", "Errors", new {statusCode = 500});
}
}
[HttpGet]
public IActionResult Create()
{
IPhoneEditable model = new PhoneCreateViewModel
try
{
Brands = _db.Brands.ToList()
};
return View(model);
return View(_phoneService.GetCreateViewModel());
}
catch (EntityNotFoundException e)
{
return RedirectToAction("Error", "Errors", new {statusCode = 777});
}
catch (Exception e)
{
return RedirectToAction("Error", "Errors", new {statusCode = 500});
}
}
[HttpPost]
......@@ -66,76 +69,121 @@ namespace PhoneStore.Controllers
return RedirectToAction("Index");
}
model.Brands = _db.Brands.ToList();
model.Brands = _brandService.GetAll();
return View("Create", model);
}
//TODO: Добавить кастомный exception
catch (EntityNotFoundException e)
{
return RedirectToAction("Error", "Errors", new {statusCode = 777});
}
catch (FileNotFoundException)
{
return RedirectToAction("Error", "Errors", new {statusCode = 666});
}
catch(Exception)
{
return RedirectToAction("Error", "Errors", new {statusCode = 777});
return RedirectToAction("Error", "Errors", new {statusCode = 500});
}
}
[HttpGet]
public IActionResult Delete(int phoneId)
{
var phone = _db.Phones.FirstOrDefault(p => p.Id == phoneId);
if (phone is null)
return RedirectToAction("Error", "Errors", new {statusCode = 777});
try
{
var phone = _phoneService.GetById(phoneId);
if (phone is null)
return RedirectToAction("Error", "Errors", new {statusCode = 777});
return View(phone);
return View(phone);
}
catch (EntityNotFoundException e)
{
return RedirectToAction("Error", "Errors", new {statusCode = 777});
}
catch (FileNotFoundException)
{
return RedirectToAction("Error", "Errors", new {statusCode = 666});
}
catch(Exception)
{
return RedirectToAction("Error", "Errors", new {statusCode = 500});
}
}
[HttpPost]
[ActionName("Delete")]
public IActionResult Confirm(int phoneId)
{
//TODO: Добавить удаление файла изображения.
var phone = _db.Phones.FirstOrDefault(p => p.Id == phoneId);
if (phone is null)
try
{
//TODO: Добавить удаление файла изображения.
var phone = _phoneService.GetById(phoneId);
if (phone is null)
return RedirectToAction("Error", "Errors", new {statusCode = 777});
_phoneService.Delete(phoneId);
return RedirectToAction("Index");
}
catch (EntityNotFoundException e)
{
return RedirectToAction("Error", "Errors", new {statusCode = 777});
_db.Phones.Remove(phone);
_db.SaveChanges();
return RedirectToAction("Index");
}
catch (FileNotFoundException)
{
return RedirectToAction("Error", "Errors", new {statusCode = 666});
}
catch(Exception)
{
return RedirectToAction("Error", "Errors", new {statusCode = 500});
}
}
[HttpGet]
public IActionResult Edit(int phoneId)
{
var brands = _db.Brands.ToList();
var phone = _db.Phones.FirstOrDefault(p => p.Id == phoneId);
if (phone is null)
try
{
return View(_phoneService.GetEditViewModel(phoneId));
}
catch (EntityNotFoundException e)
{
return RedirectToAction("Error", "Errors", new {statusCode = 777});
IPhoneEditable model = new PhoneEditViewModel
{
Id = phone.Id,
Name = phone.Name,
Price = phone.Price,
BrandId = (int)phone.BrandId,
Image = phone.Image,
Brands = brands
};
return View(model);
}
catch (FileNotFoundException)
{
return RedirectToAction("Error", "Errors", new {statusCode = 666});
}
catch(Exception)
{
return RedirectToAction("Error", "Errors", new {statusCode = 500});
}
}
//TODO: Доделать
[HttpPost]
public IActionResult Edit(PhoneCreateViewModel model)
public IActionResult Edit(PhoneEditCreateViewModel model)
{
if (model is null)
try
{
if (model is null)
return RedirectToAction("Error", "Errors", new {statusCode = 777});
string imagePath = string.Empty;
if (model.File is null)
imagePath = model.Image;
_phoneService.Update(model.MapToPhone(imagePath));
return RedirectToAction("Index");
}
catch (EntityNotFoundException e)
{
return RedirectToAction("Error", "Errors", new {statusCode = 777});
string imagePath = string.Empty;
if (model.File is null)
imagePath = model.Image;
_db.Phones.Update(model.MapToPhone(imagePath));
_db.SaveChanges();
return RedirectToAction("Index");
}
catch (FileNotFoundException)
{
return RedirectToAction("Error", "Errors", new {statusCode = 666});
}
catch(Exception)
{
return RedirectToAction("Error", "Errors", new {statusCode = 500});
}
}
[HttpGet]
......@@ -147,10 +195,18 @@ namespace PhoneStore.Controllers
var phoneViewModel = _phoneService.GetById(phoneId.Value);
return View(phoneViewModel);
}
catch (NullReferenceException)
catch (EntityNotFoundException e)
{
return RedirectToAction("Error", "Errors", new {statusCode = 777});
}
catch (FileNotFoundException)
{
return RedirectToAction("Error", "Errors", new {statusCode = 666});
}
catch(Exception)
{
return RedirectToAction("Error", "Errors", new {statusCode = 500});
}
}
}
}
\ No newline at end of file
using System;
namespace PhoneStore.Exceptions
{
public class EntityNotFoundException : Exception
{
public EntityNotFoundException(string message)
: base(message) { }
}
}
\ No newline at end of file
using Microsoft.Extensions.DependencyInjection;
using PhoneStore.Models;
using PhoneStore.Repositories;
using PhoneStore.Repositories.Interfaces;
......@@ -11,6 +12,7 @@ namespace PhoneStore.Helpers
services.AddScoped<IFeedbackRepository, FeedbackRepository>();
services.AddScoped<IOrderRepository, OrderRepository>();
services.AddScoped<IPhoneRepository, PhoneRepository>();
services.AddScoped<IBrandRepository, BrandRepository>();
return services;
}
}
......
......@@ -26,6 +26,7 @@ namespace PhoneStore.Helpers
services.AddTransient<IFeedbackService, FeedbackService>();
services.AddTransient<IPhoneService, PhoneService>();
services.AddTransient<IOrderService, OrderService>();
services.AddTransient<IBrandService, BrandService>();
return services;
}
}
......
using PhoneStore.Models;
using PhoneStore.ViewModels;
namespace PhoneStore.Mappers
{
public static class BrandMapper
{
public static BrandViewModel MapToBrandViewModel(this Brand self)
{
return new BrandViewModel
{
Id = self.Id,
Name = self.Name
};
}
public static Brand MapToBrand(this BrandViewModel self)
{
return new Brand
{
Id = self.Id,
Name = self.Name
};
}
}
}
\ No newline at end of file
using System;
using System.Linq;
using PhoneStore.Exceptions;
using PhoneStore.Models;
using PhoneStore.ViewModels.PhoneViewModels;
......@@ -6,8 +8,10 @@ namespace PhoneStore.Mappers
{
public static class PhoneMapper
{
public static Phone MapToPhone(this PhoneCreateViewModel self, string imagePath = null)
public static Phone MapToPhone(this PhoneEditCreateViewModel self, string imagePath = null)
{
if (self is null)
throw new EntityNotFoundException("Смартфон не найден");
Phone phone = new Phone
{
Name = self.Name,
......@@ -21,6 +25,9 @@ namespace PhoneStore.Mappers
}
public static PhoneViewModel MapToPhoneViewModel(this Phone self)
{
if (self is null)
throw new EntityNotFoundException("Смартфон не найден");
PhoneViewModel phone = new PhoneViewModel
{
Name = self.Name,
......@@ -37,6 +44,8 @@ namespace PhoneStore.Mappers
public static Phone MapToPhone(this PhoneViewModel self, string imagePath = null)
{
if (self is null)
throw new EntityNotFoundException("Смартфон не найден");
Phone phone = new Phone
{
Name = self.Name,
......
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PhoneStore.Models;
using PhoneStore.Repositories.Interfaces;
namespace PhoneStore.Repositories
{
public class BrandRepository : IBrandRepository
{
private readonly MobileContext _db;
public BrandRepository(MobileContext db)
{
_db = db;
}
public void Create(Brand entity)
{
_db.Brands.Add(entity);
_db.SaveChanges();
}
public async Task CreateAsync(Brand brand)
{
await _db.Brands.AddAsync(brand);
await _db.SaveChangesAsync();
}
public IEnumerable<Brand> GetAll()
=> _db.Brands;
public void Update(Brand entity)
{
_db.Brands.Update(entity);
_db.SaveChanges();
}
public Brand GetById(int id)
{
return _db.Brands.FirstOrDefault(b => b.Id == id);
}
public void Delete(int id)
{
var brand = _db.Brands.FirstOrDefault(b => b.Id == id);
_db.Brands.Remove(brand);
_db.SaveChanges();
}
}
}
\ No newline at end of file
......@@ -23,6 +23,13 @@ namespace PhoneStore.Repositories
.First(f => f.Id == id);
}
public void Delete(int id)
{
var feedback = _db.Feedbacks.Find(id);
_db.Feedbacks.Remove(feedback);
_db.SaveChanges();
}
public bool CheckFeedbackExists(int userId, int phoneId)
=> _db.Feedbacks.Any(f => f.UserId == userId && f.PhoneId == phoneId);
......
......@@ -5,5 +5,6 @@
void Create(T entity);
void Update(T entity);
T GetById(int id);
void Delete(int id);
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Threading.Tasks;
using PhoneStore.Models;
using PhoneStore.Repositories.Interfaces.Base;
namespace PhoneStore.Repositories.Interfaces
{
public interface IBrandRepository : IBaseOperations<Brand>
{
Task CreateAsync(Brand brand);
IEnumerable<Brand> GetAll();
}
}
\ No newline at end of file
using PhoneStore.Models;
using System.Collections.Generic;
using PhoneStore.Models;
using PhoneStore.Repositories.Interfaces.Base;
namespace PhoneStore.Repositories.Interfaces
{
public interface IPhoneRepository : IBaseOperations<Phone>
{
IEnumerable<Phone> GetByBrandId(int id);
}
}
\ No newline at end of file
......@@ -3,7 +3,6 @@ using System.Linq;
using Microsoft.EntityFrameworkCore;
using PhoneStore.Models;
using PhoneStore.Repositories.Interfaces;
using PhoneStore.Repositories.Interfaces.Base;
namespace PhoneStore.Repositories
{
......@@ -36,6 +35,13 @@ namespace PhoneStore.Repositories
.Include(o => o.User)
.FirstOrDefault(o => o.Id == id);
public void Delete(int id)
{
var order = _db.Orders.Find(id);
_db.Orders.Remove(order);
_db.SaveChanges();
}
public IEnumerable<Order> GetAll()
{
return _db.Orders
......
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using PhoneStore.Models;
using PhoneStore.Repositories.Interfaces;
......@@ -35,5 +36,17 @@ namespace PhoneStore.Repositories
.FirstOrDefault(p => p.Id == id);
return a;
}
public void Delete(int id)
{
var phone = _db.Phones.Find(id);
_db.Phones.Remove(phone);
_db.SaveChanges();
}
public IEnumerable<Phone> GetByBrandId(int id)
{
return _db.Phones.Where(p => p.BrandId == id);
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PhoneStore.Mappers;
using PhoneStore.Models;
using PhoneStore.Repositories.Interfaces;
using PhoneStore.Services.Interfaces;
using PhoneStore.ViewModels;
namespace PhoneStore.Services
{
public class BrandService : IBrandService
{
private readonly IBrandRepository _brandRepository;
public BrandService(IBrandRepository brandRepository)
{
_brandRepository = brandRepository;
}
public async Task CreateAsync(Brand entity)
=> await _brandRepository.CreateAsync(entity);
public void Delete(int id)
=> _brandRepository.Delete(id);
public IEnumerable<BrandViewModel> GetAll()
=> _brandRepository.GetAll().Select(x => x.MapToBrandViewModel());
public void Create(Brand entity)
=> _brandRepository.Create(entity);
}
}
\ No newline at end of file
using System.Collections.Generic;
using PhoneStore.Models;
using PhoneStore.ViewModels;
namespace PhoneStore.Services.Interfaces
{
public interface IBrandService : ICreatable<Brand>, IRemovable
{
IEnumerable<BrandViewModel> GetAll();
}
}
\ No newline at end of file
namespace PhoneStore.Services.Interfaces
{
public interface ICreateViewModelProvider<out TViewModel>
{
TViewModel GetCreateViewModel();
}
}
\ No newline at end of file
using PhoneStore.ViewModels.PhoneViewModels;
namespace PhoneStore.Services.Interfaces
{
public interface IEditViewModelProvider<out TViewModel>
{
PhoneEditViewModel GetEditViewModel(int id);
}
}
\ No newline at end of file
using PhoneStore.Models;
using PhoneStore.ViewModels;
using PhoneStore.ViewModels.PhoneViewModels;
namespace PhoneStore.Services.Interfaces
{
public interface IPhoneService : ICreatable<PhoneCreateViewModel>
public interface IPhoneService :
ICreatable<PhoneCreateViewModel>,
IRemovable,
ICreateViewModelProvider<PhoneEditCreateViewModel>,
IEditViewModelProvider<PhoneEditViewModel>
{
PhoneViewModel GetById(int phoneId);
IndexViewModel GetIndexViewModel (int? brandId);
void Update(Phone phone);
}
}
\ No newline at end of file
namespace PhoneStore.Services.Interfaces
{
public interface IRemovable
{
void Delete(int id);
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
......@@ -8,6 +9,7 @@ using PhoneStore.Mappers;
using PhoneStore.Models;
using PhoneStore.Repositories.Interfaces;
using PhoneStore.Services.Interfaces;
using PhoneStore.ViewModels;
using PhoneStore.ViewModels.Feedback;
using PhoneStore.ViewModels.PhoneViewModels;
......@@ -20,6 +22,7 @@ namespace PhoneStore.Services
private readonly UploadService _uploadService;
private readonly IHostEnvironment _environment;
private readonly IPhoneRepository _phoneRepository;
private readonly IBrandService _brandService;
......@@ -27,13 +30,16 @@ namespace PhoneStore.Services
MobileContext db,
IDefaultPhoneImagePathProvider imagePathProvider,
UploadService uploadService,
IHostEnvironment environment, IPhoneRepository phoneRepository)
IHostEnvironment environment,
IPhoneRepository phoneRepository,
IBrandService brandService)
{
_db = db;
_imagePathProvider = imagePathProvider;
_uploadService = uploadService;
_environment = environment;
_phoneRepository = phoneRepository;
_brandService = brandService;
}
public async Task CreateAsync(PhoneCreateViewModel entity)
......@@ -56,14 +62,33 @@ namespace PhoneStore.Services
await _db.SaveChangesAsync();
}
public PhoneViewModel GetById(int phoneId)
// public PhoneViewModel GetById(int phoneId)
// {
// return _phoneRepository
// .GetById(phoneId)
// .MapToPhoneViewModel();
// }
public IndexViewModel GetIndexViewModel(int? brandId)
{
return _phoneRepository
.GetById(phoneId)
.MapToPhoneViewModel();
IEnumerable<Brand> brands = _db.Brands;
IEnumerable<PhoneViewModel> phones = _db.Phones.Select(x => x.MapToPhoneViewModel());
if (brandId.HasValue)
phones = _phoneRepository.GetByBrandId(brandId.Value).Select(x => x.MapToPhoneViewModel());
return new IndexViewModel
{
Brands = brands,
Phones = phones
};
}
public PhoneViewModel GetPhoneById(int phoneId)
public void Update(Phone phone)
{
_phoneRepository.Update(phone);
}
public PhoneViewModel GetById(int phoneId)
{
var phone = _db.Phones
.Include(p => p.Brand)
......@@ -93,5 +118,36 @@ namespace PhoneStore.Services
};
return phoneViewModel;
}
public void Delete(int id)
{
_phoneRepository.Delete(id);
}
public PhoneEditCreateViewModel GetCreateViewModel()
{
PhoneEditCreateViewModel model = new PhoneCreateViewModel
{
Brands = _brandService.GetAll()
};
return model;
}
public PhoneEditViewModel GetEditViewModel(int id)
{
var brands = _brandService.GetAll();
var phone = _phoneRepository.GetById(id).MapToPhoneViewModel();
PhoneEditViewModel model = new PhoneEditViewModel
{
Id = phone.Id,
Name = phone.Name,
Price = phone.Price,
BrandId = (int)phone.BrandId,
Image = phone.Image,
Brands = brands
};
return model;
}
}
}
\ No newline at end of file
namespace PhoneStore.ViewModels
{
public class BrandViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
}
\ No newline at end of file
using System.Collections.Generic;
using PhoneStore.Models;
using PhoneStore.ViewModels.PhoneViewModels;
namespace PhoneStore.ViewModels
{
public class IndexViewModel
{
public IEnumerable<Phone> Phones { get; set; }
public IEnumerable<PhoneViewModel> Phones { get; set; }
public IEnumerable<Brand> Brands { get; set; }
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using PhoneStore.Models;
namespace PhoneStore.ViewModels.PhoneViewModels
{
public class PhoneCreateViewModel : BaseEntity, IPhoneEditable
public class PhoneCreateViewModel : PhoneEditCreateViewModel
{
[Required(ErrorMessage = "Поле обязательно для заполнения")]
[Remote("CheckName", "PhoneValidator", ErrorMessage = "Имя занято")]
[StringLength(50, MinimumLength = 3, ErrorMessage = "Минимальная длина 3 символа, максимальная - 50")]
public string Name { get; set; }
[Required(ErrorMessage = "Поле обязательно для заполнения")]
[Range(1000, 50000, ErrorMessage = "Значение не валидно, вводить можно знаение от 1000 до 5000")]
public decimal? Price { get; set; }
public int BrandId { get; set; }
public List<Brand> Brands { get; set; }
public IFormFile File { get; set; }
public string Image { get; set; }
}
}
\ No newline at end of file
......@@ -2,11 +2,10 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using PhoneStore.Models;
namespace PhoneStore.ViewModels.PhoneViewModels
{
public interface IPhoneEditable
public class PhoneEditCreateViewModel
{
public int Id { get; set; }
[Required(ErrorMessage = "Поле обязательно для заполнения")]
......@@ -17,7 +16,7 @@ namespace PhoneStore.ViewModels.PhoneViewModels
[Range(1000, 50000, ErrorMessage = "Значение не валидно, вводить можно знаение от 1000 до 5000")]
public decimal? Price { get; set; }
public int BrandId { get; set; }
public List<Brand> Brands { get; set; }
public IEnumerable<BrandViewModel> Brands { get; set; }
public IFormFile File { get; set; }
public string Image { get; set; }
}
......
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using PhoneStore.Models;
namespace PhoneStore.ViewModels.PhoneViewModels
namespace PhoneStore.ViewModels.PhoneViewModels
{
public class PhoneEditViewModel : BaseEntity, IPhoneEditable
public class PhoneEditViewModel : PhoneEditCreateViewModel
{
public string Name { get; set; }
public decimal? Price { get; set; }
public int BrandId { get; set; }
public List<Brand> Brands { get; set; }
public IFormFile File { get; set; }
public string Image { get; set; }
}
}
\ No newline at end of file
@model IPhoneEditable
@model PhoneEditCreateViewModel
@{
ViewBag.Title = "title";
......
@model Phone
@model PhoneViewModel
@{
ViewBag.Title = "title";
......
@model IPhoneEditable
@model PhoneEditViewModel
@{
ViewBag.Title = "Редактирование";
......
@model PhoneStore.ViewModels.PhoneViewModels.IPhoneEditable
@model PhoneStore.ViewModels.PhoneViewModels.PhoneEditCreateViewModel
<div class="mb-3">
<label asp-for="Name" class="form-label">Наименование</label>
<input type="text" class="form-control" asp-for="Name">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment