how to post edited cell back to model when the cell is a dropdown list

Dec 2, 2013 at 7:30 PM
I have a grid. Three columns of my grid are dropdown list. I let the user pick their choice from the dropdown list. And that part works. However, I have hard time sending their choices back to my model. The data for my grid is nothing but a table from EF data context. Here's my code:

view:
    <div id="modifyTestData">
        @Html.Grid(Model.TestData).Columns(columns =>
        {
            columns.Add(c => c.OrderNumber).Titled("Order Number").SetWidth(30).Sortable(true).Filterable(true);
            columns.Add(c => c.PartsToCreate).Titled("Part To Create").SetWidth(5).Encoded(false).Sanitized(false).RenderValueAs(p => Html.DropDownList("partToCreate", Model.GetPartsToCreate(p.PartsToCreate), new { @class = "span1" }).ToHtmlString()).SetWidth(5);
            columns.Add(c => c.DrawingTemplate).Titled("Drawing Template").SetWidth(5).Encoded(false).Sanitized(false).RenderValueAs(p => Html.DropDownList("drawingTemplate", Model.GetDrawingTemplates(p.DrawingTemplate), new { @class = "span2" }).ToHtmlString()).SetWidth(5);
            columns.Add(c => c.Company).Titled("Company").Encoded(false).SetWidth(5).Sanitized(false).RenderValueAs(p => Html.DropDownList("company", Model.GetCompanies(p.Company), new { @class = "testdatawidth" }).ToHtmlString()).SetWidth(5);
            columns.Add(c => c.OutputFormat).Titled("Output Format").SetWidth(5).Encoded(false).Sanitized(false).RenderValueAs(p => Html.DropDownList("outputFormat", Model.GetOutputFormats(p.OutputFormat), new { @class = "span1" }).ToHtmlString());
            columns.Add(c => c.Email).Titled("Email").SetWidth(30);
        }).WithPaging(20)
        <input id="SaveTestData" value="Save Test Data"  type="submit" onclick="location.href='@Url.Action("ModifyTestData", "TestData", new { testData = "Model.TestData" })'"/>
    </div>
controller:
      public ActionResult ModifyTestData(List<TestData> testData)
      {
         ...
         //when I get here, testData has 0 count
         return RedirectToAction("RegressionTest");
      }
model:
      public List<TestData> TestData
      {
         get
         {
            return _dbContext.TestDatas.ToList();
         }
         set
         {
            try
            {
               foreach (TestData td in value)
               {
                  _dbContext.TestDatas.Attach(td);
               }
               _dbContext.SaveChanges();
            }
            catch (Exception ex)
            {
               VPBS.DataUtil.DEWD_Utilities.WriteExceptionToLog("Error in TeklaWebClientMVC--TestData", ex);
            }
         }
      }
From reading some other posts, I wonder I have to implement the dropdown list OnChange event. But if I do that, I don't have a way to modify TestData. I thought Url.Action will do it, but apparently not. Please point me to some direction.

Thanks
Coordinator
Dec 3, 2013 at 2:43 AM
Hi

I guess that problem in the data format, that you post to the server.
If you want that Asp.net MVC frmawork bind posted data to you model, you need to provide them in a special format. Please see http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Dec 4, 2013 at 3:44 PM
well, Steven Sanderson also have a good post about editing a list here, but it does not work out well for me. It wants a form. I added a form, but I have other forms in the page and it does not work well. I ended up making an ajax call.

I recorded the change every time the user makes a change and upload all changes to the server when they click "Save Test Data". Here's the working code, in case somebody wants to go this route:

Jquery code:
        var modifiedTestData = new Array();
        $('.testdata').change(function () {
            var myselected = $("#" + this.id + " option:selected").val();
            modifiedTestData.push({ "TestDataID": this.id, "ModidfiedProperty": this.name, "Value": this.value });
            $("#testDataModifyResult").text("");

        });

        $("#btnSaveTestData").click(function () {
            $.ajax({
                type: 'POST',
                url: '@Url.Action("ModifyTestData", "TestData")',
                dataType: 'json',
                contentType: 'application/json; charset=utf-8',
                data: JSON.stringify({ modifiedTestData: modifiedTestData }),
                cache: false,
                async: false,
                success: function (response) {
                    $("#testDataModifyResult").text(response);
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    alert(errorThrown);
                }
                });
            modifiedTestData = new Array();
        });
view:
    <div id="modifyTestData">
        @Html.Grid(Model.TestData).Columns(columns =>
        {
            columns.Add(c => c.OrderNumber).Titled("Order Number").SetWidth(30).Sortable(true).Filterable(true);
            columns.Add(c => c.PartsToCreate).Titled("Part To Create").SetWidth(5).Encoded(false).Sanitized(false).RenderValueAs(p => Html.DropDownList("partsToCreate", Model.GetPartsToCreate(p.PartsToCreate), new { @class = "span1 testdata", id = p.TestDataID }).ToHtmlString()).SetWidth(5);
            columns.Add(c => c.DrawingTemplate).Titled("Drawing Template").SetWidth(5).Encoded(false).Sanitized(false).RenderValueAs(p => Html.DropDownList("drawingTemplate", Model.GetDrawingTemplates(p.DrawingTemplate), new { @class = "span2 testdata", id = p.TestDataID }).ToHtmlString()).SetWidth(5);
            columns.Add(c => c.Company).Titled("Company").Encoded(false).SetWidth(5).Sanitized(false).RenderValueAs(p => Html.DropDownList("company", Model.GetCompanies(p.Company), new { @class = "testdatawidth testdata", id = p.TestDataID }).ToHtmlString()).SetWidth(5);
            columns.Add(c => c.OutputFormat).Titled("Output Format").SetWidth(5).Encoded(false).Sanitized(false).RenderValueAs(p => Html.DropDownList("outputFormat", Model.GetOutputFormats(p.OutputFormat), new { @class = "span1 testdata", id = p.TestDataID }).ToHtmlString());
            columns.Add(c => c.Email).Titled("Email").SetWidth(30);
        }).WithPaging(20)
        <input id="btnSaveTestData" value="Save Test Data"  type="submit" /><h2 id="testDataModifyResult"></h2>
    </div>
Controller:
      public ActionResult ModifyTestData(List<JSONModifiedData> modifiedTestData)
      {
         if (model.UpdateTestData(modifiedTestData))
            return Json("Test data was modified.", JsonRequestBehavior.AllowGet);
         else
            return Json("Test data was NOT modified Successfully.", JsonRequestBehavior.DenyGet);

      }
Json structure:
   public class JSONModifiedData
   {
      public int TestDataID
      {
         get;
         set;
      }
      public string ModidfiedProperty
      {
         get;
         set;
      }
      public string Value
      {
         get;
         set;
      }
   }
model:
      public bool UpdateTestData(List<JSONModifiedData> modifiedTestData)
      {
         foreach (JSONModifiedData d in modifiedTestData)
         {
            TestData td = _dbContext.TestDatas.Where(rowToModify => rowToModify.TestDataID == d.TestDataID).FirstOrDefault();
            if (td == null)
               throw new Exception("Cannot find test data row");
            switch (d.ModidfiedProperty)
            {
               case "partsToCreate":
                  td.PartsToCreate = d.Value;
                  break;
               case "drawingTemplate":
                  td.DrawingTemplate = "BSL_"+d.Value;
                  break;
               case "company":
                  td.Company = d.Value;
                  break;
               case "outputFormat":
                  td.OutputFormat = d.Value;
                  break;
               default:
                  break;
            }

            _dbContext.SaveChanges();
         }
         return true;
      }
Thanks