displaying validation message on razor page when using viewbag

Anjali Agarwal 1,531 Reputation points
2024-11-30T06:53:38.3633333+00:00

I have the following code:

Model:

public partial class EmployeeInfo
{
[DisplayName("First Name")]
[Required(ErrorMessage = "First Name is required")]
public string FirstName { get; set; } 
[Required(ErrorMessage = "Job Title is required.")]
[DisplayName("Job Title")]
public virtual JobTitleLookup JobTitleLookup { get; set; }
}
 public class JobTitleLookup
 {
     
     public int JobTitleLookupId { get; set; }
     
     public string Title { get; set; } = null!;
     public virtual List<EmployeeInfo> EmployeeInfos { get; } = new List<EmployeeInfo>();
 }

This is the controller:

  public async Task<IActionResult> Index()
 {
     jobTitle = await _Reassign.GetJobTitle();
	 ViewData["Jobs"] = new SelectList(jobTitle, "JobTitleLookupId", "Title");
 }
 

// this is inside the service

  public async Task<List<JobTitleLookup>> GetJobTitle()
 {
     return await _ackContext.JobTitleLookup.OrderBy(c => c.Title).ToListAsync();
 }

this is the view:

 <div class="col-md-4">
        <label asp-for="JobTitleLookup" class="control-label" style="font-weight:bold;"></label>
        <select asp-for="JobTitleLookup" class="form-control" asp-items="ViewBag.Jobs">
            <option value="0">--Please select--</option>
    </select>
       
        <span asp-validation-for="JobTitleLookup" class="text-danger"></span>
</div>

when I run the code, I dont see the error message that Job Title is required. However, I see the error message saying "First name is required". I also tried to put this code inside the controller:

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Index(EmployeeInfo info)
    {
        if (info.JobTitleLookupId ==null)
        {
            var validationMessage = "Job Title is required";
            this.ModelState.AddModelError("JobTitleLookupId", validationMessage);
        }
        if (ModelState.IsValid)
        {
        }
        return RedirectToAction(nameof(Index));
    }
Still, I don't see the error message. Any help will be highly appreciated.
Developer technologies ASP.NET ASP.NET Core
Developer technologies C#
0 comments No comments
{count} votes

Accepted answer
  1. AgaveJoe 30,126 Reputation points
    2024-11-30T12:09:36.8133333+00:00

    I recommend changing the view model design which makes the standard model validation easier.

    Create a view model that defines the post parameters sent to the post action and include the input validation attributes.

        public class EmployeeInfoViewModel
        {
            [DisplayName("First Name")]
            [Required(ErrorMessage = "First Name is required")]
            public string FirstName { get; set; } = string.Empty;
            [Required(ErrorMessage = "Job Title is required.")]
            [DisplayName("Job Title")]
            public int? JobTitleId { get; set; }
        }
    

    Create the view that matches the view model properties.

    @model EmployeeInfoViewModel
    @{
        ViewData["Title"] = "Job Title Example";
    }
    <div class="container">
        <form method="post">
            <div>
                <label asp-formaction="FirstName" class="control-label" style="font-weight:bold;"></label>
                <input asp-for"FirstName" />
            </div>
            <div>
                <label asp-for="JobTitleId" class="control-label" style="font-weight:bold;"></label>
                <select asp-for="JobTitleId" class="form-control" asp-items="ViewBag.Jobs">
                    <option value="">--Please select--</option>
                </select>
                <span asp-validation-for="JobTitleId" class="text-danger"></span>
            </div>
            <div>
                <input type="submit" value="submit" />
            </div>
        </form>
    </div>
    

    Populate a List<SelectListItem>with the job titles. Pass the job titles (select options) using the ViewBag.

    public class JobTitleController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            ViewBag.Jobs = PopulateOptions();
            return View();
        }
        [HttpPost]
        public IActionResult Index(EmployeeInfoViewModel model)
        {
            ViewBag.Jobs = PopulateOptions();
            return View();
        }
        private List<SelectListItem> PopulateOptions()
        {
            List<SelectListItem> options = new List<SelectListItem>()
            {
                new SelectListItem()
                {
                    Text = "Job Title 1",
                    Value = "1"
                },
                new SelectListItem()
                {
                    Text = "Job Title 2",
                    Value = "2"
                },
                new SelectListItem()
                {
                    Text = "Job Title 3",
                    Value = "3"
                }
            };
            return options;
        }
    }
    

    The official tutorials and documentation covers these concepts.

    https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/?view=aspnetcore-9.0

    https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-9.0

    1 person found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2024-11-30T17:13:03.2966667+00:00

    As JobTitleLookupId is a non nullable int, it will never be null. As there is no code to set the value, not sure why you check it. As suggested you should map the select to this field. Also unassigned would be 0

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.