Uncaught Error: Invalid template in nested Grid

10 posts, 0 answers
  1. Martin
    Martin avatar
    39 posts
    Member since:
    Dec 2011

    Posted 05 Dec 2012 Link to this post

    I have a project working fine in ASP.Net MVC 4 with kendo UI 2012.2.710 developed in VS2010.

    I have recently installed VS2012 and there I have Kendo 2012.3.1114. I just copied all the code from the VS2010 to VS2012 and it all just worked except for one small point. I have a nested grid and I use a template for the detail. That template is shown below. It works fine in the 2010 project but 2012 always says "Uncaught Error: Invalid template:" and the template is identical. If I comment out the .ClientTemplateId statement, the main grid displays just fine. If I paste the template into its own Partial View and display it separately, it displays just fine but it always errors as a template.

    I have tried commenting out parts of the template, even getting to the point where it o nly has the Name and ToClientTemplate calls and it STILL errors. So I just wonder if something is broken with templates in the latest version of Kendo or the latest version of VS. The template is below:
    <script id="paneTemplate" type="text/kendo-tmpl">
        @(Html.Kendo().Grid<AWSQBCC.Models.Pane>()
        .Name("Panes_#=LiteId#")
        .Columns(columns =>
        {
            //columns.Bound(p => p.PaneId);
            columns.Bound(p => p.Sequence);
            columns.Bound(p => p.LiteId).Hidden();
            columns.ForeignKey(p => p.GlassId, (System.Collections.IEnumerable)ViewData["glasses"], "GlassId", "GlassType").Title("Glass Type");
            columns.Command(command => { command.Edit(); command.Destroy(); });
        })
        .DataSource(dataSource => dataSource
            .Ajax()
            .Sort(sort =>
            {
                sort.Add(p => p.Sequence);
            })
            .Read(read => read.Action("Pane_Read", "Lite", new { id = "#=LiteId#" }))
            .Destroy(destroy => destroy.Action("Pane_Delete", "Lite"))
            .Update(update => update.Action("Pane_Update", "Lite"))
            .Create(create => create.Action("Pane_Create", "Lite", new { id = "#=LiteId#" }))
            .Model(model =>
            {
                model.Id(p => p.PaneId);
                model.Field(p => p.PaneId).Editable(false);
                model.Field(p => p.LiteId).Editable(false);
                model.Field(p => p.GlassId);
            })
            .Events(events => { events.Error("error"); })
        )
        .ToolBar(commands => commands.Create())
        .Editable(editable => editable.Mode(GridEditMode.InLine))
        //.Events(events => events.DataBound("refresh"))
        .ToClientTemplate())
    </script>
    Any help much appreciated.
  2. Martin
    Martin avatar
    39 posts
    Member since:
    Dec 2011

    Posted 05 Dec 2012 Link to this post

    Here is some additional information in case it helps. I found the generated template in the html sent to the client and am posting it here, so you can see what was generated.

    <script id="paneTemplate" type="text/kendo-tmpl">
        <div class="k-widget k-grid" id="Panes_#=LiteId#"><div class="k-toolbar k-grid-toolbar k-grid-top"><a class="k-button k-button-icontext k-grid-add" href="/Lite/Pane_Read/%23%3dLiteId%23?Panes_%23%3DLiteId%23-mode=insert"><span class="k-icon k-add"></span>Add new item</a></div><table cellspacing="0"><colgroup><col /><col /><col /></colgroup><thead class="k-grid-header"><tr><th class="k-header" data-field="Sequence" data-title="Sequence" scope="col"><span class="k-link">Sequence</span></th><th class="k-header" data-field="LiteId" data-title="Lite Id" scope="col" style="display:none"><span class="k-link">Lite Id</span></th><th class="k-header" data-field="GlassId" data-title="Glass Type" scope="col"><span class="k-link">Glass Type</span></th><th class="k-header" scope="col"><span class="k-link"> </span></th></tr></thead><tbody><tr class="t-no-data"><td colspan="3"></td></tr></tbody></table></div><script>
        jQuery(function(){jQuery("\#Panes_#=LiteId#").kendoGrid({"columns":[{"title":"Sequence","field":"Sequence","encoded":true,"editor":"\u003cinput class=\"text-box\u0026#32;single-line\" data-val=\"true\" data-val-number=\"The\u0026#32;field\u0026#32;Sequence\u0026#32;must\u0026#32;be\u0026#32;a\u0026#32;number.\" data-val-required=\"The\u0026#32;Sequence\u0026#32;field\u0026#32;is\u0026#32;required.\" id=\"Sequence\" name=\"Sequence\" type=\"number\" value=\"0\" /\u003e\u003cspan class=\"field-validation-valid\" data-valmsg-for=\"Sequence\" data-valmsg-replace=\"true\"\u003e\u003c/span\u003e"},{"title":"Lite Id","hidden":true,"field":"LiteId","encoded":true},{"title":"Glass Type","field":"GlassId","encoded":true,"editor":"\u003cinput data-val=\"true\" data-val-number=\"The\u0026#32;field\u0026#32;GlassId\u0026#32;must\u0026#32;be\u0026#32;a\u0026#32;number.\" data-val-required=\"The\u0026#32;GlassId\u0026#32;field\u0026#32;is\u0026#32;required.\" id=\"GlassId\" name=\"GlassId\" type=\"text\" value=\"0\" /\u003e\u003cscript\u003e\tjQuery(function(){jQuery(\"\\#GlassId\").kendoDropDownList({\"dataSource\":[{\"Text\":\"Clear 3.0mm\",\"Value\":\"2\"},{\"Text\":\"Clear 3.9mm\",\"Value\":\"3\"},{\"Text\":\"Clear 4.7mm\",\"Value\":\"4\"},{\"Text\":\"Clear 5.7mm\",\"Value\":\"5\"},{\"Text\":\"LowE 240 3.0mm\",\"Value\":\"13\"},{\"Text\":\"LowE 240 3.9mm\",\"Value\":\"14\"},{\"Text\":\"LowE 240 4.7mm\",\"Value\":\"15\"},{\"Text\":\"LowE 240 5.7mm\",\"Value\":\"16\"},{\"Text\":\"LowE 270 3.0mm\",\"Value\":\"9\"},{\"Text\":\"LowE 270 3.9mm\",\"Value\":\"10\"},{\"Text\":\"LowE 270 4.7mm\",\"Value\":\"11\"},{\"Text\":\"LowE 270 5.7mm\",\"Value\":\"12\"},{\"Text\":\"LowE 366 3.0mm\",\"Value\":\"1\"},{\"Text\":\"LowE 366 3.9mm\",\"Value\":\"6\"},{\"Text\":\"LowE 366 4.7mm\",\"Value\":\"7\"},{\"Text\":\"LowE 366 5.7mm\",\"Value\":\"8\"},{\"Text\":\"Obscure 3.0mm\",\"Value\":\"17\"},{\"Text\":\"Obscure 3.9mm\",\"Value\":\"18\"},{\"Text\":\"Obscure 4.7mm\",\"Value\":\"19\"},{\"Text\":\"Obscure 5.7mm\",\"Value\":\"20\"}],\"dataTextField\":\"Text\",\"dataValueField\":\"Value\"});});\u003c\\/script\u003e\u003cspan class=\"field-validation-valid\" data-valmsg-for=\"GlassId\" data-valmsg-replace=\"true\"\u003e\u003c/span\u003e","values":[{"text":"Clear 3.0mm","value":"2"},{"text":"Clear 3.9mm","value":"3"},{"text":"Clear 4.7mm","value":"4"},{"text":"Clear 5.7mm","value":"5"},{"text":"LowE 240 3.0mm","value":"13"},{"text":"LowE 240 3.9mm","value":"14"},{"text":"LowE 240 4.7mm","value":"15"},{"text":"LowE 240 5.7mm","value":"16"},{"text":"LowE 270 3.0mm","value":"9"},{"text":"LowE 270 3.9mm","value":"10"},{"text":"LowE 270 4.7mm","value":"11"},{"text":"LowE 270 5.7mm","value":"12"},{"text":"LowE 366 3.0mm","value":"1"},{"text":"LowE 366 3.9mm","value":"6"},{"text":"LowE 366 4.7mm","value":"7"},{"text":"LowE 366 5.7mm","value":"8"},{"text":"Obscure 3.0mm","value":"17"},{"text":"Obscure 3.9mm","value":"18"},{"text":"Obscure 4.7mm","value":"19"},{"text":"Obscure 5.7mm","value":"20"}]},{"command":[{"name":"edit","buttonType":"ImageAndText","text":"Edit"},{"name":"destroy","buttonType":"ImageAndText","text":"Delete"}]}],"scrollable":false,"editable":{"confirmation":"Are you sure you want to delete this item?","mode":"inline","create":true,"update":true,"destroy":true},"toolbar":{"command":[{"name":null,"buttonType":"ImageAndText","text":"Add new item"}]},"dataSource":{"transport":{"read":{"url":"/Lite/Pane_Read/#=LiteId#"},"update":{"url":"/Lite/Pane_Update"},"create":{"url":"/Lite/Pane_Create/#=LiteId#"},"destroy":{"url":"/Lite/Pane_Delete"}},"serverPaging":true,"serverSorting":true,"serverFiltering":true,"serverGrouping":true,"serverAggregates":true,"type":"aspnetmvc-ajax","sort":[{"field":"Sequence","dir":"asc"}],"filter":[],"error":error,"schema":{"data":"Data","total":"Total","errors":"Errors","model":{"id":"PaneId","fields":{"PaneId":{"editable":false,"type":"number"},"Sequence":{"type":"number"},"LiteId":{"editable":false,"type":"number"},"GlassId":{"type":"number"}}}}}});});
    <\/script>
    </script>
    I've looked through it but can't see anything wrong with it, but maybe you guys have better tools for pulling apart generated templates.
    This is pretty urgent for me since I can't even see a work around.
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Daniel
    Admin
    Daniel avatar
    2118 posts

    Posted 07 Dec 2012 Link to this post

    Hello Martin,

    The reason for the problem is the AntiXssEncoder which is enabled in the Web.config httpRuntime configuration:

    <httpRuntime targetFramework="4.5" encoderType="System.Web.Security.AntiXss.AntiXssEncoder, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    As can be seen in the template, all spaces are encoded and the "#" character is included which breaks the templates parsing. Removing it should resolve the problem.

    Kind regards,
    Daniel
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  5. Martin
    Martin avatar
    39 posts
    Member since:
    Dec 2011

    Posted 07 Dec 2012 Link to this post

    Thanks for that. In desperation I had abandoned using the HTML Helpers and instead had recoded the grid using html instead. I got it to work in HTML and then your email arrived! I guess that is Murphy's law at work. But that now leaves a philosophical question. Is it better to use straight HTML or the helpers. 

    The pros for the helpers would be that they enable intellisense and compile time checking of variable names and they can use Reflection to know more about the fields being encoded. But a possible con is that it may not be possible to code everything in a helper that is possible in the html. At the very least the helper might lag a release behind the html upgrades. I'm interested in people's thoughts on this.

    Also, what are the implications of turning of the AntiXssEncoder and is it possible to turn it off just for some pages?

    Thanks for your feedback.
  6. Daniel
    Admin
    Daniel avatar
    2118 posts

    Posted 11 Dec 2012 Link to this post

    Hello Martin,

    Yes, not everything possible with Kendo UI Web/DataViz is possible with the MVC wrappers because they are configured to work with the MVC Controllers and not all options can be set. 
    Regarding the encoder - by default MVC uses the HttpEncoder so the application should still be protected from cross-site scripting attacks. It is possible to change the encoder in a particular view by setting the current encoder("System.Web.Security.AntiXss.AntiXssEncoder.Current") but this will change the encoder for the entire application as well.
    It is also possible to specify the characters that does not need to be encoded with the MarkAsSafe method though I have not found a way to allow spaces in the attributes which is the reason for the error in most cases.

    Regards,
    Daniel
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  7. Robert
    Robert avatar
    38 posts
    Member since:
    Feb 2012

    Posted 06 Jun 2013 Link to this post

    I came across this problem last night, and created a solution that works without monkeying with the AntiXssEncoder in any way. You can find the solution here.

    I've opened a support ticket to get it included in the next release. Feel free to lean on them as well.

    HTH,

    Robert McLaws
    AdvancedREI.com
  8. Kelvin
    Kelvin avatar
    5 posts
    Member since:
    Oct 2012

    Posted 04 Oct 2013 Link to this post

    Perfect solution! ... and when I look to see who the author is... well, well, well! Will you look at that! Mr. McLaws! Thanks buddy.  :)
  9. Robert
    Robert avatar
    38 posts
    Member since:
    Feb 2012

    Posted 04 Oct 2013 Link to this post

    Heh, thanks Kelvin! FYI, this technique was included in the Q2 2013 release, if I'm not mistaken... so it should not be necessary to implement it yourself for Kendo. However, if you use other MVC controls that use nested templates in this manner, you'll probably need it there.

    :)
  10. Matt Miller
    Matt Miller avatar
    23 posts
    Member since:
    Jan 2012

    Posted 08 Oct 2013 Link to this post

    I have been struggling with this problem as well. I am using v2013.2.918.0 of Kendo MVC, which i believe is the latest build.

    I checked my web.config, there is no reference to AntiXssEncoder.

    Here is my client detail template:

    <script id="incompleteTrainTemplate" type="text/kendo-tmpl">       
        @(Html.Kendo().Grid<CNX.Domain.Entities.EDIRailcar>()
              .Name("IncompleteTrains_#=Id#")
              .Editable(editable => editable.Mode(GridEditMode.InCell))
              .Columns(columns =>
                {
                    columns.Bound(o => o.Id).Visible(false);
                    columns.Bound(o => o.EDI_417_TRAIN_GUID).Visible(false);
                    columns.Bound(o => o.EQUIPMENT_INITIAL);
                    columns.Bound(o => o.EQUIPMENT_NUMBER);
                    columns.Bound(o => o.WEIGHT);
                    columns.Bound(o => o.TARE_WEIGHT);
                    columns.Bound(o => o.STATUS);
                })
                .DataSource(dataSource => dataSource.Ajax()
                                                    .PageSize(10)
                                                    .Read(read => read.Action("IncompleteTrainsDetail", "MenuTrain", new { edi417Guid = "#=Id#" })
                                                    .Type(HttpVerbs.Post))
                                                    .Update(update => update.Action("IncompleteTrainsUpdate", "MenuTrain", Model).Type(HttpVerbs.Post))
                                                    .Model(model => model.Id(x => x.Id))
                                                    )
                .Pageable()
                .Sortable()
                .Filterable()
               .Events(ev => ev.Save("function(e){setTimeout(function(){$('#IncompleteTrains_\#=Id\#').data('kendoGrid').dataSource.sync()})}"))       
                .ToClientTemplate()
        )
     
    </script>
    I know the problem with my template is here $('#IncompleteTrains_\#=Id\#')

    Is this not the correct way to reference it?



  11. Daniel
    Admin
    Daniel avatar
    2118 posts

    Posted 10 Oct 2013 Link to this post

    Hello,

    You should escape the character used for the id selector instead of the ones used for the template expression:

    .Events(ev => ev.Save("function(e){setTimeout(function(){$('\\#IncompleteTrains_#=Id#').data('kendoGrid').dataSource.sync()})}"))
    On a side note, the save event is called in the context of the Grid so you do not need to find the element in order to call its or its dataSource methods:
     
    .Events(ev => ev.Save("function(e){var that = this;setTimeout(function(){that.dataSource.sync()})}"))

    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
Back to Top
UI for ASP.NET MVC is VS 2017 Ready