Search code examples
c#asp.net-mvcasp.net-mvc-4model-view

I want to apply for-each loop on two models at same time Asp.Net MVC


I want to apply for each loop on two models at the same time.

My Controller Action Is:

public ActionResult MarkAttendance(int id)
{
    var students = _context.Students.Where(c => c.ClassId == id).ToList();
    var status = _context.Statuses.ToList();

    var viewModel = new AttendanceViewModel
    {
        Student = students,
        Status = status
    };

    return View(viewModel);
}

My Student Model is

 public class Student
{
    public int Id { get; set; }

    [Required]
    [StringLength(30)]
    [RegularExpression(@"^[A-Za-z\s]{1,}[\.]{0,1}[A-Za-z\s]{0,}$", ErrorMessage = "Invalid name. Use letters only")]
    public string Name { get; set; }

    [Required]
    [StringLength(30)]
    [RegularExpression(@"^[A-Za-z\s]{1,}[\.]{0,1}[A-Za-z\s]{0,}$", ErrorMessage = "Invalid name. Use letters only")]
    [Display(Name = "Father Name")]
    public String FatherName { get; set; }

    [Required]
    [Range(0, 10000)]
    public int Fee { get; set; }

    [Required]
    [RegularExpression(@"^((\+92)|(0092))-{0,1}\d{3}-{0,1}\d{7}$|^\d{11}$|^\d{4}-\d{7}$", ErrorMessage = "Please enter only mobile number, Landline not acceptable")]
    [Display(Name = "Student Contact No.")]
    public string StudentContact { get; set; }

    [Required]
    [RegularExpression(@"^[0-9]+$", ErrorMessage = "Please enter correct phone number")]
    [Display(Name = "Guardian Contact No.")]
    public string GuardianContact { get; set; }

    [Required]
    [RegularExpression(@"^[0-9]+$", ErrorMessage = "Enter only numbers")]
    [Display(Name = "Roll Number")]
    [IfRollNoExists]
    public int RollNo { get; set; }

    [Required]
    [Display(Name = "Record Date")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
    public DateTime DateTime { get; set; }

    [Display(Name = "Student Picture")]
    public String ImageURL { get; set; }

    public Class Class { get; set; }

    [Required]
    [Display(Name = "Class Title")]
    public int ClassId { get; set; }

    [ForeignKey("Account")]
    public int AccountId { get; set; }

    public virtual Account Account { get; set; }


}

My Status Class is

  public class Status
{
    public int Id { get; set; }

    public string StudentStatus { get; set; }
}

My ViewModel Is:

public class AttendanceViewModel
{
    public IEnumerable<Student> Student { get; set; }
    public IEnumerable<Status> Status { get; set; }
}

My Razor View is:

@model  Pioneer.ViewModel.AttendanceViewModel
@foreach (var student in Model.Student)
{
    <tr>
        <td>@student.Name</td>
        <td>@student.RollNo</td>
        <td>
            <div data-toggle="buttons">
                <label class="btn btn-success active">
                    @Html.RadioButtonFor(m => m.Status.StudentStatus, "Present", new { id = "1" })
                </label>
                <label class="btn btn-danger">
                    @Html.RadioButtonFor(m => m.Status.StudentStatus, "Absent", new { id = "2" })
                </label>
                <label class="btn btn-primary">
                    @Html.RadioButtonFor(m => m.Status.StudentStatus, "On Leave", new { id = "3" })
                </label>
                <label class="btn btn-warning">
                    @Html.RadioButtonFor(m => m.Status.StudentStatus, "Short Leave", new { id = "4" })
                </label>
            </div>
        </td>                                           
    </tr>
}

Now when I am getting error for using

@Html.RadioButtonFor(m => m.Status.StudentStatus, "Present", new { id = "1" })

Below I attached an image of error. Error Screen Shot

And please tell me can I iterate over my rows without using for-each if I use HTML helper here?


Solution

  • What you are trying to achieve is not possible. As per your view code, the Status model should be part of Student model class class.

    So your view Model will look like this :

    public class AttendanceViewModel
    {
        public IEnumerable<Student> Student { get; set; }
    }
    

    And Student model class will include status :

    public class Student
    {
        public IEnumerable<Status> Status { get; set; }
    }
    

    Now you can access status in your view like this :

    @model  Pioneer.ViewModel.AttendanceViewModel       
    @foreach (var student in Model.Student)
    {
        <tr>
            <td>@student.Name</td>
            <td>@student.RollNo</td>
    
            @foreach(var status in student)
            {
                <td>
                    <div data-toggle="buttons">
                        <label class="btn btn-success active">
                            @Html.RadioButtonFor(status.StudentStatus, "Present", new { id = "1" })
                        </label>
                        <label class="btn btn-danger">
                            @Html.RadioButtonFor(statusStudentStatus, "Absent", new { id = "2" })
                        </label>
                        <label class="btn btn-primary">
                            @Html.RadioButtonFor(status.StudentStatus, "On Leave", new { id = "3" })
                        </label>
                        <label class="btn btn-warning">
                            @Html.RadioButtonFor(status.StudentStatus, "Short Leave", new { id = "4" })
                        </label>
                    </div>
                </td>  
            }
        </tr>
    }
    

    EDIT :

    Or if you're particular about using the same ViewModel as mentioned in the question, you can replace foreach with for. Check below sample code :

    @model  Pioneer.ViewModel.AttendanceViewModel
    @for(var studentIndex = 0; studentIndex < Model.Student.Count(); studentIndex++)
    {
        <tr>
            <td>@Model.Student[studentIndex].Name</td>
            <td>@Model.Student[studentIndex].RollNo</td>
    
            @for(var statusIndex = 0; statusIndex < Model.Status.Count; statusIndex++)
            {
                <td>
                    <div data-toggle="buttons">
                        <label class="btn btn-success active">
                            @Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "Present", new { id = "1" })
                        </label>
                        <label class="btn btn-danger">
                            @Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "Absent", new { id = "2" })
                        </label>
                        <label class="btn btn-primary">
                            @Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "On Leave", new { id = "3" })
                        </label>
                        <label class="btn btn-warning">
                            @Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "Short Leave", new { id = "4" })
                        </label>
                    </div>
                </td>     
            }       
        </tr>
    }