0

In my MVC application, I have a model class like below

public class PROJECT
{
    [Display(Name = "Project No.")]
    public string PROJECT_NO { get; set; }

    [Display(Name = "Title")]
    [DataType(DataType.MultilineText)]
    [Required]
    public string TITLE { get; set; }

    [Display(Name = "Description")]
    [DataType(DataType.MultilineText)]
    public string DESCRIPTION { get; set; }

    [Display(Name = "Remarks")]
    public string REMARKS { get; set; }
}

And I have a ViewModel like this

public class ProjectViewModel
{
    public PROJECT Project { get; set; }

    public bool IsSelected { get; set; }

    public COMPANY Companies { get; set; }

    public CLIENT Clients { get; set; }
}

The ViewModel is the one I am creating the controller and views for. I have created the Index, Details, Delete and Create Views as well. Index, Details and Delete Views just work fine but Create controller model binding does not seem to be working. The ProjectViewModel object that comes in as input to the controller Create is null. How do I bind the ViewModel as a parameter to this object?

    // POST: /Project/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(ProjectViewModel project)
    {
        if (ModelState.IsValid)
        {
            db.PROJECTs.Add(project.Project);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        ViewBag.CLIENT_ID = new SelectList(db.CLIENTs, "ID", "NAME", project.Project.CLIENT_ID);
        ViewBag.COMPANY_ID = new SelectList(db.COMPANies, "ID", "NAME", project.Project.COMPANY_ID);
        return View(project);
    }

And here is the Create View

@model IMCCBluePrints.Models.ProjectViewModel

@{
    ViewBag.Title = "Create";
 }

 <h2>Create</h2>

@using (Html.BeginForm()) 
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>PROJECT</h4>
    <hr />
    @Html.ValidationSummary(true)

    <div class="form-group">
        @Html.LabelFor(model => model.Project.PROJECT_NO, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Project.PROJECT_NO)
            @Html.ValidationMessageFor(model => model.Project.PROJECT_NO)
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Project.TITLE, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Project.TITLE)
            @Html.ValidationMessageFor(model => model.Project.TITLE)
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Project.DESCRIPTION, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Project.DESCRIPTION)
            @Html.ValidationMessageFor(model => model.Project.DESCRIPTION)
        </div>
    </div>




    <div class="form-group">
        @Html.LabelFor(model => model.Project.REMARKS, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Project.REMARKS)
            @Html.ValidationMessageFor(model => model.Project.REMARKS)
        </div>
    </div>



    <div class="form-group">
        @Html.LabelFor(model => model.Project.COMPANY_ID, "COMPANY_ID", new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownList("COMPANY_ID", String.Empty)
            @Html.ValidationMessageFor(model => model.Project.COMPANY_ID)
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Project.CLIENT_ID, "CLIENT_ID", new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownList("CLIENT_ID", String.Empty)
            @Html.ValidationMessageFor(model => model.Project.CLIENT_ID)
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
WAQ
  • 2,556
  • 6
  • 45
  • 86
  • where is the view you post from – Ahmed Dec 21 '16 at 13:28
  • @AhmedRagheb added it just now.. please see the updated question – WAQ Dec 21 '16 at 13:30
  • you should explicitly define your model parameter in Html.BeginForm , like this: @using (Html.BeginForm("Create", "Project", FormMethod.Post, new { project = Model })) – Henrique Forlani Dec 21 '16 at 13:36
  • @WAQ I added Answer, tried it and tell me – Ahmed Dec 21 '16 at 14:12
  • 1
    The dupe explains the issue, but what you doing here is awful practice. A view model does not contain properties which are data models. It contains each property of `Project` that your want to display/edit in the view, along with `IEnumerable` properties for each of your dropdownlists. Refer [What is ViewModel in MVC?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc). And view specific attributes (`[Display]` etc do not belong in your data model - they go in the view model). –  Dec 21 '16 at 23:46
  • 1
    And your dropdownlists do not even correctly 2-way bind to anything and will not give you client side validation (refer [this answer](http://stackoverflow.com/questions/34366305/the-viewdata-item-that-has-the-key-xxx-is-of-type-system-int32-but-must-be-o) for how to generate your dropdownlists) –  Dec 21 '16 at 23:48

2 Answers2

1

In your GET action instantiate your project class and try:

...
ProjectViewModel.project = new PROJECT();
...

return View(ProjectViewModel);
Jaimin Dave
  • 1,224
  • 10
  • 18
0

The Issue that when form submit project conflict with type Project as it is complex type, Just rename it to be model for example

public ActionResult Create(ProjectViewModel model)

try this and it will work, i've tried by myself.

Ahmed
  • 1,542
  • 2
  • 13
  • 21