Pass a list of View objects to the Controller

Asked

Viewed 3,970 times

1

I have a Customer class and an address, and a customer can have many addresses. I am trying to create a Client View where I can add as many clients as I want, and then I can add these addresses to the Customer. But does not return the address list when I give Submit.

View to create customers:

@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 view of addresses:

@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 customers:

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

1 answer

5


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

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

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

2. Use the BeginCollectionItem HtmlHelper

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

3. No need to separate Cliente of Enderecos

You suggested the following method signature for the Controller:

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

No need. If the Viewmodel contains addresses, the approach already correctly links the client with the address:

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

The signature of Action would look like this:

public ActionResult Create(ClienteViewModel cliente)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.