Initialize object in Asp.Net MVC

Asked

Viewed 785 times

1

I have a class Cidade who owns the property Estado of the kind Estado:

public class Cidade
{
    [Key]
    public int ID { get; set; }

    [Required(ErrorMessage = "Campo Nome é obrigatório!")]
    public String Nome { get; set; }

    [Required(ErrorMessage = "Campo Estado é obrigatório!")]
    public Estado Estado { get; set; }

    public Cidade() { }

    public Cidade(int ID, String Nome, Estado Estado)
    {
        this.ID = ID;
        this.Nome = Nome;
        this.Estado = Estado;
    }

When I’m gonna register a new one Cidade gives null reference error. I think it is because the object Estado not initialized, but where should I initialize this object? I have tried in the class constructor Cidade, but it didn’t work out.

Follows the method in controller receiving the object Cidade of View for the register.

        [HttpPost]
        [Authorize]
        public ActionResult AddCidade(Cidade cidade)
        {
            if (ModelState.IsValid)
            {
                CidadeDal cd = new CidadeDal();
                cd.Salvar(cidade);
                return RedirectToAction("AddCidade");
            }
            else
            {
                ModelState.AddModelError("", "Houve um problema ao preencher o formulário, verifique os erros e tente novamente!");
                return RedirectToAction("AddCidade");
            }
        }

Follow the View:

@model Projeto_P1.Models.Cidade
@{
    ViewBag.Title = "Cadastro de Cidades";
}

@using (Html.BeginForm("AddCidade", "Cidade", FormMethod.Post))
{
    @Html.ValidationSummary(false, "Ocorreram erros no preenchimento das informações, verifique a lista abaixo e corrija os erros!")
    <div class="container">
        <fieldset>
            <div>
                @Html.Label("Cidade")
                @Html.TextBoxFor(model => model.Nome, new { @class = "maiusculo"})
            </div>
            <div>
                @Html.Label("País")
                @Html.DropDownList("pais", (SelectList)ViewData["paises"], "Selecione", new { id = "PaisID"})
            </div>
            <div>
                @Html.Label("Estado")
                @Html.DropDownListFor(model => model.Estado, Enumerable.Empty<SelectListItem>(), "Selecione")
            </div>

            <br />

            <input type="submit" value="Cadastrar" />
        </fieldset>
    </div>
}

<script type="text/javascript">
    $(document).ready(function () {
        $("#PaisID").change(function () {
            $.ajax({
                url: "/Estado/ListaEstados",
                type: 'POST',
                data: { ID: $(this).val() },
                datatype: 'json',
                success: function (data) {
                    var elements = "";
                    $.each(data, function () {
                        elements = elements + '<option value="' + this.ID + '">' + this.Nome + '</option>'
                    })
                    $('#Estado').empty().attr('disabled', false).append(elements);
                }
            });
        });
    });
</script>
  • 1

    Put the code where you call the City Builder.

  • places on top of its class [Seriazable]

2 answers

1


Your modeling is incorrect. The way it’s done, the ModelBinder (class that converts the values of the View in the parameter passed to the Controller) cannot make the association properly, because Estado is a complex entity, and what is being put on screen is just the Id of the Estado, which is a simpler entity. In this case, an integer.

Modify your Model to the following:

public class Cidade
{
    [Key]
    public int ID { get; set; }
    [Required(ErrorMessage = "Campo Estado é obrigatório!")]
    public int EstadoID { get; set; }

    [Required(ErrorMessage = "Campo Nome é obrigatório!")]
    public String Nome { get; set; }

    public virtual Estado Estado { get; set; }
}

May seem long-winded to have EstadoID and the object virtual Estado separately, but that’s actually how Entity Framework and MVC work. Imagine that you don’t want to use the information from Estado, ie, load it minimally. The only information needed for this is the Id of the Estado.

Builders are not really needed for what you need to do. Using the object initializer @Diegozanardo put in its answer, you can already initialize any object.

Finally, in the View, amend the following:

        <div>
            @Html.Label("País")
            @Html.DropDownList("pais", (SelectList)ViewData["paises"], "Selecione", new { id = "PaisID"})
        </div>
        <div>
            @Html.Label("EstadoID")
            @Html.DropDownListFor(model => model.EstadoID, Enumerable.Empty<SelectListItem>(), "Selecione")
        </div>

This will make the correlation between the integer variable of the Model and the DropDownList.

  • 1

    Gypsy thanks, today I will not be able to take the test, but I will do tomorrow and then put here the result.

  • This approach worked well, thank you very much, it’s really strange to work with the property of the complex type and another property representing the ID of that same property, but it worked.

0

Supposing that your class Estado be the following:

public class Estado
{
    public int ID { get; set; }
    public String Nome { get; set; }
}

To use class constructor Cidade, You’d have to do the following:

var estado = new Estado()
{
    ID = 1,
    Nome = "SP"
}
var cidade = new Cidade(1, "São Paulo", estado);
  • Diego I’m sorry but I don’t understand very well, you tell me to create the object state in the City class when I do the Ubmit in the form Asp.Net will use this constructor to assemble the object state within the city: something else in the example above you created the constructor and put the given ID = 1 Name = São Paulo, these data will come from the View, as it is for me to assemble it dynamically, so that the data entered in the Fomulários are used in this object?

  • @user3670112, put your view and your controller, what you’ve done so far, so I can make a better example.

  • I edited the question and posted there.

Browser other questions tagged

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