0

I am making a website for a friends. I am not very good yet, but I am learning. Here is the problem I am facing.

 public ActionResult CategoryRetail()
    {
        var allCategories = m_db.Categories;
        return View(allCategories);
    }

In the view I use this to display all the categories from the model.

   <ul>
        @foreach (var category in Model)
        {
          <li>@category.CategoryName</li>
        }
   </ul>

Question is, how to display a specific range of categories from the model based on ID? I want to have one section display 7 categories, then other to display the other set and so on. Would like some example of what is available to achieve this.

Ru Ru
  • 137
  • 1
  • 4
  • 18

2 Answers2

0

Instead of simply passing the DB objects into the view, you should create an intermediate object (normally called ViewModel) to hold the different sets of data that your view will need.

So your ViewModel would contain 2 lists of categories, one filtered by one ID, and the other filtered by the other ID.

The view can then access the Model.FirstSetOfCategories for one UI element, and Model.SecondSetOfCategories for another UI element, and so on.

Hope that makes sense...

See here for a nice description of ViewModel.

Community
  • 1
  • 1
demoncodemonkey
  • 11,730
  • 10
  • 61
  • 103
0

You could use a Linq Lambda Expression Where

<ul>
        @foreach (var category in Model.Where(x => x.Id > lowVal && x.Id < highVal))
        {
          <li>@category.CategoryName</li>
        }
</ul>

Though, using Linq could have a performance penalty

If you created a model that has multiple properties for the different collections and use separate queries to populate each property, that may be the better solution.

public class MyModel
{
    public IEnumerable<m_db.Categories> AllCats { get; set; }
    public IEnumerable<m_db.Categories> Cat2 { get; set; }
}

In your view, you would declare your model and iterate through each collection

@model MyProject.Models.MyModel

<ul>
        @foreach (var category in Model.Cat2)
        {
          <li>@category.CategoryName</li>
        }
</ul>

Update

In response to your comment: I typically have a BLL Folder that contains my business layer logic, including methods to populate models. I then only use the controller to pass the populated model to the view. I also typically make the model only have the properties I need. The following sample assumes that you only need a Category ID and a Category Name

Model

public class CategoryModel
{
    public IEnumerable<Category> Section1Categories{ get; set; }
    public IEnumerable<Category> Section2Categories{ get; set; }

    public class Category
    {
        public int Id { get; set; }
        public string Name { get; set; }
    } // end class category
} // end class CategoryModel

Business Logic

public Models.CategoryModel GetAllCategories()
{
    var TheModel = new Models.CategoryModel();
    TheModel.Section1Categories = GetCategoryRange(1, 7);
    TheModel.Section2Categories = GetCategoryRange(7, 9);
} // end Get All Categories

private IEnumerable<Models.CategoryModel.Category> GetCategoryRange(Int32 LowId, Int32 HighId)
{
    // This is using LINQ.  You could accomplish this with other technologies as well
    var cats = (from c in m_db.Category
                where c.Id >= LowId &&
                c.Id <= HighVal
                select new Models.CategoryModel.Category()
                {
                    Id = c.Id,
                    Name = c.Name
                });
    return cats;
} // end GetCategoryRange

Controller

public ActionResult MyPage()
{
    BLL.CategoryMethods cm = new BLL.CategoryMethods();
    Models.CategoryModel TheModel = cm.GetAllCategories();
    return View(TheModel);
} // end MyPage

View

<ul id="CategorySection1">
  @foreach (var cat in Model.Section1Categories)
  {
    <li data-catid="@cat.Id">@cat.Name</li>
  }
<ul>
<ul id="CategorySection2">
  @foreach (var cat in Model.Section2Categories)
  {
    <li data-catid="@cat.Id">@cat.Name</li>
  }
<ul>

Alternatively, you could do this by mapping the categories to a "section" using another table. This may be overkill for the given solution, but works well for larger projects.

Assuming your Category table looks like this:

Id  | CategoryName
-----------  
 1  | Books  
 2  | Music  
 3  | Sports

You could create a Sections Table:

Id  | SectionName
------------------
 1  | Header
 2  | LeftNav
 3  | Footer

Finally, create a CategorySection Table:

Id  | CategoryId | SectionId
----------------------------
 1  |     1      |     3      <-- Maps Books to Footer
 2  |     2      |     1      <-- Maps Music to Header, etc etc

Now, your query could look something like:

var footerCategories = (from c in m_db.Category
                        join cs in m_db.CategorySections on c.Id equals cs.CategoryId
                        where cs.SectionId == 3
                        select new Models.CategoryModel.Category()
                        {
                           Id = c.Id,
                           Name = c.Name
                        });
  • Thanks for your answers guys! I was moving and starting my Masters degree so didn't had time to get back. I got some more questions. What is a good way to populate IEnumerable? What is a good and efficient way to lay it out. – Ru Ru Sep 03 '14 at 07:01
  • [IEnumerable](http://msdn.microsoft.com/en-us/library/9eekhta0.aspx) is an interface that is expecting a collection of some type. Most database queries will work just fine with `IEnumerable`. I've updated my answer. – disappointed in SO leadership Sep 04 '14 at 23:12