简体   繁体   中英

MVC Edit and Send Model View with Partial Views

I'm working in a project with a View with a complex model (for simplicity I give this example):

public class Person
{
    public string Name { get; set; }
    public string LastName { get; set; }
    public string Data3 { get; set; }
    public string Data4 { get; set; }
    public List<Movie> Movies { get; set; }
}

public class Movie
{
    public string Name { get; set; }
    public double Cost { get; set; }
    public double Quantity { get; set; }
}

I have a Main View Person with two Partial Views "_Movies" and "_Books" with

@Html.Partial("_Movies", Model.Movies)

and

@Html.Partial("_Books", Model.Books)

Each of these partial views have an "add button" which opens a popup which requests the following data:

  • Name of the movie
  • Cost
  • Quantity

The idea is that when I insert this data, it will display a grid with the list of movies and the data entered. Being able to edit or delete this data.

And when I push the button at the bottom "Save all", it post all Model data to the controller.

But I don't know how play with the model data to send it all together. I am desperate.

How can I edit and refresh data of Partial Views and get their data to send the complete model to the controller?

在此处输入图像描述

And my code...

The Main Controller:

public class PersonController : Controller
{
    // GET: Person
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Create()
    {
        ViewBag.Movies = new SelectList(new List<SelectListItem> {
            new SelectListItem { Text = "Lord of the rings", Value = "Lord of the rings"},
            new SelectListItem { Text = "Inception", Value = "Inception"}
        }, "Value", "Text");

        return View(new Person());
    }

    [HttpPost]
    public ActionResult Create(Person person)
    {
        try
        {
            // TODO: Add insert logic here

            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

    [ChildActionOnly]
    public ActionResult RefreshMovies(List<Movie> movies)
    {
        ViewBag.Movies = new SelectList(new List<SelectListItem> {
            new SelectListItem { Text = "Lord of the rings", Value = "Lord of the rings"},
            new SelectListItem { Text = "Inception", Value = "Inception"}
        }, "Value", "Text");

        return PartialView("~/Views/Person/_Movies.cshtml", movies ?? new List<Movie>());
    }
}

The Main View:

@model MisPruebasMVC.Models.Person

@{
    ViewBag.Title = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>General Data</h2>

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

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

            <div class="col-md-4">
                @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label" })
                @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
            </div>
        </div>


        <div class="form-group">
            <div class="col-md-4">
                @Html.LabelFor(model => model.Data3, htmlAttributes: new { @class = "control-label" })
                @Html.EditorFor(model => model.Data3, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Data3, "", new { @class = "text-danger" })
            </div>

            <div class="col-md-4">
                @Html.LabelFor(model => model.Data4, htmlAttributes: new { @class = "control-label" })
                @Html.EditorFor(model => model.Data4, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Data4, "", new { @class = "text-danger" })
            </div>
        </div>


        @Html.Partial("_Movies", Model.Movies ?? new List<MisPruebasMVC.Models.Movie>())

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

The Partial View _Movies.cshtml:

@model IEnumerable<MisPruebasMVC.Models.Movie>


<h2>Movies</h2>

<div class="form-group">
    <button id="addISPCost" type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">
        Add movie
    </button>
</div>

<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title" id="exampleModalLabel">New Movie</h3>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                </button>
            </div>

            <div class="modal-body">
                @{
                    var newMovie = new MisPruebasMVC.Models.Movie();
                }

                <div class="form-group">
                    @Html.LabelFor(m => newMovie.Name, "ISP *:", htmlAttributes: new { @class = "control-label col-md-3" })
                    <div class="col-md-9">
                        @Html.DropDownList("Id_ISP", new SelectList(ViewBag.Movies, "Value", "Text"), "Select a movie", new { @class = "form-control", @id = "IdISP" })
                        @Html.ValidationMessageFor(m => newMovie.Name, "", new { @class = "text-danger" })
                    </div>
                </div>

                <div class="form-group">
                    @Html.LabelFor(m => newMovie.Cost, "Cost:", htmlAttributes: new { @class = "control-label col-md-3" })
                    <div class="col-md-9">
                        @Html.EditorFor(m => newMovie.Cost, new { htmlAttributes = new { @class = "form-control", @id = "Cost" } })
                        @Html.ValidationMessageFor(m => newMovie.Cost, "", new { @class = "text-danger" })
                    </div>
                </div>

                <div class="form-group">
                    @Html.LabelFor(m => newMovie.Quantity, "Quantity:", htmlAttributes: new { @class = "control-label col-md-3" })
                    <div class="col-md-9">
                        @Html.EditorFor(m => newMovie.Quantity, new { htmlAttributes = new { @class = "form-control", @id = "MaximoDiario" } })
                        @Html.ValidationMessageFor(m => newMovie.Quantity, "", new { @class = "text-danger" })
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Cerrar</button>
                <button type="button" class="btn btn-primary" id="saveConfiguracionISP">Aceptar</button>
            </div>
        </div>
    </div>
</div>

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Cost)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Quantity)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Cost)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Quantity)
            </td>
        </tr>
    }

