Reputation: 31
I create an online store, trying to implement the function "detailed view".The product is successfully displayed with the necessary attributes, but when viewing another product, the previous one is not deleted and accumulates in storage. Thus, the detailed product review form contains all the products that I added using the request.
This is class 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; }
}
}
This is 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;
}
}
}
This is the desired result:
This is trouble result:
This Index View
@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>
}
Upvotes: 3
Views: 132
Reputation: 31
I solve solution adding to DetailController abandon session:
public Detail GetDetail()
{
Detail detail = (Detail)Session["Detail"];
if (detail == null)
{
detail = new Detail();
Session["Detail"] = detail;
}
else {
Session.Abandon();
}
return detail;
}
}
}
However, how would it be better to resolve such a decision, avoiding the session?
Upvotes: 0
Reputation: 57872
In ASP.NET MVC, it's typically preferred to use a method other than Session
to store data. Session
is best used for multi-screen wizards, where the results from the previous view/action are applicable to the next view/action.
I'll give you the 'fast' answer; and then will edit my answer later to provide the 'better' approach.
It looks like you're adding multiple product lines to the Detail
class without removing the previous ones.
If it's a list, but you don't want to show more than one, why do you have it in a List
?
Right now you AddItem
without removing the item from Session
.
To remove something from the Session
; you would need to add this in the appropriate place:
var detail = (Detail)Session["Detail"];
detail.RemoveOlderItems(product);
Session["Detail"] = detail;
With RemoveOlderItems
Looking like this:
public void RemoveOlderItems(Product product)
{
List<DetailLine> lines = lineCollection
.RemoveAll(g => g.Product.ProductId != product.ProductId);
lineCollection = lines;
}
It's hard to tell what you're trying to show (I think part of it is I'm having a hard time following what the screenshots of the view is showing since it's not in my native language; but I'm following as best as I can). But I have a few further clarifying comments and questions:
What level of abstraction should the view be at? Is a Detail
filled with ProductLines
? Are you wanting to show multiple product lines? Based on the screenshots you showed, you really only want to show one. If you only need one, then I'd remove the idea of the List
altogether and have one ProductLine
in the detail.
If you can further elaborate what the end result you're going for is, and why you have a List
where it seems like you only want one result to show, that will help.
Upvotes: 1