0

I have a ViewModel and one of its elements is a list of integers

public class Recurso
{
    [...]

    [Display(Name = "Clientes")]
    public List<int> Clientes { get; set; }
}

I want to get this values from an array of hidden inputs in the form that is posted to this action

[Authorize]
[HttpPost]
public ActionResult AdicionarRecurso(Recurso model)
{
    if (ModelState.IsValid)
    {
        ViewData["sucesso"] = Recursos.NovoRecurso(model);
    }

    return View(model);
}

And in my form, along with fields that correspond to the other parts of my Model, I've got something that goes like

[..]
<input type="hidden" name="Clientes[]" value="1"/>
<input type="hidden" name="Clientes[]" value="15"/>
<input type="hidden" name="Clientes[]" value="17"/>
[...]

I know this is being posted as it should (or at least I thik so) because if Log the form I get this ...&Clientes%5B%5D=1&Clientes%5B%5D=15&Clientes%5B%5D=17

However when debuging Clientes in the Model are still NULL

How am I suposed to achieve this?

EDIT: as requested here is the part of my view that generates the form, the hidden array fields are created dynamicaly so i'll had that javascript par too:

@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "recursoform", enctype = "multipart/form-data" }))
                        {
                            <div class="form-errors">
                                @Html.ValidationSummary(true)
                                <div>@Html.ValidationMessageFor(model => model.Titulo)</div>
                                <div>@Html.ValidationMessageFor(model => model.Descricao)</div>
                                <div>@Html.ValidationMessageFor(model => model.Ficheiro)</div>
                            </div>

                            <div class="clear"></div>

                            <div class="input-prepend">
                                <label for="IDTipoRecurso" class="span3">Tipo de Recurso</label>
                                <select class="span5" id="IDTipoRecurso">
                                    @foreach (var tipoRecurso in (List<SMOnline.Models.TiposRecursos>)ViewBag.tiposRecursos)
                                    {
                                        <option value="@tipoRecurso.IDTipoRecurso">@tipoRecurso.Descricao</option>
                                    }
                                </select>
                            </div>

                            <div class="input-prepend">
                                @Html.LabelFor(model => model.Titulo, new { @class = "span3" })
                                @Html.TextBoxFor(model => model.Titulo, new { @class = "span12", placeholder = "Titulo" })
                            </div>
                            <div class="input-prepend">
                                @Html.LabelFor(model => model.Descricao, new { @class = "span3" })
                                @Html.TextAreaFor(model => model.Descricao, new { @class = "span12", placeholder = "Descrição" })
                            </div>

                            <div class="input-prepend">
                                @Html.LabelFor(model => model.Ficheiro, new { @class = "span3" })
                                <a href="javascrip:;" class="btn btn-large btn-alert span3" style="margin-left: 0;" onclick="getFile()">
                                    Carregar Ficheiro!
                                    <i class="icon-upload icon-large"></i>
                                </a>
                                <label style="padding: 10px 0 0 0;">&nbsp;<i class="icon-ok icon-large" id="fileselected" style="font-size: 30px; color: #090; display: none;"></i></label>
                                <div style='height: 0px;width:0px; overflow:hidden;'>@Html.TextBoxFor(model => model.Ficheiro, null, new { type = "file", @class = "upfile" })</div>
                            </div>

                            <div class="clear">&nbsp;</div>

                            <div class="input-prepend">
                                <label for="Associacao" class="span3">Disponível para</label>
                                <select class="span5" id="Associacao">
                                    <option value="1">Todos os clientes</option>
                                    <option value="2">Tipos de clientes especificos</option>
                                    <option value="3">Clientes especificos</option>
                                </select>

                                <div class="clear"></div>
                            </div>

                            <div class="span3"></div>
                            <div id="clientesEspecificos" class="clientes">
                                <div class="span5" style="margin-left: 0;">
                                    <input type="text" value="" placeholder="Filtrar" id="box" class="span5" style="margin-left: 0;" />
                                    <ul class="navList span5" style="margin-left: 0;">
                                    @foreach (var cliente in (List<SMOnline.Models.Entidades>)ViewBag.clientes)
                                    {
                                        <li><a href="javascript:void(0);" id="[email protected]@cliente.UserName" class="addCliente" title="adicionar cliente à listagem">@Html.Raw(cliente.UserName)</a></li>
                                        <!--<input type="checkbox" name="Clientes[]" id="[email protected]" value="@cliente.IDEntidade" class="pull-left" />
                                        <label for="[email protected]">&nbsp;@Html.Raw(cliente.UserName)</label>-->
                                    }
                                    </ul>
                                </div>
                                <div class="span5">
                                    <div><strong>Clientes Selecionados</strong></div>
                                    <div id="clientesSelect">

                                    </div>
                                </div>
                            </div>
                            <div id="tiposClientes" class="clientes span5">
                                @foreach (var tipo in (List<SMOnline.Models.TiposClientes>)ViewBag.tiposClientes)
                                {
                                    <input type="checkbox" name="TiposClientes[]" id="[email protected]" value="@tipo.IDTipoCliente" class="pull-left" />
                                    <label for="[email protected]">&nbsp;@Html.Raw(tipo.Descricao)</label>
                                }
                            </div>
                            <div class="clear"></div>

                            <div class="box-footer">
                                <a href="@Url.Action("Index", "Admin")" class="btn btn-danger">
                                    <i class="icon-remove"></i>
                                    Cancelar
                                </a>

                                <button type="submit" class="btn btn-primary">
                                    <i class="icon-ok"></i>
                                    Gravar
                                </button>
                            </div>
                        }

