Problems saving a selected item in Dropdownlistfor using a Viewmodel

Asked

Viewed 225 times

0

I’m trying to save a change I try to make by selecting a Category in a Dropdownlistfor.

Kind of: View de edição de uma SubCategoria

I keep following the Debug and the View is sending the selected Category, but I am not able to continue this change.

My Subcategory Controller looks like this:

 // GET: SubCategorias/Edit/5
    public ActionResult Edit(Guid? id)
    {
        if (id == null)
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

        SubCategoriaViewModel subCategoriaViewModel =
            _subCategoriaAppService.ObterPorId(id.Value);

        subCategoriaViewModel.Categorias = _categoriaAppService.ObterTodas();

        if (subCategoriaViewModel == null)
            return HttpNotFound();

        return View(subCategoriaViewModel);
    }

    // POST: SubCategorias/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(SubCategoriaViewModel subCategoriaViewModel)
    {            
        _subCategoriaAppService.Atualizar(subCategoriaViewModel);
        return RedirectToAction("Index");
    }

My method for upgrading is like this:

public SubCategoriaViewModel Atualizar(
        SubCategoriaViewModel subCategoriaViewModel)
    {
        //var categoriaSelecionada =
        //     _categoriaService.ObterPorId(subCategoriaViewModel.CategoriaId);
        subCategoriaViewModel.Categoria =
            _categoriaService.ObterPorId(subCategoriaViewModel.CategoriaId);

        var subCategoria =
            Mapper.Map<SubCategoriaViewModel,
            SubCategoria>(subCategoriaViewModel);

        //subCategoria.Categoria = categoriaSelecionada;
        _subCategoriaService.Atualizar(subCategoria);

        return subCategoriaViewModel;
    }

In my View:

