0

Trying to get this to work but keep getting null values from the Model.

Controller:

[HttpPost]
public ActionResult Index(OPISPriceReportOLY_Result model)
{
    if (ModelState.IsValid)
    {
        int id = model.orpid;

        using (var context = new IntranetCoreEntities())
        {
            var selected = context.OPISRetailPricings.Find(id);
            selected.DMarkup = model.DMarkup;
            selected.DSell = model.DSell;
            selected.RMarkup = model.RMarkup;
            selected.RSell = model.RSell;
            context.SaveChanges();
        }
    }

    return View("Index", model);
}

View:

@model IEnumerable<OPIS7.Models.OPISPriceReportOLY_Result>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
@using (Html.BeginForm("Index", "OPISPriceReportOLY_Result", FormMethod.Post))
{
    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.cpid)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Zone)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ZoneDescription)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Rack)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ActualProduct)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Cost)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.DMarkup)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.DSell)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.RMarkup)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.RSell)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.DateUpdated)
            </th>
            <th></th>
        </tr>

        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.cpid)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Zone)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.ZoneDescription)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Rack)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.ActualProduct)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Cost)
                </td>
                <td>
                    @Html.TextBoxFor(modelItem => item.DMarkup)
                </td>
                <td>
                    @Html.TextBoxFor(modelItem => item.DSell)
                </td>
                <td>
                    @Html.TextBoxFor(modelItem => item.RMarkup)
                </td>
                <td>
                    @Html.TextBoxFor(modelItem => item.RSell)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.DateUpdated)
                </td>
                <td>
                    <button type="submit">Update</button>
                </td>
            </tr>
        }

    </table>
}

Model:

namespace OPIS7.Models
{
    using System;
    using System.ComponentModel.DataAnnotations;

    public partial class OPISPriceReportOLY_Result
    {
        [Key]
        public int orpid { get; set; }
        public int cpid { get; set; }
        public string Zone { get; set; }
        public string ZoneDescription { get; set; }
        public string Rack { get; set; }
        public string ActualProduct { get; set; }
        public Nullable<double> Cost { get; set; }
        public Nullable<double> DMarkup { get; set; }
        public string DSell { get; set; }
        public Nullable<double> RMarkup { get; set; }
        public Nullable<double> RSell { get; set; }
        public Nullable<System.DateTime> DateUpdated { get; set; }
    }
}

According to documentation this is supposed to work without having to resort to AJAX or JS of any kind but I'm hitting a wall. Any ideas?

7
  • 4
    You appear to be posting a collection of models but your controller expects one. Commented Dec 19, 2018 at 18:35
  • The only model I see is OPISPriceReportOLY_Result .. call me blind but where is the other model? Commented Dec 19, 2018 at 18:44
  • @model **IEnumerable**<OPIS7.Models.OPISPriceReportOLY_Result> Commented Dec 19, 2018 at 18:45
  • 2
    This is the wrong way of using ASP.Net MVC Url Routing <button type="submit">Update</button>. you have to pass just the Id as http get which will redirect to another view with input fields for updating the fields. Use Html.ActionLink and pass Id rather repeating submit button Commented Dec 19, 2018 at 18:47
  • 1
    I'm not saying don't make it a collection, I'm saying that is a problem for the controller that expects a single item. If you only want to modify one model at a time then the way to do it is as @SonalBorkar says - do not use the table to edit, redirect to a form that details that particular selection and post that form to your controller. Commented Dec 19, 2018 at 18:56

1 Answer 1

2

If you just want to take single OPISPriceReportOLY_Result in action method, you will need to move form tag inside for loop.

The clean approach is to create a Partial View. You can read more at Adam Freeman's book.

Index.cshtml

@model IEnumerable<OPISPriceReportOLY_Result>

<table class="table">
    @foreach (var item in Model)
    {
        @Html.Partial("_Result", item)
    }    
</table>

_Result.cshtml

@model OPISPriceReportOLY_Result

@using (Html.BeginForm("Update", "Home", FormMethod.Post))
{
    <tr>
        <td>
            @Html.DisplayFor(x => x.cpid)
            @Html.HiddenFor(x => x.cpid)
        </td>
        <td>
            @Html.DisplayFor(x => x.Zone)
            @Html.HiddenFor(x => x.Zone)
        </td>
        <td>
            @Html.DisplayFor(x => x.ZoneDescription)
            @Html.HiddenFor(x => x.ZoneDescription)
        </td>
        <td>
            @Html.DisplayFor(x => x.Rack)
            @Html.HiddenFor(x => x.Rack)
        </td>
        <td>
            @Html.DisplayFor(x => x.ActualProduct)
            @Html.HiddenFor(x => x.ActualProduct)
        </td>
        <td>
            @Html.DisplayFor(x => x.Cost)
            @Html.HiddenFor(x => x.Cost)
        </td>
        <td>
            @Html.TextBoxFor(x => x.DMarkup)
        </td>
        <td>
            @Html.TextBoxFor(x => x.DSell)
        </td>
        <td>
            @Html.TextBoxFor(x => x.RMarkup)
        </td>
        <td>
            @Html.TextBoxFor(x => x.RSell)
        </td>
        <td>
            @Html.DisplayFor(x => x.DateUpdated)
            @Html.HiddenFor(x => x.DateUpdated)
        </td>
        <td>
            <button type="submit">Update</button>
        </td>
    </tr>

}

Controllers

After updating in database, you cannot return View("Index", model);. Index view is expecting an enumerable. The best approach is to redirect to Index page again.

public class HomeController : Controller
{
    public ActionResult Index()
    {
        List<OPISPriceReportOLY_Result> results = new List<OPISPriceReportOLY_Result>();
        results.Add(new OPISPriceReportOLY_Result { cpid = 1 });
        results.Add(new OPISPriceReportOLY_Result { cpid = 2 });
        results.Add(new OPISPriceReportOLY_Result { cpid = 3 });
        return View(results);
    }

    [HttpPost]
    public ActionResult Update(OPISPriceReportOLY_Result model)
    {
        if (ModelState.IsValid)
        {

            int id = model.orpid;

            using (var context = new IntranetCoreEntities())
            {
                var selected = context.OPISRetailPricings.Find(id);
                selected.DMarkup = model.DMarkup;
                selected.DSell = model.DSell;
                selected.RMarkup = model.RMarkup;
                selected.RSell = model.RSell;
                context.SaveChanges();
            }
        }

        return RedirectToAction("Index");
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

I'm still getting null values in my model when I hit the submit button. It's strange, on the browser side I can see that when I click the button that all the values are being submitted but for some reason they just aren't getting to the controller.
You still need @Html.HiddenFor(modelItem => item.cpid) for every Html.DisplayFor if you want their values in postback. Tip: I'll start with single item post. If it works, then use foreach loop.
Yeah, I figured that was the case so I inserted that, but it's still no-go.
You should not name controller and model same name OPISPriceReportOLY_Result. I also updated my answer regarding return value.
I changed the return View("Index", model); to just return View(). It never gets that far though.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.