This is a migrated thread and some comments may be shown as answers.

Multiselect and form, not sending values back

8 Answers 643 Views
MultiSelect
This is a migrated thread and some comments may be shown as answers.
Gaetano
Top achievements
Rank 1
Gaetano asked on 16 May 2014, 10:54 AM
Hi guys,
I have a mvc view (still a pretty standard one) to edit one of my entities..

@using (Ajax.BeginForm("Edit", "Role",
       new AjaxOptions() { HttpMethod = "POST", UpdateTargetId = "ajaxRoleEditForm", OnSuccess = "OnRoleUpdated" }))
   {
 
       @Html.AntiForgeryToken()
       @Html.ValidationSummary(true)
 
       <fieldset>
           <legend>ROLE_T005</legend>
 
           @Html.HiddenFor(model => model.ID)
 
           <div class="editor-label">
               @Html.LabelFor(model => model.Name)
           </div>
           <div class="editor-field">
               @Html.EditorFor(model => model.Name)
               @Html.ValidationMessageFor(model => model.Name)
           </div>
 
           <div class="editor-label">
               @Html.LabelFor(model => model.Description)
           </div>
           <div class="editor-field">
               @Html.EditorFor(model => model.Description)
               @Html.ValidationMessageFor(model => model.Description)
           </div>
 
           <div class="editor-label">
               @Html.LabelFor(model => model.Functions)
           </div>
 
           <div class="editor-field">
               @Html.EditorFor(model => model.Functions)
           </div>
           <p>
               <input type="submit" value="Save" />
           </p>
       </fieldset>
   }

the model is a view model because the actual table (using EF) has a cross table to a child entity and I dont want to bother with it.
so my wiew model is:
public class RoleViewModel
   {
       public int ID { set; get; }
 
       public string Name { set; get; }
 
       public string Description { set; get; }
 
       [UIHint("FunctionMultiSelectTemplate")]
       public IList<FUNCTION_T008> Functions { set; get; }
   }

and the custom template for the list of functions is:
@model IList<Lme.WQ2.AccessControl.Dal.FUNCTION_T008>
 
@(Html.Kendo().MultiSelect()
    .Name("FunctionMultiSelectTemplate")
    .Placeholder("Select functions...")
    .BindTo(ViewBag.Functions)
    .Value(Model)
    .DataTextField("NAME")
    .DataValueField("ID")
    )

at last my action looks like:

public ActionResult Edit(int id = 0)
        {
            ROLE_T005 role_t005 = db.ROLE_T005
                .Include(x => x.ROLE_FUNCTION_T010)
                .Include(x => x.ROLE_FUNCTION_T010.Select(y => y.FUNCTION_T008))
                .SingleOrDefault(x => x.ID == id);
 
 
            RoleViewModel roleViewModel = new RoleViewModel()
            {
                ID = role_t005.ID,
                Name = role_t005.NAME,
                Description = role_t005.DESCRIPTION,
                Functions = role_t005.ROLE_FUNCTION_T010.Select(x => x.FUNCTION_T008).ToList()
            };
 
 
            ViewBag.Functions = db.FUNCTION_T008.AsEnumerable();
 
            if (role_t005 == null)
            {
                return HttpNotFound();
            }
            return View(roleViewModel);
        }

now, when I hit the save button of the view, the function list is always null or empty...
What am I doing wrong?
Thanks
Fabio

8 Answers, 1 is accepted

Sort by
0
Georgi Krustev
Telerik team
answered on 16 May 2014, 11:09 AM
Hello Fabio,

I would suggest you check this code library, which shows how to bind MultiSelect and then post its values to the server. The key point here is that the name of the widget should be same as the model property as this is the only way for the ASP.NET MVC DefaultModelBinder to map the posted values to the view model.

Regards,
Georgi Krustev
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Gaetano
Top achievements
Rank 1
answered on 16 May 2014, 02:38 PM
ok but in the example you posted, the returned values are "just" ids (int)...
is it not possible to return the whole class list? 
0
Georgi Krustev
Telerik team
answered on 19 May 2014, 11:00 AM
Hello Fabio,

