Как правильно создать страницу «Создать» для продуктов с базовым классом? - PullRequest
0 голосов
/ 04 апреля 2019

Допустим, у меня есть базовый класс следующим образом:

public class Product {

        public int Id { get; set; }

        public string Name { get; set; }

        public decimal Price { get; set; }

И у меня есть несколько классов, которые наследуют этот базовый класс:

 public class SomeProduct: Product {

        public string Type { get; set; }

    }
 public class SomeOtherProduct: Product {

        public string Model { get; set; }

    }

Как правильно создать форму для создания каждого из этих продуктов? Создание разных контроллеров и создание страниц для каждого кажется излишним. Какой правильный путь?

1 Ответ

0 голосов
/ 04 апреля 2019

Вы можете создать базовый базовый контроллер:

[Route("[controller]")]
public abstract class BaseProductController<TProduct, TProductModel> : Controller
    where TProduct : Product, new()
    where TProductModel : ProductModel, new()
{
    protected readonly ApplicationDbContext _context;
    protected readonly IMapper _mapper;

    protected BaseProductController(ApplicationDbContext context, IMapper mapper)
    {
        _context = context;
        _mapper = mapper;
    }

    [HttpGet("create")]
    public IActionResult Create()
    {
        return View(new ProductModel());
    }

    [HttpPost("create")]
    public async Task<IActionResult> Create(TProductModel model)
    {
        if (!ModelState.IsValid)
            return View(model);

        var product = _mapper.Map<TProduct>(model);

        _context.Add(product);
        await _context.SaveChangesAsync();

        return RedirectToAction("Index");
    }

    // etc.
}

Затем для каждого типа продукта:

public class SomeProductController : BaseProductController<SomeProduct, SomeProductModel>
{
    public SomeProductController(ApplicationDbContext context, IMapper mapper)
        : base(context, mapper)
    {
    }
}

Примечания:

  • Я предполагаю, что модели представлений, потому что вы используете модели представлений, не так ли?Серьезно, однако, есть множество причин использовать модель представления, особенно для обработки сообщений.Здесь я предполагаю, что вы, вероятно, также создадите модель представления базового продукта.Вы также можете легко использовать простое ограничение class, если хотите разрешить любой тип класса.

  • Для базового контроллера я использовал IMapper из AutoMapper.Вы можете обрабатывать сопоставление другим способом, с другой библиотекой или даже вручную, если хотите.Однако абстракция, предоставляемая библиотекой сопоставлений, такой как AutoMapper, значительно упрощает эту работу.

  • Когда неизбежно необходимо учитывать различия, вы можете справиться с ними с помощью ловушек.Например, вы можете создать метод на базовом контроллере, например:

    public virtual Task BeforeSaveAsync(TProduct product, TProductModel model) =>
        Task.CompletedTask;
    

    , а затем вызвать его в своем действии Create post прямо перед вызовом SaveChangesAsync.Затем в своих производных контроллерах вы можете переопределить этот метод для выполнения любой дополнительной логики, которая вам может потребоваться.По сути, это позволяет вам заглушить функциональность без необходимости повторения всего действия.Вы можете реализовать столько этих типов крючков, сколько вам нужно или нужно.Например, вы можете захотеть разрешить что-то сделать перед проверкой, после сохранения, до того, как представление будет возвращено и т. Д. Или вы можете захотеть иметь такие вещи, как BeforeCreateAsync и BeforeUpdateAsync для реализации различных функций в каждом действии.Это полностью зависит от вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...