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

[Solved] Implicit Model Binding with Grid

4 Answers 190 Views
Grid
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Justin Stuparitz
Top achievements
Rank 1
Justin Stuparitz asked on 16 Nov 2009, 04:04 PM
Hi,

I have a simple grid that is bound to a List when I post back the grid my list of custom types are not being implicitly created like I would expect so that I can save the list.  Am I missing something or do I need to do this manually?  Thanks. Justin

View:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<Flagship.Business.BusinessObjects.Language>>" %>

    <style type="text/css">
        .t-grid tr
        {
            cursor: pointer;
        }
    </style>
  
<% using (Html.BeginForm("SaveLanguages", "Admin"))
   {

       Html.Telerik().Grid(Model)
           .Name("Languages")
           .Scrollable()
           .Sortable()
           .Columns(columns =>
           {
               columns.Add(o =>
               {%>
                <%=Html.Hidden("LanguageID", o.LanguageID.Value)%>
                <%=Html.CheckBox("IsFlagshipLanguage", o.IsFlagshipLanguage.Value, new { title = o.Name })%>
             <%
    }).Title("Flagship Language").Width(20);
               columns.Add(o => o.Name).Width(100);
               columns.Add(o =>
              {
                %>
        
                <%= Html.ActionLink("Delete", "Delete","", new { @class = "t-link action-delete" })%>
                <%
    }).Title("Delete").Width(150);
           })
           .Render();
%>
<input type="submit" value="Save All" class="Button" title="Save all languages in the list" />

<% } //end form tag  %>


Method on Controller:

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SaveLanguages(List<Language> languages)
        {
            programService.SaveLanguages(languages);
            return RedirectToAction("ShowLangauges", "Admin");
        }


4 Answers, 1 is accepted

Sort by
0
Alex Gyoshev
Telerik team
answered on 17 Nov 2009, 06:50 AM
Hello Justin,

Binding the grid to a given model means that it will display the model, nothing more. Since ASP.NET MVC is stateless (unlike ASP.NET WebForms), the information about the model perishes once the content gets rendered. What you will get at the server when the button is clicked are the checkboxes that you create. Furthermore, the code
    <%=Html.Hidden("LanguageID", o.LanguageID.Value)%>
    <%=Html.CheckBox("IsFlagshipLanguage", o.IsFlagshipLanguage.Value, new { title = o.Name })%>

will never generate unique IDs (again, unlike WebForms).

That said, you can do the following:
  1. Generate unique IDs for the fields. You could merge the checkbox name with the language id - this way there will be less elements on the page, too. ("IsFlagshipLanguage-" + o.LanguageID.Value)
  2. Attach a javascript event handler on the submit button. The handler should gather the IDs of all the checkboxes and populate a hidden field, say, FlagshipLanguages
  3. Get the FlagshipLanguages hidden field as a parameter of the action method (instead of a list of languages). Parse it and update the languages as required.

Best wishes,
Alex
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
Justin Stuparitz
Top achievements
Rank 1
answered on 17 Nov 2009, 03:11 PM
Alex,

Your comment on unique ids helped my memory.  If you follow a particular naming convention the asp.net MVC framework will build you a list if the view is strongly typed.
http://stackoverflow.com/questions/231878/complex-model-binding-to-a-list

I'm definitely trying to avoid doing any type of JavaScript to get these values myself.  So this works:

View:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<List<Flagship.Business.BusinessObjects.Language>>" %>
<%@ Import Namespace="Flagship.Business.BusinessObjects" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Language
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <% using (Html.BeginForm("SaveLanguages", "Admin"))
   {
%>
<input type="submit" value="Save All" class="Button" title="Save all languages in the list" />
<ul>
<%
           int x = 0;
           foreach (Language l in Model)
           {%><li><% =Html.Hidden("languages[" + x + "].LanguageID", l.LanguageID.Value) %>
               <%=Html.CheckBox("languages[" + x + "].IsFlagshipLanguage", l.IsFlagshipLanguage.Value, new { title = l.Name }) %>
               <%=Html.TextBox("languages[" + x + "].Name", l.Name) %>
               </li> <%
                         x++;
           }%>
</ul>
<% } //end form tag  %>
</asp:Content>

Controller:

        [HttpPost]
        public ActionResult SaveLanguages(List<Language> languages)
        {
            //programService.SaveLanguages(languages);
            return RedirectToAction("Langauge", "Admin");
        }

I get a nice populated list.  So now I'm trying to get all the form names in the grid to comply with the convention but I'm getting an invalid expression term error:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Flagship.Business.BusinessObjects.Language>>" %>
<%@ Import Namespace="Flagship.MVC.HtmlHelpers" %>

<% using (Html.BeginForm("SaveLanguages", "Admin"))
   {
       int x = -1;
       Html.Telerik().Grid(Model)
           .Name("Languages")
           .RowAction(row => { x++; })
           .Columns(columns =>
           {
               columns.Add(o =>
               {%>
                <%=Html.Hidden("languages[" + x.ToString() + "].LanguageID", o.LanguageID.Value)%>
                <%=Html.CheckBox("languages[" + x.ToString() + "].IsFlagshipLanguage", o.IsFlagshipLanguage.Value, new { title = o.Name })%>
                <%=Html.TextBox("languages[" + x.ToString() + "].Name", o.Name); %>
               <%});
           })
           .Render();
%>
<input type="submit" value="Save All" class="Button" title="Save all languages in the list" />

<% } //end form tag  %>

controller is the same:

        [HttpPost]
        public ActionResult SaveLanguages(List<Language> languages)
        {
            //programService.SaveLanguages(languages);
            return RedirectToAction("Langauge", "Admin");
        }

Can you tell me how I can control the names of the form elements in the grid?  If I can get them to follow the pattern:

languages[0].LanguageID
languages[1].LanguageID

MVC will automagically create a list for me









0
Justin Stuparitz
Top achievements
Rank 1
answered on 17 Nov 2009, 04:12 PM
I was mistaken.  The previous post with RowAction totally works!  I had an error with my TextBox so I removed it below.  So this works like a charm and will give you a beautiful list in your controller so long as the parameter name in your controller method is of type  IEnumerable and is called "languages" in this example.

<% using (Html.BeginForm("SaveLanguages", "Admin"))
   {
       int x = -1;
       Html.Telerik().Grid(Model)
           .Name("Languages")
           .RowAction(row => { x++; })
           .Columns(columns =>
           {
       
               columns.Add(o =>
               {%>
                <%=Html.Hidden("languages["+x+"].LanguageID", o.LanguageID.Value)%>
                <%=Html.CheckBox("languages["+x+"].IsFlagshipLanguage", o.IsFlagshipLanguage.Value)%>
                
               <%});
               columns.Add(o => o.Name);
           })
           .Render();
%>
<input type="submit" value="Save All" class="Button" title="Save all languages in the list" />

<% } //end form tag  %>

0
Alex Gyoshev
Telerik team
answered on 18 Nov 2009, 03:03 PM
Hi Justin,

Glad you managed to do it. I was just preparing a sample application (and I unintentionally removed the  textbox, just to clear the output). Thank you for the StackOverflow reference, we were not aware of this automagical functionality. The RowAction also is a very cunning tactic - I think that others will find your solution useful, too.

Kind regards,
Alex
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Tags
Grid
Asked by
Justin Stuparitz
Top achievements
Rank 1
Answers by
Alex Gyoshev
Telerik team
Justin Stuparitz
Top achievements
Rank 1
Share this question
or