displaying validation message on razor page when using viewbag

Anjali Agarwal 1,491 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.
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,663 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,090 questions
0 comments No comments
{count} votes

Accepted answer
  1. AgaveJoe 28,786 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) 67,906 Reputation points
    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.