Validation DropDownList value from ViewModel in ASP.Net MVC

I tried to search posts, without any result either, maybe I didn’t use the right words.

I need a solution in MVC for validate the DropDownList value, populated from database using Model class and the Html.DropDownListFor Helper method and MySql.

In the view I have added new DDL and this is populated correctly from database

    @Html.DropDownListFor(m => m.Fruits, Model.Fruits, "[ === Please select === ]", new { @Class = "textarea" })
    @Html.ValidationMessageFor(m => m.Fruits, "", new { @class = "text-danger" })

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

But when on click the

<input type="submit" value="Create" class="btn btn-default" />

The form is validate and does not stop sending when the DDL has not selected any value.

Without DDL the validation working correctly.

Please, help me.

My code below

Model

namespace InsGE.Models
{
    public class PersonModel
    {
        [Required]
        [Display(Name = "Fruits")] 
        public List<SelectListItem> Fruits { get; set; }

        public string Namex { get; set; }
        
        public string Codex { get; set; }

        [Required]
        [Display(Name = "CL")] 
        public string CL { get; set; }

        [Required]
        [Display(Name = "Ticket")]
        public string Ticket { get; set; }
    }
}

Controller

namespace InGE.Controllers
{
    public class HomeController : Controller
    {
        private static List<SelectListItem> PopulateFruits()
        {
            string sql;

            List<SelectListItem> items = new List<SelectListItem>();

            string constr = ConfigurationManager.ConnectionStrings["cn"].ConnectionString;

            using (MySqlConnection con = new MySqlConnection(constr))
            {
                sql = @String.Format("SELECT * FROM `dotable`; ");

                using (MySqlCommand cmd = new MySqlCommand(sql))
                {
                    cmd.Connection = con;
                    con.Open();

                    using (MySqlDataReader sdr = cmd.ExecuteReader())
                    {
                        while (sdr.Read())
                        {
                            items.Add(new SelectListItem
                            {
                                Text = sdr["sName"].ToString(),
                                Value = sdr["sCode"].ToString()
                            });
                        }
                    }
                    con.Close();
                }
            }

            return items;
        }

        [HttpPost]
        public ActionResult Index(PersonModel person)
        {
            string sCl = person.CL;
            string sTicket = person.Ticket;       
            string sName = person.Namex;
            string sCode = person.Codex;

            return View();
        }

        [HttpGet]
        public ActionResult Index()
        {
            PersonModel fruit = new PersonModel();
            fruit.Fruits = PopulateFruits();
            return View(fruit);
        }

        public ActionResult About()
        {
           ViewBag.Message = "Your application description page.";    
           return View();
        }

        public ActionResult Contact()
        {
           ViewBag.Message = "Your contact page.";    
           return View();
        }

update

Controller

   public class HomeController : Controller
    {
        public class Fruit
        {
            public string Code { get; }
            public string Name { get; }

            public Fruit(string code, string name)
            {
                Code = code;
                Name = name;
            }
        }

        public class FruitsRepository
        {
            private static List<Fruit> GetAll()
            {
                string sql;

                var fruits = new List<Fruit>();

                string constr = ConfigurationManager.ConnectionStrings["cn"].ConnectionString;

                using (MySqlConnection con = new MySqlConnection(constr))
                {
                    sql = @String.Format("SELECT * FROM `dotable`; ");

                    using (MySqlCommand cmd = new MySqlCommand(sql))
                    {
                        cmd.Connection = con;
                        con.Open();

                        using (MySqlDataReader sdr = cmd.ExecuteReader())
                        {
                            while (sdr.Read())
                            {
                                var fruit = new Fruit(sdr["sCode"].ToString(), sdr["sName"].ToString());
                                fruits.Add(fruit);
                            }
                        }
                        con.Close();
                    }
                }

                return fruits;
            }
        }

        [HttpGet]
        public ActionResult Index() <<<<<< Error “not all code paths return a value”
        {
            var personModel = new PersonModel();
            var fruitsRepo = new FruitsRepository();
            var fruits = fruitsRepo.GetAll(); <<<<<< Error “is inaccessible due to its protection level”
            var fruitsSelecteListItems = fruits.Select(fruit => new SelectListItem
            {
                Text = fruit.Name;
                Value = fruit.Code; <<<<<< Error “The name 'Value' does not exist in the current context”
            });
        return View(personModel); <<<<<<Error “The type or namespace name could not be found”
    }

Model

public class PersonModel
{
    [Required]
    [Display(Name = "Fruits")] 
    public string SelectedFruitCode { get; set; }

