Home > database >  Save MVC dropdownlist item in database using ViewModel
Save MVC dropdownlist item in database using ViewModel

Time:11-24

I am completely new to the MVC architecure and need help with saving a dropdownlist chosen item in a database. Basically for every Project Model on its Create View I need to have a Dropdown list in which I need to pick an istance of Client (Name of client is displayed in the Dropdonwlist). Based on the chosen client the ClientID should be linked to Project object instance in database upon Post method (as a foreign key).

GET part to display Create and populate Dropdownlist works, POST is what is torturing me.

This is my Project Model:

    public class Project
{
    [Key]
    public int ProjectId { get; set; }
    public string Name { get; set; }
    public string Budget { get; set; }
    public string BusinessCase { get; set; }
    [DataType(DataType.Date)]
    public string StartDate { get; set; }
    [DataType(DataType.Date)]
    public string FinishDate { get; set; }
    public int ClientId { get; set; }
    public Client Client { get; set; }
    public ICollection<ProjectMember> ProjectMembers { get; set; }

    public Project()
    {
    }
}

This is my Client Model:

    public class Client
{
    [Key]
    public int ClientId { get; set; }
    public string Name { get; set; }
    public string State { get; set; }
    public string Address { get; set; }
    public int VAT { get; set; }
    public ICollection<Project> Projects { get; set; }

    public Client()
    {

    }
}

This is my CreateProject ViewModel (some of the attributes might be not needed - I just tried a lot of approaches already...)

public class CreateProjectViewModel
{
    [Key]
    public int ProjectId { get; set; }
    public string Name { get; set; }
    public string Budget { get; set; }
    public string BusinessCase { get; set; }
    [DataType(DataType.Date)]
    public string StartDate { get; set; }
    [DataType(DataType.Date)]
    public string FinishDate { get; set; }
    public int ClientId { get; set; }
    public Client Client { get; set; }
    public ICollection<ProjectMember> ProjectMembers { get; set; }


    public IEnumerable<SelectListItem> Clients { get; set; }
}

This is my Controller GET method for Create (To populate the dropdownlist with Select values from Client table):

   public IActionResult Create()
    {


        var clients = _context.Client.Select(r => r.Name);
        var viewmodel = new CreateProjectViewModel
        {
            Clients = new SelectList(clients)
        };
        
        return View(viewmodel); 

    }

And Finally, this is is the Create View using the CreateProjectViewModel:

@model ProjectPortfolioApp.ViewModels.CreateProjectViewModel
    
    @{
        ViewData["Title"] = "Create";
    }



<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>

            <div class="form-group">

                @Html.LabelFor(model => model.Client.Name, htmlAttributes: new { @class = "control label col-md-2" })
                **@Html.DropDownListFor(model => model.ClientId, Model.Clients, "---Select Client---", new { @class = "form-control" })**
            </div>

The above code works fine for displaying the Dropdown elements as expected (Name of the client) using public IEnumerable<SelectListItem> Clients { get; set; }. What I am struggling with is the POST part where I receive error Object reference not set to an instance of an object. When I post model => model.ClientId If I pass here basically anyhing else e.g model => model.Name there is no error only the Client ID is not succesfully posted in database (obviously).

Here is the snippet of HTTP Post which is most probably wrong:

[ValidateAntiForgeryToken]
    public async Task<ActionResult> Create(CreateProjectViewModel model)
    {
        if (ModelState.IsValid)
        {
            var project = new Project() { Name = model.Name, ClientId = model.ClientId, Budget = model.Budget, BusinessCase = model.BusinessCase, StartDate = model.StartDate, FinishDate = model.FinishDate };
            _context.Add(project);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
       
        return View();

        
    }

Can anyone look at my code and help me identify:

  • Is my GET Create constructed fine to serve the purpose of POST Create
  • What should be passed in @Html.DropDownListFor as valid parameters to avoid the error?
  • What should the HTTP Post Create look like?

I looked in dozens of threads, unfortunately nothing helped. Really any help would be appreciated. Thanks.

CodePudding user response:

you have to fix the action

public IActionResult Create()
{

 var clients = _context.Client
           .Select(r =>  new SelectListItem{ Value= r.ClientId.ToString(), Text= r.Name)
           .ToList();

        var viewmodel = new CreateProjectViewModel
        {
            Clients = clients
             .... another properties
        };
        
        return View(viewmodel); 

    }

and view

@Html.DropDownListFor(model => model.ClientId, @Model.Clients, "---Select Client---", new { @class = "form-control" })
  • Related