Search code examples
asp.net-corec#-8.0.net-3.0

.net core modelstate invalid using selectlist with guid


So i am in the process of creating my 3rd crud service inside my webapp. the webapp is running .net core 3.0. my 2 previous crud apps where project and employee. so a user/employee does some work on a project.

so for my 'work' crud service/application in my creation view I need to have a dropdown of all projects and a dropdown for all employees and a view inputs. for employee and project the id is a guid because its unique. But i am seem to having an issue that my modelstateis always invalid.

ps: also my data model so to say it doesn't make any foreign keys for example project id with work id or employee id."

model for work:

public class Work
    {

        public int Id { get; set; }

        [Required]
        [StringLength(512, ErrorMessage = "Description cannot exceed 512 characters!")]
        public string Description { get; set; }        

        [Required]
        [Display(Name = "Working hours")]
        public double WorkingHours { get; set; }

        [Required]
        [Display(Name = "Employee")]
        public Guid EmployeeId { get; set; }

        public Employee Employee { get; set; }

        [Required]
        [Display(Name = "Project")]
        public Guid ProjectId { get; set; }

        public Projects Project { get; set; }

        [Required]
        public DateTime dateAdded { get; set; }


    }

viewmodel:

public class WorkViewModel
    {
        public IEnumerable<Projects> projects { get; set; }
        public IEnumerable<Employee> employees { get; set; }
        public Guid employeeId { get; set; }
        public Guid projectId { get; set; }
        public Work work { get; set; }
    }

create view:

@model TimeSheetTool.ViewModels.WorkViewModel
@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>

<div class="row">
    <div class="col-sm-4">
        <form asp-action="Save">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <select asp-for="projectId" asp-items="@(new SelectList(Model.projects, "Id", "Name"))">
                    <option>Please select one!</option>
                </select>
                <span asp-validation-for="projectId" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="work.Description" class="control-labels"></label>
                <input asp-for="work.Description" class="form-control" />
                <span asp-validation-for="work.Description" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="work.WorkingHours" class="control-labels"></label>
                <input asp-for="work.WorkingHours" class="form-control" />
                <span asp-validation-for="work.WorkingHours"></span>
            </div>
            <div class="form-group">
                <select asp-for="employeeId" asp-items="@(new SelectList(Model.employees, "Id", "Name"))">
                    <option>Please select one!</option>
                </select>
                <span asp-validation-for="employeeId" class="text-danger"></span>
            </div>

            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-outline-primary" />
            </div>
        </form>
    </div>
</div>
<div>
    <a asp-action="Index">Back to List</a>
</div>

What am I doing wrong with this? as you can see in the create view for select list I have got Id i assume it would actually need guid since i'm using guid but then the app won't work at all.


Solution

  • It is because of the Work property in the view model.

    public Work work { get; set; }
    

    It has validation, which if not satisfied will cause the invalid model state issue

    Add the necessary properties to the view model

    public class WorkViewModel {
        public IEnumerable<Projects> projects { get; set; }
        public IEnumerable<Employee> employees { get; set; }
        public Guid employeeId { get; set; }
        public Guid projectId { get; set; }
        [StringLength(512, ErrorMessage = "Description cannot exceed 512 characters!")]
        public string Description { get; set; }        
        [Display(Name = "Working hours")]
        public double WorkingHours { get; set; }
    }
    

    and populate them as needed when invoking the action to bind the view

    <div class="form-group">
        <label asp-for="Description" class="control-labels"></label>
        <input asp-for="Description" class="form-control" />
        <span asp-validation-for="Description" class="text-danger"></span>
    </div>
    
    <div class="form-group">
        <label asp-for="WorkingHours" class="control-labels"></label>
        <input asp-for="WorkingHours" class="form-control" />
        <span asp-validation-for="WorkingHours"></span>
    </div>
    

    The values can be copied over to the model on post