0

Here is my view:

 using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using NHibernate.AspNet.Identity;

    namespace MyProject.Web.Models
    {
        public class IdentityRoleView
        {
            public virtual string Id { get; set; }
            public virtual string Name { get; set; }
            public virtual IList<IdentityUser> Users { get; set; }
        }
    }

Here is my controller:

  [HttpGet]
            public ActionResult Edit(string roleId)
            {
                IdentityRole role = Service.Find(roleId);

                return View("Edit", AutoMapper.Mapper.Map<IdentityRoleView>(role));
            }

            [HttpPost]
            public ActionResult Edit(IdentityRoleView role)
            {
                Service.Update(role);
                TempData["Comment"] = "The record was updated";
                return RedirectToAction("Index");
            }
        }

Here is my view:

@model MyProject.Web.Models.IdentityRoleView
@{
    ViewBag.Title = "Edit";
    Layout = "~/Areas/Administration/Views/Shared/_Layout.cshtml";
}

    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)
        @Html.HiddenFor(model => model.Id);
        <div>
            Role name
        </div>
        <p>
            @Html.TextBoxFor(model => model.Name)
        </p>

         for (int items = 0; items < Model.Users.Count; items++)
            {
                @Html.DisplayFor(m => m.Users[items].Id);
                @Html.DisplayFor(m => m.Users[items].UserName);
            }

        <input type="submit" value="Save" />
    }

IdentityRoleView.Users is always null when it is passed back to the controller. What is the problem? I can see IdentityRoleView.Users on the view - they are all deleted when posted back to the server as IdentityRoleView.Users is always null.

w0051977
  • 15,099
  • 32
  • 152
  • 329
  • 2
    Well, at the very least it's not posting now because there are no form values for that list in your form. The only form value you have is the "Name" property, nothing else. As for how to use the model binder for a list of models, I don't have any ready-made code for that but this looks like a great place to start: https://stackoverflow.com/questions/19964553/mvc-form-not-able-to-post-list-of-objects – David Oct 08 '17 at 13:30
  • So, wait, you just want to pass the current values back into the POST method of the controller? Is that it? Just trying to clarify. – Gary.Taylor717 Oct 08 '17 at 13:59

2 Answers2

0

Here is the viewmodel

  public class IdentityRoleView
    {
        public IdentityRoleView()
        {
            Users = new List<IdentityUser>();
        }
        public virtual string Id { get; set; }
        public virtual string Name { get; set; }
        public virtual IList<IdentityUser> Users { get; set; }
    }

The Controller Methods

  public ActionResult Edit(string roleId)
        {
            IdentityRoleView model = new IdentityRoleView();

            model.Name = "IdentityRoleViewUser";
            model.Id = "2";

            model.Users.Add(new IdentityUser {
                UserName = "testuser",
                Id = "1",
                Email = "test@test.com"
            });

            model.Users.Add(new IdentityUser
            {
                UserName = "testuser2",
                Id = "2",
                Email = "test@test2.com"
            });

            return View("Edit", model);
        }

        [HttpPost]
        public ActionResult Edit(IdentityRoleView model)
        {

            //Your logic
            return RedirectToAction("Index");
        }

Then View

@model MyProject.Web.Models.IdentityRoleView
@{
    ViewBag.Title = "Edit";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    @Html.HiddenFor(model => model.Id);
    <div>
        Role name
    </div>
        <p>
            @Html.TextBoxFor(model => model.Name)
        </p>

for (int i = 0; i < Model.Users.Count(); i++)
{
    @Html.TextBoxFor(model => model.Users[i].Email)
    @Html.TextBoxFor(model => model.Users[i].UserName)

}

            <input type="submit" value="Save" />
}

If you want that user can not edit value then make TextBoxFor readonly.

sina_Islam
  • 1,068
  • 12
  • 19
0

This is a bit of a quirk of MVC.

What you have is mostly correct.

Your controller is just fine:

 [HttpGet]
        public ActionResult Index()
        {
            Person p1 = new Person();
            p1.name = "Ian";

            List<Sport> sports = new List<Sport>();
            Sport s1 = new Sport();
            s1.description = "Football";
            sports.Add(s1);
            Sport s2 = new Sport();
            //s1.description = "Netball";   I'm guessing this is a typo?
            s2.description = "Netball";
            sports.Add(s2);
            p1.sports = sports;

            return View("Person", p1);
        }

        [HttpPost]
        public ActionResult Index(Person p1)
        {
            return View();
        }

However, its the view that has the issue:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Person</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.name, "", new { @class = "text-danger" })
            </div>
        </div>

        @* This is the key difference here *@
        @for (int items = 0; items < Model.sports.Count; items++)
        {
            <div>
                @Html.DisplayFor(sport => Model.sports[items].description)
                @Html.HiddenFor(sport => Model.sports[items].description)
                <hr />
            </div>
        }

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default"/>
            </div>
        </div>

    </div>
}

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

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

So let me explain.

What I did was moved your sports list into the Form(){}. This needs to be done in order to actually have the form pass the objects back. Whatever is in that Form is what it is going to post back.

Another thing you have to do is give the form something to actually bind the model object to. The @Html.DisplayFor helper won't do it, and since it appears you don't want users changing the sports, you can simply create a @Html.HiddenFor. This will pass back the values to your [HttpPost] Index(Person p1) method.

What you do after that, is up to you.

Hope this helps.

Gary.Taylor717
  • 163
  • 1
  • 13
  • Sorry, but this just does not work. There are syntax errors. Once I fixed all the syntax errors; no collection is passed back - it is null. – w0051977 Oct 09 '17 at 09:02