Pass a list of View objects to the Controller

1

I have a Client class and an address, and a client can have many addresses. I'm trying to create a View Client where I can add as many clients as I want, and then add those addresses to the Client. But it does not return the address list when I submit.

View of creating clients:

@model SomIluminacao.Application.ViewModel.ClienteViewModel

@{
ViewBag.Title = "Create";
}

<h2>Incluir</h2>


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

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

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

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

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

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

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

@Html.Partial("~/Views/Enderecos/_Create.cshtml")

<div>
@Html.ActionLink("Voltar para lista", "Index")
</div>

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

  <script type="text/javascript">
    function createEndereco() {

        $('#FormEndereco').submit(function (e) {
            e.preventDefault();

            $.ajax({
                type: 'POST',
                url: '/Clientes/CreateEndereco',
                cache: false,
                async: true,
                data: $(this).serialize(),
                datatype: 'html',
                success: function (data) {
                },
                error: function (erro) {
                }
            });
        });

    }
  </script>
}

Partial address view:

@model SomIluminacao.Application.ViewModel.EnderecoViewModel


<form id="FormEndereco">
    @Html.AntiForgeryToken()

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

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

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

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

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

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

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

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

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Incluir" class="btn btn-default" onclick="createEndereco();" />
            </div>
        </div>
    </div>
</form>

Action to add clients:

// POST: Clientes/Create
    [HttpPost]
    public ActionResult Create(ClienteViewModel cliente, List<EnderecoViewModel> enderecos)
    {
        try
        {
            _clienteAppService.Add(cliente, enderecos);
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }
    
asked by anonymous 30.04.2015 / 17:05

1 answer

5

The approach is correct. You need to change some things:

1. The Partial should be created within @Html.BeginForm

This is because all address fields will be treated by form and included in Model Binder .

2. Use BeginCollectionItem HtmlHelper

I've answered very similar questions several times using this component, and I do not find it necessary to repeat the explanation. They are here . See the examples of how to do it. If in doubt, edit your question or leave me comments so I can help you.

3. You do not need to separate% w / w% of% w / w%

You have suggested the following method signature for Controller :

public ActionResult Create(ClienteViewModel cliente, List<EnderecoViewModel> enderecos)

No need. If the ViewModel contains addresses, the approach already binds the client correctly with the address:

public class ClienteViewModel
{
    ...
    public virtual ICollection<EnderecoViewModel> Enderecos { get; set; }
}

The Action signature would look like this:

public ActionResult Create(ClienteViewModel cliente)
    
30.04.2015 / 17:53