</table>

The _Books Partial View is the same than _Movies Partial View.

I have tried to putting the partials in the same directory than the main and calling them by

@Html.Partial("_Movies", Model.Movies ?? new List<MisPruebasMVC.Models.Movie>())

I also tried with

@Html.Action("RefreshMovies", Model.Movies)

Calling this Action

[ChildActionOnly]
public ActionResult RefreshMovies(List<Movie> movies)
{
    ViewBag.Movies = new SelectList(new List<SelectListItem> {
        new SelectListItem { Text = "Lord of the rings", Value = "Lord of the rings"},
        new SelectListItem { Text = "Inception", Value = "Inception"}
    }, "Value", "Text");

    return PartialView("~/Views/Person/_Movies.cshtml", movies ?? new List<Movie>());
}

Even I tried moving them to the EditorTemplates folder inside the Shared folder calling them by:

@Html.EditorFor(m=> m.Movies, "_Movies") @Html.EditorFor(m=> m.Books, "_Books")

But I don't know how to add the movies and books lists from the partial views to the parent view model to send them to the controller through submit in the BeginForm.

Any idea?

I have achieved to send to the controller the data of the partial views in the Movies and Books properties.

For what I have seen, the view only gets the model when it receives the data from the controller and then it is interpreted as HTML and only the form data is sent to the controller, I have solved it as follows:

To the Person entity, I have added the properties MoviesRequest and BooksRequest of type string. Here I will receive two arrays in JSON format that I will parse to the Movies and Books properties respectively, leaving the class Person as follows:

public class Person
{
    public string Name { get; set; }
    public string LastName { get; set; }
    public string Data3 { get; set; }
    public string Data4 { get; set; }
    public List<Movie> Movies { get; set; }
    public List<Book> Books { get; set; }
    public string MoviesRequest { get; set; }
    public string BooksRequest { get; set; }
}

On the other hand, in the parent view I have added two hidden fields that refer to these two new properties:

@Html.HiddenFor(m=> m.MoviesRequest, new { id = "hiddenMovies" })
@Html.HiddenFor(m=> m.BooksRequest, new { id = "hiddenBooks" })

In the partial view _Books I have in javascript a global variable books , which in the document.ready I set as follows:

books = @Html.Raw(Json.Encode(Model));

And every time I modify the books array, I update the hidden field, assigning it:

$("#hiddenBooks").val(JSON.stringify(books));

The same form partial view _Movies .

And then, in the form post, in the controller, what I do is to parse them to their original property in this way:

[HttpPost]
public ActionResult Create(Person person)
{
    try
    {
        person.Books = JsonConvert.DeserializeObject<List<Books>>(person.BooksRequest);
        person.Movies = JsonConvert.DeserializeObject<List<Movies>>(person.MoviesRequest);
        
        // TODO: Add insert logic here

        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM