Waqar Ahmed
Waqar Ahmed

Reputation: 203

Model is Empty on HTTP POST

Controller

[HttpPost]
public ActionResult SaveProduct(string id, AddProductViewModel m)
{
    if (ModelState.IsValid)
    {
        using (ComparisonDBDataContext CMP = new ComparisonDBDataContext())
        {
            tblProduct prod = (from c in CMP.tblProducts
                               where c.ProductID == Guid.Parse(id)
                               select c).SingleOrDefault();
            prod.Name = m.myName;
            prod.CategoryID = Guid.Parse(m.myCategory);
            prod.ManufacturerID=Guid.Parse(m.myManufacturer);
            CMP.SubmitChanges();
        }
        return RedirectToAction("Products");
    }
    else
    {
        m.ProductID = Guid.Parse(id);
        return View("EditProduct", m);
    }
}

View

@model Comparison.Models.AddProductViewModel 
@{
    ViewBag.Title = "EditProduct";
    Layout = "~/Views/_LayoutData.cshtml";
}

<style>
    .field-validation-error {
        color: Black;
    }
    .validation-summary-errors {
        font-weight: bold;
        color: Black;
    }
</style>
<h2>Edit Product</h2>
@using (Html.BeginForm("SaveProduct", "Home", new { id = @Model.ProductID }, FormMethod.Post))
{
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
        <hr />
        @Html.ValidationSummary(true)
        <div class="form-group">
            <label class="control-label col-md-2" id="lblName">Name</label>
            <div class="col-md-5">
                @Html.TextBoxFor(m => m.myName, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.myName)
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-md-2" id="lblCategory">Category</label>
            <div class="col-md-5">
                @Html.DropDownListFor(m => m.myCategory,  Model.Category, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.myCategory)
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-md-2" id="lblManufucturer">Manufucturer</label>
            <div class="col-md-5">
                @Html.DropDownListFor(m => m.myManufacturer, Model.Manufacturer, new {@class="form-control" })
                @Html.ValidationMessageFor(m => m.myManufacturer)
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Products")
</div>

View Model

public Guid? myUserID;

        [Required(ErrorMessage="Required")]
        public string myCategory;
        public List<SelectListItem> category = new List<SelectListItem>();
        public List<SelectListItem> Category
        {
            get
            {

                category.Clear();
                using (ComparisonDBDataContext CMP = new ComparisonDBDataContext())
                {
                    var cat = from g in CMP.tblCategories
                              select new { g.Name, g.CategoryID };
                    foreach (var q in cat)
                    {
                        category.Add(new SelectListItem() { Text = q.Name, Value = q.CategoryID.ToString() });
                    }
                    return category;
                }
            }
        }
        public Guid? ProductID;

        [Required(ErrorMessage = "Required")]
        public string myManufacturer;
        public List<SelectListItem> manufacturer = new List<SelectListItem>();
        public List<SelectListItem> Manufacturer
        {
            get
            {

                category.Clear();
                using (ComparisonDBDataContext CMP = new ComparisonDBDataContext())
                {
                    var manu = from g in CMP.tblManufacturers
                              select new { g.Name, g.ManufacturerID };
                    foreach (var q in manu)
                    {
                        manufacturer.Add(new SelectListItem() { Text = q.Name, Value = q.ManufacturerID.ToString() });
                    }
                    return manufacturer;
                }
            }
        }

        [Required(ErrorMessage = "Required")]
        [StringLength(100, ErrorMessage = "Maximum lenght can be 100")]
        public string myName;

        public DateTime? CreationDate;

I have tried googling it but could not find any solutions.

I know similar questions are already asked but i couldn't find my solution in them. So kindly just review my code and tell me what I am doing wrong. Why my Model is empty ON POSTBACK?

Upvotes: 0

Views: 402

Answers (1)

user3559349
user3559349

Reputation:

Your view model contains properties with only getters (and in some case they are just fields without any getter or setter) so the DefaultModelBinder cannot set their values. It needs to be

public string myName { get; set; }

Side note: A view model should not contain database access code. It shouldbe simply

public List<SelectListItem> manufacturer { get; set; }

and the controller should be responsible for assigning the collection to the property.

Upvotes: 4

Related Questions