как избежать дублирования данных запроса MVC

#c# #asp.net-mvc

#c# #asp.net-mvc

Вопрос:

Я создаю интернет-магазин, пытаясь реализовать функцию «детальный просмотр».Товар успешно отображается с необходимыми атрибутами, но при просмотре другого товара предыдущий не удаляется и накапливается в хранилище. Таким образом, форма подробного обзора продукта содержит все продукты, которые я добавил с помощью запроса.

Это класс Detail

 namespace App.Domain.Entities
{
    public class Detail 
    {
        private List<DetailLine> lineCollection = new List<DetailLine>();

        public void AddItem(Product product)
        {
            DetailLine line = lineCollection
                .Where(g => g.Product.ProductId == product.ProductId)
                .FirstOrDefault();

            if (line == null)
            {
                lineCollection.Add(new DetailLine
                {
                    Product = product
                });   
            }

        }
        public IEnumerable<DetailLine> Lines
        {
            get { return lineCollection; }
        }
    }
public class DetailLine
    {
        public Product Product { get; set; }
}
}

  

Это DetailController

 namespace App.Web.Controllers
{
    public class DetailController : Controller
    {
        public ViewResult Index(string returnUrl)
        {
            return View(new DetailIndexViewModel
            {
                Detail = GetDetail(),
                ReturnUrl = returnUrl
            });
        }
        private IProductRepository repository;
        public DetailController(IProductRepository repo)
        {
            repository = repo;
        }
        public RedirectToRouteResult AddToDetail(int productId, string returnUrl)
        {
            Product product = repository.Products
                .FirstOrDefault(g => g.ProductId == productId);

            if (product != null  )
            {
                GetDetail().AddItem(product);
            }
            return RedirectToAction("Index", new { returnUrl });
        }



        public Detail GetDetail()
        {
            Detail detail = (Detail)Session["Detail"];
            if (detail == null)
            {
                detail = new Detail();
                Session["Detail"] = detail;
            }
            return detail;
        }
    }
}
  

Это желаемый результат:
это желаемый результат

Это результат проблемы: этот результат проблемы

Это представление индекса

 @model App.Web.Models.DetailIndexViewModel
@{
    ViewBag.Title = "Подробное описание товара";
}
<table class="table">
    <thead>
        <tr>
            <th>Название</th>
            <th class="text-left">Цена</th>
            <th class="text-left">Вес</th>
            <th class="text-left">Вкус</th>

        </tr>
    </thead>
    <tbody>
        @foreach (var line in Model.Detail.Lines)
        {
            <tr>
                <td class="text-left">@line.Product.Name</td>
                <td class="text-left">@line.Product.Price.ToString("# руб")</td>

                <td class="text-left">@line.Product.Mass</td>
                <td class="text-left">@line.Product.Taste</td>
            </tr>

        }
    </tbody>
</table>
<tr>
    <th class="text-center" >Описание</th>
</tr>
@foreach (var line in Model.Detail.Lines)
{
<div class="container">
    @line.Product.Description

</div>
}

  

Комментарии:

1. Можете ли вы предоставить представление для интерфейса?

2. Кажется, вы продолжаете добавлять элементы в сеанс, даже не удаляя их. Если вы используете MVC так, как он предназначен, вам вообще никогда не понадобится сеанс. Я предлагаю вам переосмыслить свой дизайн

Ответ №1:

В ASP.NET MVC, обычно предпочтительнее использовать метод, отличный от Session , для хранения данных. Session лучше всего использовать для многоэкранных мастеров, где результаты предыдущего просмотра / действия применимы к следующему представлению / действию.

Я дам вам «быстрый» ответ; а затем отредактирую свой ответ позже, чтобы обеспечить «лучший» подход.

Похоже, что вы добавляете несколько продуктовых линеек в Detail класс, не удаляя предыдущие.

Если это список, но вы не хотите показывать более одного, почему он у вас в List ? Прямо сейчас вы, AddItem не удаляя элемент из Session .

Чтобы удалить что-то из Session ; вам нужно будет добавить это в соответствующее место:

 var detail = (Detail)Session["Detail"];
detail.RemoveOlderItems(product);
Session["Detail"] = detail;
  

С RemoveOlderItems выглядит следующим образом:

 public void RemoveOlderItems(Product product)
{
    List<DetailLine> lines = lineCollection
        .RemoveAll(g => g.Product.ProductId != product.ProductId);
    lineCollection = lines;    
}
  

Трудно сказать, что вы пытаетесь показать (я думаю, что отчасти это связано с тем, что мне трудно следить за тем, что показывают скриншоты представления, поскольку это не на моем родном языке; но я слежу за всем, что могу). Но у меня есть еще несколько уточняющих комментариев и вопросов:

На каком уровне абстракции должно быть представление? Detail Заполнен ProductLines ? Вы хотите показать несколько продуктовых линеек? Судя по показанным вами скриншотам, вы действительно хотите показать только один. Если вам нужен только один, тогда я бы List полностью удалил идею и подробно описал один ProductLine .

Если вы можете подробнее рассказать, к какому конечному результату вы стремитесь, и почему у вас есть List , где кажется, что вы хотите показать только один результат, это поможет.

Комментарии:

1. Я сделал «подробный просмотр» на основе функции «Добавить в корзину», теперь я понял, что это неправильное решение. Цель состоит в том, чтобы отобразить продукт с большим количеством атрибутов в другой форме. Например, основная форма содержит 3 атрибута продукта: название, масса, цена. Когда в подробном списке должно быть больше атрибутов: описание, вкус, изображения и т.д..

Ответ №2:

Я решаю решение, добавляющее в DetailController отказ от сеанса:

 public Detail GetDetail()
        {
            Detail detail = (Detail)Session["Detail"];
            if (detail == null)
            {
                detail = new Detail();
                Session["Detail"] = detail;

            }
            else {
                Session.Abandon();
            }

            return detail;
        }
    }
}
  

Однако, как было бы лучше решить такое решение, избегая сеанса?