#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;
}
}
}
Однако, как было бы лучше решить такое решение, избегая сеанса?