<div class="form-group">
        @Html.LabelFor(model => model.Categoria, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(model => model.CategoriaId,
           new SelectList(Model.Categorias, "CategoriaId", "CategoriaNome"), new { @class = "form-control" })              
        </div>
    </div>

My Viewmodel

public class SubCategoriaViewModel
{
    public SubCategoriaViewModel()
    {
        SubCategoriaId = Guid.NewGuid();
    }

    [Key]
    public Guid SubCategoriaId { get; set; }

    [Required(ErrorMessage = ("Preencha o nome da SubCategoria."))]
    [MaxLength(60, ErrorMessage = ("Máximo {0} caracteres."))]
    [MinLength(1, ErrorMessage = ("Mínimo {0} caracteres."))]
    [DisplayName("Nome")]
    public string SubCategoriaNome { get; set; }

    public IEnumerable<CategoriaViewModel> Categorias = new List<CategoriaViewModel>();
    public Guid CategoriaId { get; set; }

    //[ScaffoldColumn(false)]
    //public DomainValidation.Validation.ValidationResult ValidationResult { get; set; }

    public virtual Categoria Categoria { get; set; }
    //public ICollection<Produto> Produtos { get; set; }

}

The interesting thing is that if I modify the name of the subcategory it persisted! Anything, this the way I’m trying to persist this http://imgur.com/a/i75n3

  • How is the subcategory structureViewModel ? Add to question.

  • @LP.Gonçalves I updated the question

  • 1

    Iago Frota, post the solution of the problem and then mark your answer as accepted (I believe it releases only two days later). So future users who are having an equal or similar problem know what to do.

2 answers

1


After much conversation with two good people at heart (Tiago Silva and LP. Gonçalves), we can understand the problem.

The problem was how I was treating the Association Type to save and/or change my entities in the database using the Entity Framework.

Before the solution, I was using Associação Independente which was one of the first forms of association between entities and which used object orientation to make this association. As you may already know, I was misusing the resource. So in conversation with Tiago Silva he explained me the error and why it would be better to use Foreign key association (Foreign Key).

What has changed is my application class, which is now like this:

public SubCategoriaViewModel Atualizar(
        SubCategoriaViewModel subCategoriaViewModel)
    {
        var categoriaSelecionada =
             _categoriaService.ObterPorId(subCategoriaViewModel.CategoriaId);

        var subCategoria =
            Mapper.Map<SubCategoriaViewModel,
            SubCategoria>(subCategoriaViewModel);

        subCategoria.Categoria = categoriaSelecionada;
        _subCategoriaService.Atualizar(subCategoria);

        return subCategoriaViewModel;
    }

And, there was the addition of property public Guid CategoriaId { get; set; } in the Subcategory domain class, to serve as a foreign key in the Category-Subcategory association (1:N). Follows the code:

public class SubCategoria
{
    public Guid SubCategoriaId { get; set; }
    public string SubCategoriaNome { get; set; }
    public virtual Categoria Categoria { get; set; }
    public Guid CategoriaId { get; set; }
    public ICollection<Produto> Produtos { get; set; }

    public SubCategoria()
    {
        SubCategoriaId = Guid.NewGuid();
        Produtos = new List<Produto>();
    }        
}

Who wants to take a look at the material I read on the topic, follow the links

  • Now that I’ve seen that answer boy! Forget my previous comments!

0

If I understand your problem well, the solution is very simple, just fill in the CategoriaId before calling the view.

Yeah, how do you know, CategoriaId is responsible for the value of the selected object in the dropdown, if you do not initialize this variable with the correct value, the dropdown will be displayed the option default which in its case is the first object of the list of Categorias.

The solution to your problem is:

subCategoriaViewModel.CategoriaId = Id.value; 

I don’t understand your structure, but it’s the id of the category you saved in the comic.

  • 1

    Thanks for your attention! But CategoriaId I use it only to facilitate the use of persistence. Your suggestion, subCategoriaViewModel.CategoriaId = Id.value; would be within the method of Controller?

  • 1

    I took a test now. I selected a certain Category (image). This is the correct Id of the Category I selected. But I don’t know why, it’s not saving this change. I already did a test to know the state of the EntityState before the SaveChanges() and its state is Modifield.

  • 1

    About my structure, I’m using DDD concepts

  • 1

    @Iagofrota yes, it would be in the same controller, in get, before going to the view. But its BD structure, how is the relationship of entities ? When you save, you create an object that relates to category 1:1 or 1:n, you do not save the Id of that object for reference ?

  • 1

    My relationship is 1:N. I use independent association in EF. Type, when I create a new Subcategory I do thus. When I want to search for some record, I use the method ObterPorId(Guid Id) that returns a Subcategory.

  • How is your method code _subCategoriaService.Update(subcategory); ?

  • @Gabrielsimas He would be a generic method. Follows the code. I have a breakpoint in all lines of this method. The EntryState is modified. From now on, I appreciate your intention to help!

  • 1

    @Iagofrota, I am always available to help, no need to thank. I also develop with the concepts of DDD and I saw no error in its architecture, however, by the code snippet that you showed me, you called Entry from your Dbcontext, used attach and then changed the state to Modified. You only use Attach when you are using a session outside the current session and that doesn’t seem to be the case, have you tried removing the attach? Whenever you commit, via Savechanges, it ends the session, so it will always give error if you want to perform another operation then recommend the Unit of Work

  • 1

    @Iagofrota If your dbContext is using the same connection or session, you do not need to use attach because there is almost an overlap of threads and they are not synchronized causing your attached objects to stay out of the thread that manages the current connection with the BD and this may be influencing your work. If you are using the DDD I believe you are injecting the Dbcontext in the Below and using it in the business and application layers, then there is no need to create a parallel space to what is already open, so I spoke Uow where you give a commit at the end of the operation

  • 1

    @Gabrielsimas Very interesting your comment! I will give a check in the code. Anyway, thank you!

  • 1

    @Iagofrota, take a look there and tell us the result, okay?

Show 6 more comments

Browser other questions tagged

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