javascript:

$('.addCliente').click(function () {
            var splitId = this.id.split("-");

            $(this).fadeOut('slow');

            var clienteAdicionado = '<div class="removeCliente" id="removeCliente-' + splitId[1] + '-' + splitId[2] + '">' + splitId[2] + '</div>';
            clienteAdicionado += '<input type="hidden" name="Clientes[1]" value="' + splitId[1] + '"/>';

            $('#clientesSelect').append(clienteAdicionado);

            removeCliente();
        });

function removeCliente() {
        $('.removeCliente').click(function () {
            var splitId = this.id.split("-");

            $(this).fadeOut('slow', function () { $(this).remove(); });

            $('#cliente-' + splitId[1] + '-' + splitId[2]).fadeIn();
        });
    }

and the initial action:

[Authorize]
    public ActionResult AdicionarRecurso()
    {
        Recurso model = new Recurso();

        string email = this.GetEmailFromCookie();
        string key = Admin.GetUserKey(email);

        ViewData["clientes"] = Admin.GetAllClientes(email);
        ViewData["tiposClientes"] = Admin.GetTiposClientes(email);
        ViewData["tiposRecursos"] = Recursos.GetTiposRecursos(key);

        return View(model);
    }

3 Answers 3

1

the view output that you have shown is wrong:

<input type="hidden" name="Clientes[]" value="1"/>
<input type="hidden" name="Clientes[]" value="15"/>
<input type="hidden" name="Clientes[]" value="17"/>

it should be this way:

<input type="hidden" name="Clientes[0]" value="1"/>
<input type="hidden" name="Clientes[1]" value="15"/>
<input type="hidden" name="Clientes[2]" value="17"/>

This is the reason that the list is null in model on action post

and in your initial action, do like this:

[Authorize]
    public ActionResult AdicionarRecurso()
    {
        Recurso model = new Recurso();

        model.Clientes  = new List<int>();

        string email = this.GetEmailFromCookie();
        string key = Admin.GetUserKey(email);

        ViewData["clientes"] = Admin.GetAllClientes(email);
        ViewData["tiposClientes"] = Admin.GetTiposClientes(email);
        ViewData["tiposRecursos"] = Recursos.GetTiposRecursos(key);

        return View(model);
    }
Sign up to request clarification or add additional context in comments.

7 Comments

it still does the same thing
can you post the action in which you are populating model and passing to view
and also post your complete view
been away for the weekend, i've edited my question with more code
+1 for defining model.Clientes = new List<int>(); in the action but the form part doesn't work, found out the solution however.
|
1

So as Ehsan Sajjad I needed to define model.Clientes = new List<int>(); on the initial action before sending the model to the view.

As for the form in the view, it turns out that if I don't add brackets to name="Clientes[]" nor name="Clientes[1]" and instead just name all of them with name="Clientes"

as in:

<input type="hidden" name="Clientes" value="1"/>
<input type="hidden" name="Clientes" value="15"/>
<input type="hidden" name="Clientes" value="17"/>

The default model binder sees all these name/value pairs with the same name and converts that to a collection with the key ints, which is then matched up with the ints parameter to the action method.

here's the article that guided me in the right direction.

1 Comment

its fine, but in my case passing indexes worked for me
0

First I think you are not passing the model object on your Action, you are passing his field the your model will be null. I suppose maybe retreiving your int by Request in the action and then after correct validationn you can create your model with this field (from request) and pass it to the view.

HttpContext.Current.Request.QueryString["somekey"]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.