Telerik MVC 3 (Razor) Q1 2012 Editor EditorFor() Binding Returns Null Value and Unobtrusive Validation Doesn't Work

StackOverflow https://stackoverflow.com/questions/10020530

Question

I'm currently working on my first MVC3 application at work (using the Razor view engine), and decided to use the open source Telerik Q1 2012 controls since they will provide a lot of the functionality I need (and look nice as well). Right now the issue I'm having is using the Telerik Editor control and binding to my view model. I have standard Html.EditorFor() controls on the page that return the value in the ViewModel correctly, but the property bound to Telerik Editor is null. Their documentation is completely useless (it only mentions EditorFor one time), and it doesn't seem like they answer too many questions on the forum either. My main question is, how do I bind the Telerik MVC3 Editor to a model and have it set the property that's bound to it? My code for the view model is below (thanks for any help you can provide, and keep in mind, I'm brand new to MVC, I'm doing this project on my own to get familiar with it and introduce some new technologies to the group):

public class SupportViewModel
{
    [Display(Name = "Ticket Subject")]
    [MaxLength(30)]
    [Required(ErrorMessage = "The ticket subject is required.")]
    public string TicketSubject { get; set; }

    [Display(Name = "Support Issue")]
    [Min(1, ErrorMessage = "You must select a support issue.")]
    public int SupportIssueID { get; set; }

    [Display(Name = "Ticket Priority")]
    [Min(1, ErrorMessage = "You must select a ticket priority.")]
    public int TicketPriorityID { get; set; }

    //public string EmployeeID { get; set; }
    public bool IsClosed { get; set; }

    [Required(ErrorMessage = "The detail message is required.")]
    public string DetailMessage { get; set; }
}

View Code:

@model RadixMVC.ViewModels.SupportViewModel

@{
    ViewBag.Title = "Create New Support Ticket";
}

<h2>Radix Support: Create New Support Ticket</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset style="width: 500px">
        <legend>Create New Support Ticket</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.TicketSubject)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.TicketSubject)
            @Html.ValidationMessageFor(model => model.TicketSubject)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.SupportIssueID)
        </div>
        <div class="editor-field">
            @Html.DropDownList("SupportIssueID", string.Empty)
            @Html.ValidationMessageFor(model => model.SupportIssueID)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.TicketPriorityID)
        </div>
        <div class="editor-field">
            @Html.DropDownList("TicketPriorityID", string.Empty)
            @Html.ValidationMessageFor(model => model.TicketPriorityID)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.IsClosed)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.IsClosed)
            @Html.ValidationMessageFor(model => model.IsClosed)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.DetailMessage)
        </div>
        <div class="editor-field">  
            @*@Html.EditorFor(model => model.DetailMessage)*@
            @Html.ValidationMessageFor(model => model.DetailMessage)

            <br />

            @{ Html.Telerik().EditorFor(model => model.DetailMessage)
                   .Name("DetailMessageEditor")
                   .HtmlAttributes(new { style = "height: 200px" })
                   .Encode(false)
                   .Render();
            } 
        </div>

        <div>
            <br />
            <input type="submit" value="Create Ticket" title="Submits a new support ticket" />
            <input type="submit" onclick="parent.location='@Url.Action("Index", "Support", "Index")'" value="Cancel" title="Return to Support Home" />
        </div>
    </fieldset>
}

And finally, Controller Code:

    [HttpPost]
    public ActionResult Create(SupportViewModel vm)
    {
        if (ModelState.IsValid)
        {
            SupportTicket SupportTicket = new SupportTicket()
            {
                SupportTicketID = Guid.NewGuid(),
                EmployeeID = "123456",
                TicketOpenDate = DateTime.Now,
                TicketModifiedDate = DateTime.Now,
                IsClosed = vm.IsClosed,
                TicketSubject = vm.TicketSubject,
                SupportIssueID = vm.SupportIssueID,
                TicketPriorityID = vm.TicketPriorityID
            };

            TicketDetail TicketDetail = new TicketDetail()
            {
                TicketDetailID = Guid.NewGuid(),
                SupportTicketID = SupportTicket.SupportTicketID,
                TicketOrder = 1,
                EmployeeID = "123456",
                DetailDate = DateTime.Now,
                DetailMessage = vm.DetailMessage
            };

            SupportTicket.TicketDetails.Add(TicketDetail);
            db.SupportTickets.Add(SupportTicket);
            db.SaveChanges();
            return RedirectToAction("Index");  
        }

        ViewBag.SupportIssueID = new SelectList(db.SupportIssues, "SupportIssueID", "Name", vm.SupportIssueID);
        ViewBag.TicketPriorityID = new SelectList(db.TicketPriorities, "TicketPriorityID", "Name", vm.TicketPriorityID);

        return View(vm);
    }
Was it helpful?

Solution

I was able to get this working. The documentation is either very outdated or just doesn't explain how to do this very well (probably both). But I was able to get this working by making the following change to my Razor syntax:

        <div class="editor-label">
        @Html.LabelFor(model => model.DetailMessage)
    </div>
    <div class="editor-field">  
        @*@Html.EditorFor(model => model.DetailMessage)*@
        @Html.ValidationMessageFor(model => model.DetailMessage)

        <br />

        @{ Html.Telerik().EditorFor(model => model.DetailMessage)
               //.Name("DetailMessageEditor")
               .HtmlAttributes(new { style = "height: 200px" })
               .Encode(true)
               .Render();
        } 
    </div>

Removing the "Name" property from the control solved the problem of not getting anything back, but when I tried to save, I immediately got an error (something to do with XSS, cross-site scripting), and I assumed it was because the HTML wasn't being encoded. I changed the Encode property to true, and now all is good.

OTHER TIPS

Came across a similar thing today.

I was using a View Model and the property I wanted to bind to was was a property of a child object in the View Model.

When I submitted, the value in the RTE was not being bound. When I looked in Request.From object I could see the the value was being returned in the correct format for it to bound in the usual way so I was a little confused.

Anyway, if you want it to bind you need to give the exact name of your property to the the RTE so in your case

.Name("DetailMessage") 

should work but

.Name("DetailMessageEditor") 

will not.

Im my case i had to name the RTE

.Name("object.Property") 

where object is the child object on the View model where my property lives to get it to work

Hope this helps someone.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top