DropDownListFor Template Exception

2 posts, 1 answers
  1. Drewanz
    Drewanz avatar
    6 posts
    Member since:
    Jan 2009

    Posted 21 Jul 2014 Link to this post

    I have the following issue which may be something I've missed along the code.

    One TemplateEditor for a ViewModel to produce a DropDownList with choices from a database:

    @model MyApp.ViewModels.JobTitleViewModel
     
    @(Html.Kendo().DropDownListFor(m => m)
    .DataValueField("Id")
    .DataTextField("Name")
    .DataSource(r => r.Read("GetAll", "JobTitles"))
    .HtmlAttributes(new { style = "width:90%" })
    )

    A controller action to return the current list of active items on the database:

    [AllowAnonymous]
    public JsonResult GetAll()
    {
        var titles = context.JobTitles
            .Where(e => e.IsActive == true)
            .OrderBy(e => e.Name)
            .Select(t => new JobTitleViewModel
            {
                Id = t.Id,
                Name = t.Name,
                IsActive = t.IsActive
            });
         
        return this.Json(titles, JsonRequestBehavior.AllowGet);
    }

    Finally, a View where the user picks the desired option, and submit it back:

    @model MyApp.Models.RegisterViewModel
    @{
        ViewBag.Title = "Register";
    }
     
    <h2>@ViewBag.Title</h2>
     
    @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
    {
        @Html.AntiForgeryToken()
        <hr />
        @Html.ValidationSummary("", new { @class = "text-danger" })
         
        <div class="form-group">
            @Html.LabelFor(m => m.FullName, new { @class= "col-md-2 control-label"})
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.FullName, new { @class="form-control"})
            </div>
        </div>
     
        <div class="form-group">
            @Html.LabelFor(m => m.JobTitle.Name, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.EditorFor(m => m.JobTitle, new { @class = "form-control" })
            </div>
        </div>
     
        <div class="form-group">
            @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" class="btn btn-default" value="Registra" />
            </div>
        </div>
    }
     
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }


    The editor is "hinted" using data annotation on the ViewModel :

    public class RegisterViewModel
    {
        [Required]
        [EmailAddress]
        [Display(Name = "Email")]
        public string Email { get; set; }
     
        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }
     
        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
     
        [StringLength(80, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 4)]
        [Display(Name = "Name")]
        public string FullName { get; set; }
     
        [UIHint("JobTitleEditor")]
        public JobTitleViewModel JobTitle { get; set; }
    }


    When the View is submitted back, the ModelState is not valid with an error associated with the JobTitle property, resulting in an exception with the following text:

    The parameter conversion from type 'System.String' to type 'MyApp.ViewModels.JobTitleViewModel' failed because no type converter can convert between these types.

    Could you please point what am I doing wrong ??

    Regards.

  2. Answer
    Georgi Krustev
    Admin
    Georgi Krustev avatar
    3706 posts

    Posted 23 Jul 2014 Link to this post

    Hello Marcello,

    We answered to the support ticket opened on the same subject. I will ask you to continue our discussion in only one thread to avoid any duplication. Thank you for the understanding.

    Here is a quote of the answer:

    The problem comes from the difference between what the DefaultModelBinder expects and what is send from the client (using Form element). In general, ASP.NET MVC requires "ObjectFieldName.PropertyName" format when it comes to complex objects binding. The DropDownList widget uses input element under the hood and that is why only the selected value is send back to the server and not the whole object. When it comes to form posting the dropdownlist declaration:
    Copy Code
    @(Html.Kendo().DropDownListFor(m => m)
    ...
    )
    is absolutely equivalent to:
    Copy Code
    @model MyApp.ViewModels.JobTitleViewModel
      
    @(Html.TextBoxFor(m => m))

    If you would like to avoid the error, then you will need to set the widgte name to JobTitleViewModel.Id.Thus the model binder will be able to map the value correctly. Once this is done, you can find the whole JobTitleViewModel based on the selected value and set the RegisterViewModel.JobTitle property.

    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.

     
  3. UI for ASP.NET MVC is VS 2017 Ready
Back to Top