Solved

MVC SaveChanges Model with Nested List?

Posted on 2013-10-27
9
943 Views
Last Modified: 2013-11-06
I have a model with a List and need to save changes. The VS 2012 debugger shows the Edit action model contains all indexed data. I'm used editor templates to achieve this.
The action method posted does not error and does not save the 'Limit' property changes. Help!

[Models]
    public class BudgetEdit
    {
        public List<BudgetList> BudgetList { get; set; }
    }

    public class BudgetList
    {
        public string Name { get; set; }
        public Nullable<int> ItemID { get; set; }
        public decimal Limit { get; set; }
        public System.DateTime Posted { get; set; }
    }


 [Action]
    public ActionResult Edit(Models.BudgetEdit model)
    {            
         var r = context.Budgets.Select(x => x.ItemID == model.BudgetList.FirstOrDefault().ItemID);

          if (r != null)
          {
              TryUpdateModel(r);
              context.SaveChanges();
          }
          return View((model);
     }
0
Comment
Question by:WorknHardr
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
9 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 39606841
What does the view look like?  Is this supposed to be a POST method, with [HttpPost] attribute?
0
 

Author Comment

by:WorknHardr
ID: 39607380
okay, here's the View and Editor Template complete code.

Note: I renamed the above posted model from 'BudgetEdit' to 'BudgetEditView ' because it's more intuitive.

I included a 'For' loop in the Action to step-through each List item, although I still don't have the mapping correct yet.

I've been exploring AutoMapper (unsuccessfully) like so:

[Action]
  public ActionResult Edit(BudgetEditView model)
  {
        for (int i = 0; i < model.BudgetList.Count; i++)
            {
                Budget b = context.Budgets.Find(model.BudgetList(i).ItemID);
                AutoMapper.Mapper.Map(model.BudgetList, b);
                context.SaveChanges();
            }
  }      

[View]
@model BudgetProjectUI.BudgetEditView

 @using (Html.BeginForm("Edit", "Budget", FormMethod.Post))
        {
            @Html.ValidationSummary(false)

            <fieldset>
                <legend>Month/Year </legend>
                <table>
                    <thead>
                        <tr>
                            <td><b>Category</b></td>
                            <td></td>
                            <td><b>Limit</b></td>
                        </tr>
                    </thead>
                    <tbody>

                        @Html.EditorFor(model => @Model.BudgetList)

                    </tbody>
                </table>
            </fieldset>  
                                               
            <input type="submit" value="Save Changes" />

[Editor Template]
@model BudgetProjectUI.BudgetList

<table>
    <tr>        
        <td>@Html.HiddenFor(model => model.BudgetID)</td>
        <td>@Html.HiddenFor(model => model.ItemID)</td>
        <td>@Html.HiddenFor(model => model.CategoryID)</td>
        <td style="width:150px">
            @Model.Name

        </td>
        <td></td>
        <td></td>
        <td>
            <div style="width:50px">
                @Html.EditorFor(model => model.Limit)

            </div>
        </td>
    </tr>
</table>
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 39607580
You have a submit button, but I don't see that the action method has an HttpPost attribute.

Here is some "light reading" that should explain the need for HttpPost:

When to use [HttpGet] vs. [HttpPost] in ASP.NET MVC
http://www.linkedin.com/groups/When-use-HttpGet-vs-HttpPost-43315.S.261572227
0
Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

 

Author Comment

by:WorknHardr
ID: 39607646
Hmmm, interestingly enough the VS 2012 debugger shows the Edit action model contains all indexed data.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 39608761
I overlooked this line, which does the same thing:

@using (Html.BeginForm("Edit", "Budget", FormMethod.Post))

If you are using Entity Framework, it is possible to determine what changes are detected.

public static void TestEntityState(BaseEntity entity)
{
   var state = _dataContext.ObjectStateManager.GetObjectStateEntry(entity);
   var propertyList = state.GetModifiedProperties();

   foreach (var property in propertyList)
   {
       Console.WriteLine("Property {0} changed from {1} to {2}", 
           property,
           state.CurrentValues[property],
          state.OriginalValues[property]);
   }
}

Open in new window

0
 

Author Comment

by:WorknHardr
ID: 39617948
Okay, here's my latest failed attempt to save a collection back to its model. I receive the following error on 'var' below.

Q. So it must be pure Lambda to not error?

 "Error: LINQ to Entities does not recognize the method 'BudgetProjectUI.BudgetList get_Item(Int32)' method, and this method cannot be translated into a store expression."


  public ActionResult Edit(BudgetEditView model)
  {
         for (int i = 0; i < model.BudgetList.Count; i++)
         {
                var changes = (from b in context.Budgets where b.BudgetID == model.BudgetList(i).BudgetID select b.Limit).First();

                changes = model.BudgetList(i).Limit;
                context.SaveChanges();
          }
   }
0
 
LVL 96

Accepted Solution

by:
Bob Learned earned 500 total points
ID: 39625797
I showed you that code, so that you could double check the changes applied to Entity Framework.  That way, you could check to see if Limit was included in the changeset.
0
 

Author Comment

by:WorknHardr
ID: 39627258
Understood! I hope MVC 5 has a better way to do these things. Until then I'll use a reliable FormCollection.
0
 

Author Closing Comment

by:WorknHardr
ID: 39627266
Thx for helping...
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…
This video shows how to use Hyena, from SystemTools Software, to update 100 user accounts from an external text file. View in 1080p for best video quality.

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question