netgen
netgen

Reputation: 35

Data sorting in mvc

I am really new to ASP.net MVC.In my project I have 2 models. Person.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace CleryAct.Models
{
    public class Person
    {
        [Key]
        public string rockets { get; set; }
        public bool csa { get; set; }
        public string fname { get; set; }
        public string lname { get; set; }
        public string email { get; set; }

        public virtual ICollection<Session> Sessions { get; set; }
    }
}

Session.cs

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace CleryAct.Models
{
    public class Session
    {

        [Key]
        public int ID { get; set; }
        public string rockets { get; set; }
        public virtual Person Person { get; set; }
        public DateTime training { get; set; }


    }
}

I also have 1 view folder with a Details and Index view inside. I created this by adding a new scaffolding item under controller and linking it to my Person Model. In my details folder I an trying to sort the list of dates that comes up. I can not figure out how to call on the dates in my sort function. Persons controller Details .cs

public ActionResult Details(string id, string sortOrder)
{
    ViewBag.CurrentSort = sortOrder;
    ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Person person = db.Persons.Find(id);
    if (person == null)
    {
        return HttpNotFound();
    }
    var persons = from s in db.Persons select s;

    switch (sortOrder)
    {
        default:
            persons = persons.OrderBy(s => s.Sessions);
            break;
        case "date_desc":
            persons = persons.OrderByDescending(s => s.Sessions);
            break;
    }
    return View(person);
}

Details view code

<h2>Details</h2>

<div>
  <h4>Person</h4>
  <hr />
  <dl class="dl-horizontal">

    <dt>
            @Html.DisplayNameFor(model => model.lname), @Html.DisplayNameFor(model => model.fname) 
        </dt>

    <dd>
      @Html.DisplayFor(model => model.lname), @Html.DisplayFor(model => model.fname)
    </dd>

    <dt>
            @Html.DisplayNameFor(model => model.rockets)
        </dt>

    <dd>
      @Html.DisplayFor(model => model.rockets)
    </dd>

    <dt>
            @Html.DisplayNameFor(model => model.email)
        </dt>

    <dd>
      @Html.DisplayFor(model => model.email)
    </dd>
    <br />
    <br />
    <dt>
            @Html.DisplayNameFor(model => model.Sessions)
        </dt>
    <dd>
      <table class="table">
        @foreach (var item in Model.Sessions) {
        <tr>
          <td>
            @Html.DisplayFor(modelItem => item.training)
          </td>
        </tr>
        }
      </table>
    </dd>

  </dl>
</div>
<p>
  @Html.ActionLink("Edit", "Edit", new { id = Model.rockets }) | @Html.ActionLink("Back to List", "Index")
</p>

Upvotes: 1

Views: 1137

Answers (3)

Ivan Gritsenko
Ivan Gritsenko

Reputation: 4236

Try this code

public ActionResult Details(string id, string sortOrder)
{
    // don't know what logic stands behind these ViewBag usages.
    // maybe you should get rid of them
    ViewBag.CurrentSort = sortOrder;
    ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    // changes start
    Person person = db.Persons.Include(x => x.Sessions).FirstOrDefault(p => p.rockets == id);
    if (person == null)
        return HttpNotFound();
    person.Sessions = sortOrder == "date_desc" ? 
        person.Sessions.OrderByDescending(s => s.training).ToList() : 
        person.Sessions.OrderBy(s => s.training).ToList();
    // changes end
    return View(person);
}

You must be missing id field on Person class. Also why not to use int id instead of string id in action? You have integer id in Session - public int ID { get; set; }.

Upvotes: 1

Christos
Christos

Reputation: 53958

You just need this:

switch (sortOrder)
{
    case "date_desc":
        person.Sessions = person.Sessions
                                .OrderByDescending(session => session.Training);
        break;
    default:
        person.Sessions = person.Sessions
                                .OrderBy(session => session.Training);
        break;

}

There isn't any reason for fetching all the persons and then ordering them based on sessions. It doesn't make sense. The only thing you need is just to order the Sessions of a person.

Upvotes: 0

JB06
JB06

Reputation: 1931

case "date_desc":
  persons = persons.OrderByDescending(s => s.Sessions.Select(t => t.training));
  break;

The .Select() will create a collection of the training dates from the Sessions for you to order.

Upvotes: 0

Related Questions