    public List<SelectListItem> Fruits { get; set; }

    public string Namex { get; set; }
    
    public string Codex { get; set; }

    [Required]
    [Display(Name = "CL")] 
    public string CL { get; set; }

    [Required]
    [Display(Name = "Ticket")]
    public string Ticket { get; set; }
}

Validation DropDownList value from ViewModel in ASP.Net MVC

Complete View

@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
    @Html.AntiForgeryToken()
    <div>
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <table>
            <tr>
                <td class="textarea">CL</td>
                <td>
                    @Html.TextBoxFor(m => m.CL, new { @Class = "textarea", placeholder = "CL" })
                    @Html.ValidationMessageFor(m => m.CL, "", new { @class = "text-danger" })
                </td>
                <td class="textarea"></td>
            <tr>
                <td class="textarea">Ticket</td>
                <td>
                    @Html.TextBoxFor(m => m.Ticket, new { @Class = "textarea", placeholder = "Ticket" })
                    @Html.ValidationMessageFor(m => m.Ticket, "", new { @class = "text-danger" })
                </td>
                <td class="textarea"></td>
                <td class="textarea">Fruits</td>
                <td>
                    @Html.DropDownListFor(m => m.SelectedFruitCode, Model.Fruits, "[ === Please select === ]", new { @Class = "textarea" })
                    @Html.ValidationMessageFor(m => m.SelectedFruitCode, "", new { @class = "text-danger" })
                </td>
            </tr>
        </table>
        <br />
        <hr class="new3">
        <div class="form-group">
            <div class="col-md-offset-5 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {

    @Scripts.Render("~/bundles/jqueryui")
    @Styles.Render("~/Content/cssjqryUi")

    <script type="text/javascript">
        $(document).ready(function () {
            $('input[type=datetime]').datepicker({
                dateFormat: "dd/mm/yy",
                changeMonth: true,
                changeYear: true,
                yearRange: "-2:+0"
            });
        });
    </script>
}

Complete Controller

public class HomeController : Controller
{

    [HttpPost]
    public ActionResult Index(PersonModel person)
    {
        if (ModelState.IsValid)
        {
            string cl = person.CL;
            string ticket = person.Ticket;
        }

        return View();
    }

   public class Fruit
    {
        public string Code { get; }
        public string Name { get; }

        public Fruit(string code, string name)
        {
            Code = code;
            Name = name;
        }
    }

    public class FruitsRepository
    {
        public List<Fruit> GetAll()
        {
            string sql;

            var fruits = new List<Fruit>();

            string constr = ConfigurationManager.ConnectionStrings["cnx"].ConnectionString;

            using (MySqlConnection con = new MySqlConnection(constr))
            {
                sql = @String.Format("SELECT * FROM `dotable`; ")

                using (MySqlCommand cmd = new MySqlCommand(sql))
                {
                    cmd.Connection = con;
                    con.Open();

                    using (MySqlDataReader sdr = cmd.ExecuteReader())
                    {
                        while (sdr.Read())
                        {
                            var fruit = new Fruit(sdr["sCode"].ToString(), sdr["sName"].ToString());
                            fruits.Add(fruit);
                        }
                    }
                    con.Close();
                }
            }

            return fruits;
        }
    }

    [HttpGet]
    public ActionResult Index()
    {
        var personModel = new PersonModel();
        var fruitsRepo = new FruitsRepository();
        var fruits = fruitsRepo.GetAll();
        var fruitsSelecteListItems = fruits.Select(fruit => new SelectListItem
        {
            Text = fruit.Name,
            Value = fruit.Code
        }).ToList();
        personModel.Fruits = fruitsSelecteListItems;
        return View(personModel);
    }

    public ActionResult About()
    {
        ViewBag.Message = "Your application description page.";
        return View();
    }