The MultiSelect widget uses a SELECT element (<select multiple="multiple></select>), which posts only the selected values. If you would like to post the whole objects, then you will need to do it manually. You can get the selected data items using widget's dataItems method. To post the data, you can use jQuery.ajaxmethod.

Regards,
Georgi Krustev
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Gaetano
Top achievements
Rank 1
answered on 03 Jun 2014, 04:04 PM
Hi Georgi,
I'm trying to figure this issue out...

I changed a little bit my structure...I'm not working with the ViewModel object anymore..

here is my new template:
@model ICollection<USER_ROLE_T007>
 
@(Html.Kendo().MultiSelect()
    .Name("USER_ROLE_T007")
    .Placeholder("Select roles...")
    .BindTo(ViewBag.Roles)
    .Value(Model.Select(x => x.ROLE_T005))
    .DataTextField("NAME")
    .DataValueField("ID")
    )

and here is my razor:
<div class="editor-label">
                @Html.LabelFor(model => model.USER_ROLE_T007)
            </div>
             <div class="editor-field">
                @Html.EditorFor(model => model.USER_ROLE_T007)
                @Html.ValidationMessageFor(model => model.USER_ROLE_T007)
            </div>
and I linked the template with the UHint dataAnnotation attribute.
As a reminder USER_ROLE_T007 is the cross-table entity.
On visualization everything works fine.
I can also add items (roles) to the multi-select.
When I hit the save button and the code arrives to the update action it doesn't pass the "ModelState.IsValid" check
and the reason is that the multiselect (as you explained in your post) returns only ids...

for your reference the exception raised is 
The parameter conversion from type 'System.String' to type 'USER_ROLE_T007' failed because no type converter can convert between these types.

Do you know If there is any workaround or any way to intercept the validation and custom convert the id to the class??
Consider that the object posted back to the server always has its list (cross table entity) empty...even if it contained some element in the first place...

Thanks
Fabio
0
Gaetano
Top achievements
Rank 1
answered on 04 Jun 2014, 09:23 AM
UPDATE:

I managed to remove cross classes from entity model.
So now each class is related to the other one directly; In this case eneity USER_T001 contains a list of ROLE_T005.

so now my multiselect is bound to roles...
the issue remain the same... Model.isValid is false...same error..
always ids post back to the server... but now I'm more optimistic about a possible solution since it seems now a common scenario.

Thanks
0
Daniel
Telerik team
answered on 05 Jun 2014, 02:07 PM
Hello Fabio,

I am not sure if I understand the described changes. Does the list bound to the multiselect still consists of objects? If yes and the entire dataItems cannot be posted via Ajax in your scenario then you can use one of the following approaches to bind the property when it is posted with a form:
  • exclude the property from the model binding and add a separate parameter for the ids collection e.g.
    public ActionResult Action([Bind(Exclude = "CollectionPropertyName")]MyModel model, IEnumerable<int> CollectionPropertyName)
    {  
        if (CollectionPropertyName != null)
        {
            model.CollectionPropertyName = CollectionPropertyName.Select(id => new CollectionObjectType
            {
                ID = id
            });
        }
  •  Implement a custom model binder for the model type or for the collection type and create a collection of objects when a comma separated string with the IDs is posted to the server.


Regards,
Daniel
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Gaetano
Top achievements
Rank 1
answered on 06 Jun 2014, 08:46 AM
Hi Daniel,
Yes the list bound to multiselect still consists of objects.

I had a look to both your suggestions and I think that the first suits me better in this case.
Now I got my Model.IsValid check as true; I don't get why I get the state of the object as detached though...
0
Daniel
Telerik team
answered on 10 Jun 2014, 07:10 AM
Hi,

Could you clarify what you mean by:
 get the state of the object as detached
If you are using an ORM tool and the action parameter is in detached state then this behavior is expected. You should explicitly attach the model to the context.

Regards,
Daniel
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
Tags
MultiSelect
Asked by
Gaetano
Top achievements
Rank 1
Answers by
Georgi Krustev
Telerik team
Gaetano
Top achievements
Rank 1
Daniel
Telerik team
Share this question
or