Hi, I've been working at this for some time to no avail. Here is my code:
// view models
public class RegisterViewModel
{
[Required]
[Display(Name = "Roles")]
public List<
RoleModel
> RolesList { get; set; }
}
public class RoleModel
{
public string Id { get; set; }
public string Name { get; set; }
}
// view
@model ERMgtProgram.Models.RegisterViewModel
@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
<
div
class
=
"form-group"
>
@Html.LabelFor(m => m.RolesList)
@(Html.Kendo().MultiSelectFor(m => m.RolesList)
.Name("RolesList")
.Placeholder("Select roles")
.DataTextField("Name")
.DataValueField("Id")
.HtmlAttributes(new { style = "width: 485px;" })
.IgnoreCase(true)
.AutoBind(true)
.DataSource(datasource =>
{
datasource.Read(read => read.Action("ReadRolesList", "Manage"));
})
)
</
div
>
<
div
class
=
"form-group"
>
<
div
class
=
"col-md-offset-2 col-md-10"
>
<
input
type
=
"submit"
class
=
"k-button"
value
=
"Register"
/>
</
div
>
</
div
>
}
<
script
>
$(document).ready(function () {
var multiSelect = $("#RolesList").data("kendoMultiSelect");
});
</
script
>
// Controller method for reading data
[Authorize(Roles = "DM_Admin")]
public async Task<
ActionResult
> ReadRolesList()
{
var dmRoles = await RoleManager.Roles.Where(r =>
r.Name.Contains("DM_")).ToListAsync();
var roles = dmRoles.Select(u => new RoleModel
{
Id = u.Id,
Name = u.Name
}).ToList();
return Json(roles, JsonRequestBehavior.AllowGet);
}
// controller method that widget posts back to
public async Task<
ActionResult
> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
// additional code
}
// additional code
}
So, in the view, the MultisSelect widget populates with the correct list of roles, and I am able to select them and everything is fine, and when I click the button to submit the form the correct "Register" controller method is called.
However, ModelState.IsValid == false and my model.RolesList is empty
Additionally, I receive this exception:
Exception {"The parameter conversion from type 'System.String' to type 'ERMgtProgram.Models.RoleModel' failed because no type converter can convert between these types."} System.Exception {System.InvalidOperationException}
When debugging I can see that the attempted value was: "AttemptedValue "2" string"
Why is the MultiSelect widget not posting back to the controller with type: List<RoleModel>, and what is an efficient fix for this issue?
Thanks for all the help!
Ruben
8 Answers, 1 is accepted
I am attaching an ASP.NET MVC solution, where a similar scenario to the one described is demonstrated (Binding Kendo UI MultiSelect to model).
I have created the above solution based on the code sample provided and I have made a few modifications in order to achieve the desired result:
1) When the widget is initialized via a [WidgetName]For method, the id and name for the element are automatically set and there is no need to set the Name() option. More information can be found in the Fundamentals article.
2) The MultiSelect widget uses a <select> element under the hood to pass its values to the controller method. Therefore, we are able to pass the selected values as List<string> RolesList { get; set; }. In case the RoleModel has an integer Id, then the parent will also have to be modified accordingly - List<int> RolesList { get; set; } .
In the provided solution, a breakpoint can be set in the beginning of the Save method in the HomeController to verify that the selected values are being successfully received.
Regards,
Dimitar
Progress Telerik
Hello Dimitar,
I downloaded your project and run it .. it works like a charm but, i can't figure out what the problem with my project is ...
so this is what i did ..
i Have
a Class Kommunikation with 20 properties,
Kendo MultiSelect :
@model WebCalendar_09K.Models.KommunikationViewModel
panelBar.Add().Text(
"Einladung"
)
.Content(@<text>
@using (Html.BeginForm(
"Save"
,
"Einladung"
,FormMethod.Post))
{
<div class=
"form-group"
>
@(Html.Kendo().MultiSelectFor(model => model.MitarbeiterCRM_Einladung)
.Name(
"Einladung"
)
.Placeholder(
"Auswählen ..."
)
.DataTextField(
"CrmUserNameZuordnung"
)
.DataValueField(
"ID"
)
.IgnoreCase(
true
)
.AutoBind(
true
)
.ValuePrimitive(
false
)
.Filter(FilterType.Contains)
.DataSource(source =>
{
source.Custom()
.ServerFiltering(
true
)
.Type(
"aspnetmvc-ajax"
)
.Transport(transport =>
{
transport.Read(
"CRM_USERNAME_ZUORDNUNG_CALL"
,
"User"
);
})
.Schema(schema =>
{
schema.Data(
"Data"
)
.Total(
"Total"
)
.Errors(
"Errors"
);
});
})
)
</div>
<input type=
"submit"
value=
"Save"
/>
}
</text>
);
3-ActionMethod :
[HttpPost]
public
ActionResult Save ([DataSourceRequest]DataSourceRequest request,KommunikationViewModel model)
{
EinladungViewModel einladungViewModel =
new
EinladungViewModel();
string
CrmUnameLocal = UserController.Global_CRMusername;
using
(var db =
new
cRM_FM_v2_KARAMEntities())
{
foreach
(var item
in
model.MitarbeiterCRM_Einladung)
{
if
(item !=
null
)
{
var Entity =
new
TERMINEINLADUNGEN()
{
SID_TERMINEINLADUNGEN = Guid.NewGuid(),
RECID_MITARBEITER = db.MITARBEITER.Where(x => x.CRMUSERNAME == item).Select(q => q.SID_MITARBEITER).FirstOrDefault(),
ERFUSER = CrmUnameLocal,
ERFDAT = DateTime.Now,
LASTUSER = CrmUnameLocal,
LASTDAT = DateTime.Now,
ZUSAGE = einladungViewModel.Zusage,
ABSAGE = einladungViewModel.Absage,
VORBEHALT = einladungViewModel.Vorbehalt
//Sid_termineinladungen
//Recid_kommunikationen
};
db.TERMINEINLADUNGEN.Add(Entity);
db.SaveChanges();
}
}
return
Json(
new
[] { model }.ToDataSourceResult(request));
}
}
Hello,
From the provided code snippet it is not clear what the problem with the MultiSelect is. That being said, could you elaborate a bit more on what is the exact issue that you are experiencing?
Regards,
Dimitar
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
Hello,
So I want to add a MultiSelectto my Scheduler Edit-PopUp (This MultiSelect has Values from a DataBase), So I added a Property to my ClassViewModel.
and then I placed breakPoints in my ActionMethod to see when saving if the Value of this Property is changing, but it's not!
I added the MultiSelect This way, I found the right spot on the edit popup and append it to it.
I used this way because I couldn't find the way to add this to my custom Edit popup.
I added another KendoDropDownList items :
for
(resource = 0; resource < resources.length; resource++) {
if
(resources[resource].multiple) {
jQuery(kendo.format(
'<select data-bind="value: {0}" name="{0}">'
, resources[resource].field))
.appendTo(container)
.kendoMultiSelect({
dataTextField: resources[resource].dataTextField,
dataValueField: resources[resource].dataValueField,
dataSource: resources[resource].dataSource,
valuePrimitive: resources[resource].valuePrimitive,
itemTemplate: kendo.format(
'<span class="k-scheduler-mark" style="background-color:\#= data.{0}?{0}:"None" \#"></span>\#={1}\#'
, resources[resource].dataColorField, resources[resource].dataTextField),
tagTemplate: kendo.format(
'<span class="k-scheduler-mark" style="background-color:\#= data.{0}?{0}:"none" \#"></span>\#={1}\#'
, resources[resource].dataColorField, resources[resource].dataTextField)
});
}
else
{
jQuery(kendo.format(
'<select data-bind="value: {0}" name="{0}">'
, resources[resource].field))
.appendTo(container)
.kendoDropDownList({
dataTextField: resources[resource].dataTextField,
dataValueField: resources[resource].dataValueField,
dataSource: resources[resource].dataSource,
valuePrimitive: resources[resource].valuePrimitive,
optionLabel:
"auswählen"
,
template: kendo.format(
'<span class="k-scheduler-mark" style="background-color:\#= data.{0}?{0}:"None" \#"></span>\#={1}\#'
, resources[resource].dataColorField, resources[resource].dataTextField)
});
}
}
and that is working like its life depend on it :-)
But i couldn't figure out how to do it like the way above .. so I'm trying to append it and that is not working..
i just want to someway to achieve this goel (taking the values of the MultiSelect to my Server DataBase)
Hello,
To achieve the desired result, a template should be specified for the Scheduler as follows:
.Editable(editable => { editable.TemplateName("CustomEditorTemplate"); })
Then, the respective editors should be bound inside the template through the data-bind mvvm attribute pointing to the model field(lowercased):
<div class="k-edit-label">
@(Html.LabelFor(model => model.Title))
</div>
<div data-container-for="title" class="k-edit-field">
@(Html.TextBoxFor(model => model.Title, new { @class = "k-textbox", data_bind = "value:title" }))
</div>
There is an available ASP.NET MVC solution that you could use for reference on the above and in general for building a custom edit template for the Scheduler:
Regards,
Dimitar
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
The model includes a List which is used by the multiselect, but I convert that list to a comma delimited string before insert ..
MODEL
public List<string> StructureCodes { get; set; }
public string StructurePoint { get; set; }
CONTROLLER
main.StructurePoint = string.Join(", ", main.StructureCodes);
So it is string.Join that converts the List into a string - choose your own delimiter.