2

I am using MVC 4 and I want to get rid of the edit page and just make the change I want on the Index page to multiple items at the same time.

Here is the CSHTML:

@model IEnumerable<HelpDesk.Models.ViewPerm>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>

@using (Html.BeginForm())
{
@Html.ValidationSummary(true)

<fieldset>
    <legend>ViewPerm</legend>
    <table style="border: 5px solid white;">
        <tr>
            <th style="border: 5px solid white;">
                @Html.DisplayNameFor(model => model.Roles.Role)
            </th>
            <th style="border: 5px solid white;">
                @Html.DisplayNameFor(model => model.Views.Page)
            </th>
            <th style="border: 5px solid white;">
                @Html.DisplayNameFor(model => model.Perm)
            </th>
            <th></th>
        </tr>
        @foreach (var item in Model)
        {
            <tr>
                <td style="border: 5px solid white;">
                    @Html.DisplayFor(modelItem => item.Roles.Role)
                </td>
                <td style="border: 5px solid white;">
                    @Html.DisplayFor(modelItem => item.Views.Folder)
                    @Html.DisplayFor(modelItem => item.Views.Page)
                </td>
                <td style="border: 5px solid white;">
                    @Html.EditorFor(modelItem => item.Perm)
                </td>
                <td>                        
                    @Html.ActionLink("Delete", "Delete", new { id = item.VPermID })
                </td>
            </tr>
        }
    </table>
    <input type="submit" value="Save" />
</fieldset>
}


@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

And the C#:

    public ActionResult Index()
    {
        var viewperm = db.ViewPerm.Include(v => v.Roles).Include(v => v.Views);
        return View(viewperm.ToList());
    }

    [HttpPost]
    public ActionResult Index(ViewPerm viewperm)
    {
        if (ModelState.IsValid)
        {
            db.Entry(viewperm).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(viewperm);
    }

When I hit the save button it says "Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries."

Thanks for the help.

Steve Konves
  • 2,648
  • 3
  • 25
  • 44

1 Answers1

2

First problem: Your view deals with multiple ViewPerm, yet your post action only takes one.

Change your post method to deal with multiple:

[HttpPost]
public ActionResult Index(IEnumerable<ViewPerm> viewperms)
{
    if (ModelState.IsValid)
    {
        foreach (ViewPerm viewperm in viewperms)
        {
            db.Entry(viewperm).State = EntityState.Modified;
        }

        db.SaveChanges();
    }

    return View(viewperms);
}

Your second problem is that you're using a foreach to iterate through the items in the Model in your view. The fields need to be indexed correctly so the model binder can do it's stuff (it works on arrays). Change your view to be:

@for (int i = 0; i < Model.Count(); i++)
{
    <tr>
        <td style="border: 5px solid white;">
            @Html.DisplayFor(m => m[i].Roles.Role)
        </td>
        <td style="border: 5px solid white;">
            @Html.DisplayFor(m => m[i].Views.Folder)
            @Html.DisplayFor(m => m[i].Views.Page)
        </td>
        <td style="border: 5px solid white;">
            @Html.EditorFor(m => m[i].Perm)
        </td>
        <td>                        
            @Html.ActionLink("Delete", "Delete", new { id = Model[i].VPermID })
        </td>
    </tr>
}
Mathew Thompson
  • 55,877
  • 15
  • 127
  • 148
  • I run into a in the cshtml at **m[i]**.Roles.Role and those like it and **Model[i]** saying " cannot apply indexing with [] to an expression of type 'System.Collections.Generic.IEnumerable' – user2116960 Feb 27 '13 at 20:56
  • @user2116960 Change your model and your action method to be a `List` instead of an `IEnumerable` – Mathew Thompson Feb 27 '13 at 20:58
  • Sorry, I am still learning MVC. Could you give me an example of that or tell me how to go about doing that. Thank you for your help. – user2116960 Feb 27 '13 at 21:01
  • @user2116960 Change your action method from `public ActionResult Index(IEnumerable viewperms)` to `public ActionResult Index(List viewperms)` and your view model declaration to be `@model List` :) – Mathew Thompson Feb 27 '13 at 21:03
  • Ok. That works but now when I go to save it gives me this error "The entity type List`1 is not part of the model for the current context." on db.Entry(viewperms).State = EntityState.Modified; – user2116960 Feb 27 '13 at 21:08
  • You have to wrap that code in a `foreach` like I said, you need to save each item individually. – Mathew Thompson Feb 27 '13 at 21:15
  • This is what I have in the HttPost: foreach (ViewPerm viewPerm in viewperms) { if (ModelState.IsValid) { db.Entry(viewPerm).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } } return View(viewperms); – user2116960 Feb 28 '13 at 19:45
  • @user2116960 Check my updated edit, I've added the action result method for you. – Mathew Thompson Feb 28 '13 at 20:13
  • oh ok I think I just had the if and foreach backwards. Now I am getting this when it hits db.SaveChanges: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries. – user2116960 Feb 28 '13 at 20:27
  • @user2116960 Check the second answer in this link: http://stackoverflow.com/questions/1836173/entity-framework-store-update-insert-or-delete-statement-affected-an-unexpec debug it and make sure that the IDs match what's in your database. – Mathew Thompson Feb 28 '13 at 20:29
  • @user2116960 Actually hang on, it doesn't look like you have a `HiddenFor` for the `viewperm` ID in your view? Make sure you add that. – Mathew Thompson Feb 28 '13 at 20:30