    public ActionResult Contact()
    {
        ViewBag.Message = "Your contact page.";
        return View();
    }
}

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You need some changes. Let’s start with database related code. Instead of mixing database related things (MySqlConnection, MySqlCommand etc.) with presentation layer things (SelectListItem, List<SelectListItem> etc.) and doing that also inside a Controller, you should

  • Create a separate class for accessing the database and fetching the data.
  • The method that would be called should return a List of some kind of domain/entity object that would represent the Fruit.

So, let’s define initially our class, Fruit:

public class Fruit
{
    public string Code { get; }
    public string Name { get; }

    public Fruit(string code, string name)
    {
        Code = code; 
        Name = name;
    }
}

Then let’s create a class that would be responsible for accessing the database and fetch the fruits:

public class FruitsRepository
{
    public List<Fruits> GetAll()
    {
        string sql;

        var fruits = new List<Fruit>();

        string constr = ConfigurationManager.ConnectionStrings["cn"].ConnectionString;

        using (MySqlConnection con = new MySqlConnection(constr))
        {
            sql = @String.Format("SELECT * FROM `dotable`; ");

            using (MySqlCommand cmd = new MySqlCommand(sql))
            {
                cmd.Connection = con;
                con.Open();

                using (MySqlDataReader sdr = cmd.ExecuteReader())
                {
                    while (sdr.Read())
                    {
                        var fruit = new Fruit(sdr["sCode"].ToString(), sdr["sName"].ToString());
                        fruits.Add(fruit);
                    }
                }
                con.Close();
            }
        }

        return fruits;
    }
}

Normally, this class should implement an interface, in order we decouple the controller from the actual class that performs the database operations, but let’s not discuss this at this point.

Then at your controller:

  • We should use the above class to fetch the fruits.
  • We should create a list of SelectListItem objects and you would provide that list to the model.
  • We should change the model, in a way that it would hold an info about the selected fruit (check below).
  • We should change the view.

Changes in the model

public class PersonModel
{
    [Required]
    [Display(Name = "Fruits")] 
    public string SelectedFruitCode { get; set; }

    public List<SelectListItem> Fruits { get; set; }

    public string Namex { get; set; }
    
    public string Codex { get; set; }

    [Required]
    [Display(Name = "CL")] 
    public string CL { get; set; }

    [Required]
    [Display(Name = "Ticket")]
    public string Ticket { get; set; }
}

Changes in the View

@Html.DropDownListFor(model => model.SelectedFruitCode, Model.Fruits, "[ === Please select === ]", new { @Class = "textarea" })
@Html.ValidationMessageFor(model => model.SelectedFruitCode, "", new { @class = "text-danger" })

Changes in the Controller

 [HttpGet]
 public ActionResult Index()
 {
     var personModel = new PersonModel();
        
     // THIS IS **BAD CODE**...Normaly, you should create an interface that describes
     // what is expected from the class that communicates with the DB for operations
     // related with the Fruit and then inject the dependency in the HomeController 
     // Constructor. 
        
     var fruitsRepo = new FruitsRepository();
     var fruits = fruitsRepo.GetAll();
     var fruitsSelecteListItems = fruits.Select(fruit => new SelectListItem
     {
         Text = fruit.Name,
         Value = fruit.Code
     }).ToList();
     personModel.Fruits = fruitsSelecteListItems; 
     return View(personModel);
 }

Please check thoroughly the comments in the code above ^^. As a starting point for that mentioned in the comments, you could see this.

UPDATE

We have also to change the post action:

[HttpPost]
public ActionResult Index(PersonModel person)
{
    // Removed the Model.IsValid check since it's redundant in your case
    // Usually we use it and when it is valid we perform a task, like update 
    // the corresponding object in the DB or doing something else. Otherwise,
    // we return a view with errors to the client. 
    var fruitsRepo = new FruitsRepository();
    var fruits = fruitsRepo.GetAll();
    var fruitsSelecteListItems = fruits.Select(fruit => new SelectListItem
    {
        Text = fruit.Name,
        Value = fruit.Code,
        Selected = String.Equals(fruit.Code, 
                                 person.SelectedFruitCode,             
                                        StringComparison.InvariantCultureIgnoreCase)
    }).ToList();

    person.Fruits = fruitsSelecteListItems;         

    return View(person);
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x