Search code examples
c#asp.net-mvcforeachhtml-helper

Html helpers for enum in Asp .Net MVC


I have two models classes:

  1. Employee.cs
    public class Employee
    {
        public int Id { get; set; } 
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public ProjectType Project { get; set; }
    }
  1. ProjectType.cs

    public enum ProjectType
    {
        Project1,
        Project2,
        Project3,
        Project4
    }

In the Create view for Employee, I want to display projects with possibility to check few of them.

I have created a foreach loop with Html.RadioButtonFor in Create view

@model App.Data.Models.Employee
@using App.Data.Models;
    
@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
}

<div class="form-horizontal">

<div class="form-group">
   @Html.LabelFor(model => model.Project, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @foreach (var project in Enum.GetValues(typeof(ProjectType)))
        {
        <div class="col-md-10">

            @Html.RadioButtonFor(m => m.Project, project)
            @Html.Label(project.ToString())
        </div>
                }
        </div>

        </div>

    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>



Which would work just fine if I would be able to choose more than one option. I am assuming that in this case I should create foreach loop with Html.CheckBoxFor and I was trying to do this like in this instruction -> http://findnerd.com/list/view/How-to-bind-checkbox-with-enum-values-in-MVC/25707/

But it didn't really work: I didn't add anything to ProjectType.cs. I have added one class to Employee.cs

 public class Employee
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public List<EnumModel> CheckBoxProjectType { get; set; }
    }
    public class EnumModel
    {
        public ProjectType ProjectType { get; set; }
        public bool isSelected { get; set; }
    }

And when I was creating a loop in EmployeeController - CheckBoxProjectType was underlined in red:

  public ActionResult Create()
        {
            ProjectType model = new ProjectType();
            model.CheckBoxProjectType = new List<EnumModel>();
            foreach (ProjectType projectType in Enum.GetValues(typeof(ProjectType)))
            {
                model.CheckBoxProjectType.Add(new EnumModel() { ProjectType = projectType, isSelected = false });
            }
            return View();
        }

In create view I was trying to copy the loop from the link I have posted earlier

@model App.Data.Models.Employee
@using App.Data.Models;
    
@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
}

<div class="form-horizontal">
    
       <div class="form-group">
      
            <div class="col-md-10">
                @for (int i = 0; i < Model.CheckBoxProjectType.Count; i++)
                {
                    @Html.DisplayFor(m => m.CheckBoxProjectType[i].ProjectType);
                    @Html.CheckBoxFor(m => m.CheckBoxProjectType[i].isSelected);
                    @Html.HiddenFor(m => m.CheckBoxProjectType[i].ProjectType);
                }


                @Html.ValidationMessageFor(model => model.ProjectType, "", new { @class = "text-danger" })

        

            </div>

        </div>

    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>


Can someone guide me how to create foreach loop for enum?


Solution

  • I can see the error already - "i" is not defined and not assigned. How could you compile this?

     @Html.LabelFor(m => m.CheckBoxProjectType[i].ProjectType);
    

    User just " Projects " instead.

    And I don't see any @model in your create view and acton too.

    public ActionResult Create()
            {
                ProjectType model = new ProjectType();
                  //Where is your ProjectType class?
                 // and why I see an Employee AS a model in your view?
    ......
               
           //you have to change your return to this
    
                return View(model);
            }
    

    And it is better idea to create a special viewModel like this to use as model (put it in a separate file) :

    public class EmployeeViewModel
    {
            public Employee Employee{ get; set; }
            public List<EnumModel> EnumModels{ get; set; }
     }
    

    and your Employee will be:

    public class Employee
        {
            public int Id { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public List<ProjectType > ProjectTypes { get; set; }
        }
    
    

    and your new create action will be like this:

    public ActionResult Create()
            {
                var model = new EmployeeViewModel{
                    Employee=new Employee, 
                    EnumModels=new List<EnumModel>()
                   };
               
                foreach (var projectType in Enum.GetValues(typeof(ProjectType)))
                {
                    model.EnumModels.Add(new EnumModel { ProjectType = projectType, 
                    isSelected = false });
                }
                return View(model);
            }
    

    and in your create view replace Employee by EmployeeModel ( and I think you have to add some Employee input controls too) :

    
    @using App.Data.Models
    @model EmployeeViewModel
        
    @{
        ViewBag.Title = "Create";
    }
    
    <h2>Create</h2>
    
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
    }
    
    <div class="form-horizontal">
        
           <div class="form-group">
          <h5> Projects </h5>
                <div class="col-md-10">
    
                    @for (int i = 0; i < Model.EnumModels.Count; i++)
                    {
                        @Html.DisplayFor(m => m.EnumModels[i].ProjectType);
                        @Html.CheckBoxFor(m => m.EnumModels[i].isSelected);
                        @Html.HiddenFor(m => m.EnumModels[i].ProjectType);
                    }
    
    
                    @Html.ValidationMessageFor(model => model.EnumModels, "", new {  
            class = "text-danger" })
    
                </div>
    
            </div>
    
        </div>
    
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>