0

My question is where to put the logic for the table data that is getting returned.

I'm playing with a tutorial that shows courses and enrollments for students.

here is the data from the screen

Grade Title LastName

2.00 Economics Tibbetts Edit | Details | Delete

3.50 Economics Guzman Edit | Details | Delete

4.00 Literature Catlett Edit | Details | Delete

1.80 Literature Tibbetts Edit | Details | Delete

3.20 Chemistry Tibbetts Edit | Details | Delete

4.00 Chemistry Guzman Edit | Details | Delete

4.00 Literature Pete Edit | Details | Delete

the code started out just showing the table data

@foreach (var item in Model.Enrollments)
{
  <tr>
    <td>
      @Html.DisplayFor(modelItem => item.Course.Title)
     </td>
     <td>
       @Html.DisplayFor(modelItem => item.Grade)
     </td>
     <td>
       @Html.DisplayFor(modelItem => item.Course.Credits)
     </td>
   </tr>
}

I was able to change the tr background red if the grade was <=2 by adding the vars style and style="@style" ( found this on stack overflow)

@foreach (var item in Model.Enrollments)
{
  var style = item.Grade <= 2 ? "background-color:Red" : null;
  <tr style="@style">
    <td>
      @Html.DisplayFor(modelItem => item.Course.Title)
    </td>
    <td>
      @Html.DisplayFor(modelItem => item.Grade)
    </td>
    <td>
      @Html.DisplayFor(modelItem => item.Course.Credits)
    </td>
   </tr>
}

Is this correct, because it is on the view and how would I do something harder like remove the delete action for a title of Economics or not show the user lastname if it starts with a "T" Is this all supposed to be in a PartialView or a controller or both and how to do this. An example would be great. I guess I just don't understand how to massage the data before it gets to a view.

I'm a classic asp doer moving to MVC. I'm realize there is supposed to be a separate of code so that it's not spaghetti like classic, but I'm a newbie and am confused on how to do so. In the old days I would do an if statement and do the logic and then just execute asp and or html based on that.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
dnice
  • 21
  • 7
  • Create view models with additional properties to represent what you want to display. For example, `EnrollmentsViewModel` could include a property `bool CanDelete` that you use for conditionally rendering elements. You the set those properties in the controller before you pass it to the view. –  Dec 07 '14 at 01:10
  • Thanks for the quick reply. So I would have a new folder called viewModels and then I would have a class with a method inside that did the logic. I'm wondering if you have an example or something I could look at. I have never made a view model or really anything yet. – dnice Dec 07 '14 at 01:14
  • Having a separate folder `ViewModels` will make it easier to manage. Just cut and paste the properties of `Enrollment` into `EnrollmentVM` and add new properties as required. Suggest you read [What is a view model in MVC](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) –  Dec 07 '14 at 01:18
  • Ok, I'll check that out. I think the main thing is i'm still trying to get the mvc thing down and I appreciate that It's something that is super easy for you, so thanks for your help and patience – dnice Dec 07 '14 at 01:19
  • I'll post a generic example a little later. –  Dec 07 '14 at 01:33
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Dec 07 '14 at 01:43

1 Answers1

0

While there are no hard and fast rules, using a view model to represent what you want to display will save polluting the view with complex code and keep your logic in the controller. An example of what you could do (you haven't posted you models and the view you posted does not match the table layout, so I'm just guessing)

View models

public class CourseVM
{
  public string Name { get; set; }
  public IEnumerable<EnrollmentVM> Enrollments { get; set; }
}

public class EnrollmentVM
{
  public int ID { get; set; }
  public string Title { get; set; }
  [DisplayFormat(DataFormatString="{0:0.00}")]
  public decimal Grade { get; set }
  public string LastName { get; set; }
  public bool CanDelete { get; set; }
  public string ClassName { get; set; }
}

Controller

public ActionResult Index(int ID)
{
  var course = // get the course based on the ID
  CourseVM model = new CourseVM();
  {
    Name = course.Name,
    Enrollments = course.Enrollments.Select(e => new EnrollmentVM()
    { 
      ID = e.ID,
      Title = e.Title,
      Grade = e.Grade,
      LastName = e.LastName,
      CanDelete = e.Title != "Economics",
      ClassName = e.Grade < 2.0 ? "fail" : "pass"
    })
  };
  return View(model);
}

View

@model CourseVM
<h2>@Html.DisplayFor(m => m.Name)</h2>
<table>
  <thead>
    ...
  </thead>
  <tbody>
    @foreach(var enrollment in Model.Enrollments)
    {
      <tr class="@enrollment.ClassName">
        <td>@Html.DisplayFor(m => enrollment.Grade)</td>
        ....
        <td>@Html.ActionLink("Edit", "Edit", "Enrollment", new { ID = enrollment.ID }, null)</td>
        <td>
          if(enrollment.CanDelete)
          {
            @using(Html.BeginForm("Delete", "Enrollment", new { ID = enrollment.ID })
            {
              <input type="submit" class="deletelink" value="Delete" />
            }
          }
        </td>
      </tr>
    }
  </tbody>
</table>

css

.fail {
  background-color:red;
}
.pass {
  background-color:green;
}
.deletelink {
  // style to look like a hyperlink if required
}
  • thanks stephen. I think this is what i need. I have a long way to go with the learning curve but this will be great to play with and go over – dnice Dec 07 '14 at 06:30