0

I have two classes many-to-many the first is "Anuncios" and the second "SubCategorias"

public class Anuncios {
    public int AnuncioId {get;set;}
    public string Titulo {get;set;}
    public ICollection<SubCategorias> SubCategorias {get;set;}
}

public class SubCategorias {
    public int SubCategoriaId {get;set;}
    public string Nome {get;set;}
    public ICollection<Anuncios> Anuncios {get;set;}
}

In DAL layer I did method to save the "Anuncio" in DB.

public void Salvar(Anuncio entidade)  {
     entidade.SubCategorias = entidade.SubCategorias.Select(subcat => _contexto.SubCategorias.FirstOrDefault(x => x.SubCategoriaId == subcat.SubCategoriaId)).ToList();
     _contexto.Anuncios.Add(entidade);
     _contexto.SaveChanges();
}

I Create the Action "Create":

private readonly Context _ctx = new Context();

public ActionResult Create()
{
    var model = new Anuncios {SubCategorias = _ctx.SubCategorias.ToList()};
    return View(model);
}

In View I made DropDownList with "SubCategorias":

@Html.LabelFor(model => model.SubCategorias)
@Html.DropDownListFor(model => model.SubCategorias, new SelectList(Model.SubCategorias, "SubCategoriaId", "Nome"))

The DropDownListFor is populated with sucess..

Fine....

But when submit form the value selected in DropDownListFor not pass to method Create. The anuncio.SubCategorias is null!

private readonly AnunciosDal _anuncio = new AnunciosDal();

[HttpPost]
public ActionResult Create(Anuncio anuncio)
{
    _anuncio.Salvar(anuncio);
    return View(anuncio);
}

I have sought in various forums the solution, but could not find

Somebody help me?!

Sorry about my english rs...

Thank You! Fabrício Oliveira

4 Answers 4

4

The first parameter of DropDownListFor needs to be the object holding the selected value, where the second parameter contains the list:

@Html.DropDownListFor(model => model.SOME_ID_FOR_SELECTED_VALUE, 
                  new SelectList(Model.SubCategorias, "SubCategoriaId", "Nome"))

Currently the example you have also maps the same list as the first property. You should use an ID like @Maess suggested, and then bind it via:

@Html.DropDownListFor(model => model.SubCategoriaID, new SelectList(Model.SubCategorias, "SubCategoriaId", "Nome"))

Selecting a value will then post it back to the server to this SubCategoriaID field.

Sign up to request clarification or add additional context in comments.

5 Comments

The "SubCategorias" is a collection of "Anuncio" and "Anuncios" is "SubCategoria" collection. Is a many to many class. I did as you said, I created a property "SubCategoriaId", but when a submit form the SubCategorias Count = 0 And the SubCategoriaId is 2. Now how I save is in the DAL?
Using the ID; the items in the list will never by saved back to the server; you have to reload it from the list. In web forms, viewstate would normally save this for you, using a hidden field with encryption. But in MVC, your controller has to reload the list of items in the dropdown; there is no persistence mechanism.
A try save changes and return an error "Column name 'SubCategoriaId' is invalid"
Yes, with reverse engineer. I have 3 db tables, "Anuncios", "SubCategorias", "AnunciosSubCategorias". How I add a reference in "AnunciosSubCategorias" of "AnuncioId" and "SubCategoriaId"
This is the complexity of binding to EF objects within MVC. The problem you are experiencing is pretty complex, and you probably aren't going to be able to use your EF objects directly. What I would recommend is not returning Anuncios directly; I'd recommend creating a CreateModel view model class. This will change your bindings and your expectations on what posts back, but you can add SubCategoriaID to the CreateModel viewmodel, then use that to figure out which records need to be added or removed in the backend objects.
1

You need to have another property to store the selected value from the dropdown. It is best if you create a viewmodel with properties which are needed for your view.

public class CreateAnuncios
{
  public string Title {set;get;}
  public int SelectedSubCategoryId {set;get;}
  public List<SelectListItem> SubCategories {set;get;}

  public CreateAnuncios()
  {
    this.SubCategories = new List<SelectListItem>();
  }
}

Now in your create action, create an object of this view model, Fill the SubCategories property and send to the view.

public ActionResult Create()
{
  var vm=new CreateAnuncios();
  vm.SubCategories = ctx.SubCategorias
       .Select(s=> new SelectListItem
             { Value = s.SubCategoriaId .ToString(), 
               Text=s.Nome}).ToList();

  return View(vm);
}

Your create view should be strongly typed to the CreateAnuncios class

@model YourNameSpaceHere.CreateAnuncios
@using(Html.Beginform())
{
  @Html.TextBoxFor(s=>s.Title)
  @Html.DropdownListFor(s=>s.SelectedSubCategoryId,Model.SubCategories,"Select")
  <input type="submit" />
}

Now when user posts the form, Read the Properties of the posted model and use that to save to db.

[HttpPost]
public ActionResult Create(CreateAnuncios model)
{
  //Check for model.Title and model.SelectedSubCategoryId and use it to save
  // to do :Save and redirect
}

Comments

0

You need to provide a collection of SelectListItems that populate your DropDownList as well as a property to hold the currently selected SelectListItems' Id (which will be posted back to the server):

public class Anuncios {
    public int AnuncioId {get;set;}
    public string Titulo {get;set;}
    public ICollection<SubCategorias> SubCategorias {get;set;}

    public int SelectedSubCategoryId {get;set;}
    public IEnumerable<SelectListItem> SubCategoryListItems {get;set;}
}

then, present them to the user via:

@html.DropDownListfor(x => x.SelectedSubCategoryId, Model.SubCategoryListItems)

The SubCategoryListItems will have to be populated from the server, typically something like this:

this.SubCategoryListItems = this.SubCategorias.Select(x => new SelectListItem { Text = x.Name, Value = x.Id });

Comments

-1

You need an id property for the SubCategoria you have it in your binding, but not in the model

public class Anuncios {
    public int AnuncioId {get;set;}
    public string Titulo {get;set;}
    public ICollection<SubCategorias> SubCategorias {get;set;}
    public int SubCategoriaId{get;set;}
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.