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" />
}