0

I have these classes:

public class User
{
   [Key]
   public Guid Id { get; set; }
}

 public class Computer 
{
   public int Id { get; set; }
   public virtual ICollection<User> Users { get; set; }
}

My action looks something like this:

public ActionResult Create([Bind(Include = "Users")] Computer computer)
{
   if (ModelState.IsValid)
   {
      ...
   }
   var userList = _useRepository.GetAll();
   ViewBag.travelers = new MultiSelectList(userList, "Id", "Name");

   return View(travelRequest);
 }

My view:

@Html.ListBox("Travelers", (MultiSelectList)ViewBag.travelersList, new { @class = "form-control" }) 

This question is very similar to this and the solution might still work. Is there a way to do this but avoid adding the items to the collection.

Additionally I have this

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Conventions.Remove<PluralizingEntitySetNameConvention>();

        modelBuilder.Entity<TravelRequest>()
            .HasMany(x => x.Travelers)
            .WithMany()
            .Map(m =>
            {
                m.MapLeftKey("TravelReqeustId");
                m.MapRightKey("UserId");
                m.ToTable("Travelers");
            });


    }

I have tried without the modification in OnModelCreating but I still get the same error.

Validation fails and says value is invalid.

Exception   {"The parameter conversion from type 'System.String' to type 
'User' failed because no type converter can convert 
between these types."}  System.Exception {System.InvalidOperationException}
Community
  • 1
  • 1
d0001
  • 2,162
  • 3
  • 20
  • 46

1 Answers1

1

You are trying to put IEnumerable<string> into a IEnumerable<User>.

If all you need is users you can change your signature to this.

public ActionResult Create(IEnumerable<string> users)
{
    ...
}

Though the best way is to create a viewmodel.

public class MyViewModel
{
    public Computer Computer { get; set; }
    public IEnumerable<string> SelectedUsers { get; set; }
}

public ActionResult Create(MyViewModel viewModel)
{
    ...
}
jamesSampica
  • 12,230
  • 3
  • 63
  • 85
  • Is there no way of doing this automatically? I come from Symfony2/Doctrine2. Binding in this situations is done automatically. – d0001 Jul 14 '14 at 16:32
  • 1
    Yes but you'll have to make your own `ListBox` razor extension. If you look at the generated html you have now it will bind to an `IEnumerable`. You need each item to have the name `Users[i].Name` where i is an index. – jamesSampica Jul 14 '14 at 16:55
  • From the error I do see that the html is binding to IEnumerable but I don't understand how I can conclude that from looking at the generated html. Can you ellaborate more on the Users[i].Name part? Thanks. – d0001 Jul 14 '14 at 17:01
  • The model binder takes the name of the form element and matches it up with the model property. The `ListBox` is nothing but a `select` html element. The name of it will be something like `Users` and the values are the `option` values. All the `ListBox` does is build that element with the values you give it and names it so that it binds. Since you need it to bind in a special way you need to write your own razor extension that will build out the naming in such a way that it binds correctly. – jamesSampica Jul 14 '14 at 17:32