Home > Back-end >  Data Annotation Required works but doesn't display error message, when using dropdowns
Data Annotation Required works but doesn't display error message, when using dropdowns

Time:12-14

I'm building a basic project using Visual Studio 2019. All of the input fields work fine, the Required data annotation prevents a submit if the input isn't completed. But all of the dropdown input fields don't display the error message (they work, just don't show any message).

Controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using ImprovedWorkCenter.Context;
using ImprovedWorkCenter.Models;

namespace ImprovedWorkCenter.Controllers
{
    public class PlanController : Controller
    {
        private readonly ImprovedWorkCenterContext _context;

        public PlanController(ImprovedWorkCenterContext context)
        {
            _context = context;
        }

        // GET: Plan/Create
        public IActionResult Create()
        {

            bool existenSocios = _context.Socios.Count() > 0;


            if (!existenSocios)
            {
                ModelState.AddModelError(String.Empty, "No existen socios para asignar un Plan, cargue uno y vuelva a intentar");
                return View();
            }

            var sociosAElegir = from s in _context.Socios
                                select s;

            ViewBag.SociosActividad = new SelectList(sociosAElegir.ToList(), "SocioId", "Nombre", "Apellido");

            return View();
        }

        // POST: Plan/Create
        // To protect from overposting attacks, enable the specific properties you want to bind to, for 
        // more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("PlanId,SocioId,NombreSocio,Precio,TipoPlan")] Plan plan)
        {

            var sociosAElegir = from s in _context.Socios
                                select s;

            ViewBag.SociosActividad = new SelectList(sociosAElegir.ToList(), "SocioId", "Nombre", "Apellido");

            if (ModelState.IsValid)
            {
                var socio = await _context.Socios.FindAsync(plan.SocioId);

                bool existeTipo = _context.Planes.Any(s => s.SocioId == plan.SocioId);

                if (existeTipo)
                {
                    ModelState.AddModelError(String.Empty, "El Socio "   socio.Nombre   " "   socio.Apellido   " ya cuenta con un plan.");

                    return View(plan);
                }

                bool esDeudor = socio.EsDeudor;

                if (esDeudor)
                {
                    ModelState.AddModelError(String.Empty, "No se puede agregar Actividad, el Socio: "   socio.Nombre   " "   socio.Apellido   " es Deudor.");
                    return View(plan);
                }
                plan.NombreSocio = socio.Nombre.ToString()   " "   socio.Apellido.ToString();

                _context.Add(plan);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View(plan);
        }

Model:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace ImprovedWorkCenter.Models
{
    public class Plan
    {
        [Key]
        public int PlanId { get; set; }

        [ForeignKey(nameof(Socio))]
        [Required(ErrorMessage = "Debe seleccionar un Socio.")]
        public int SocioId { get; set; }

        [Display(Name = "Nombre de Socio")]
        public string NombreSocio { get; set; }

        [Required(ErrorMessage = "El Precio del plan es obligatorio")]
        [Range(1, 100000, ErrorMessage = "El Precio debe estar entre {1} y {2} pesos.")]
        public double Precio { get; set; }

        [Display(Name = "Tipo de Plan")]
        [EnumDataType(typeof(TipoPlan))]
        [Required(ErrorMessage = "El tipo de plan es obligatorio.")]
        public TipoPlan TipoPlan { get; set; }

View:

@model ImprovedWorkCenter.Models.Plan

@{
    ViewData["Title"] = "Create";
}

<h1>Agregar Plan</h1>
<hr />
<div >
    <div >
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" ></div>
            @if (ViewBag.SociosActividad != null)
           {
            <label asp-for="SocioId" ></label>
            @Html.DropDownList("SocioId", ViewBag.SociosActividad as SelectList, "Selecciones un Socio...", new { @class = "form-control mb-3" });
           }
            <div >
                <label asp-for="TipoPlan" ></label>
                <select asp-for="TipoPlan"  asp-items="Html.GetEnumSelectList<TipoPlan>()">
                    <option selected="selected" value="">Por favor elija un tipo de Plan</option>
                    <span asp-validation-for="TipoPlan" ></span>

                </select>
            </div>
            <div >
                <label asp-for="Precio" ></label>
                <input asp-for="Precio"  />
                <span asp-validation-for="Precio" ></span>
            </div>
            <div >
                <input type="submit" value="Agregar"  />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Volver</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

This is how it looks when you try to submit without typing any info (only one error message appears): enter image description here

CodePudding user response:

It shows only one error message because only one field has no info. You have specified a default value for your select lists, which is interpreted as a value, too. Remove the third parameters of your Html.DropDownList() calls (third parameter is the default value).

CodePudding user response:

First change your ViewModel like this:

public class RegisterViewModel
{
   //Other Properties
 
   [Required]
   [Display(Name = "Continent")]
   public string SelectedContinent { set; get; }
   public IEnumerable<SelectListItem> Continents{ set; get; }
 
}

In the GETAction method, set the data obtained from the database and set the Continents Collection property of the ViewModel.

public ActionResult DoThatStep()
{
  var vm=new RegisterViewModel();
  //The below code is hardcoded for demo. you may replace with DB data.
  vm.Continents= new[]
  {
    new SelectListItem { Value = "1", Text = "Prodcer A" },
    new SelectListItem { Value = "2", Text = "Prodcer B" },
    new SelectListItem { Value = "3", Text = "Prodcer C" }
  }; 
  return View(vm);
}

And use it in your View.

@model RegisterViewModel
@using(Html.BeginForm())
{
  @Html.ValidationSummary()
 
  @Html.DropDownListFor(m => m.SelectedContinent, 
               new SelectList(Model.Continents, "Value", "Text"), "Select")
 
   <input type="submit" />
}
  • Related