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

Uncaught Error: Invalid template in nested Grid

9 Answers 651 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Martin
Top achievements
Rank 1
Martin asked on 05 Dec 2012, 06:39 AM
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.

9 Answers, 1 is accepted

Sort by
0
Martin
Top achievements
Rank 1
answered on 06 Dec 2012, 05:18 AM
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.
0
Daniel
Telerik team
answered on 07 Dec 2012, 06:43 AM
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!
0
Martin
Top achievements
Rank 1
answered on 07 Dec 2012, 07:44 AM
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.
0
Daniel
Telerik team
answered on 11 Dec 2012, 02:14 PM
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!
0
Robert
Top achievements
Rank 1
answered on 06 Jun 2013, 08:43 PM
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
0
Kelvin
Top achievements
Rank 1
answered on 04 Oct 2013, 02:38 PM
Perfect solution! ... and when I look to see who the author is... well, well, well! Will you look at that! Mr. McLaws! Thanks buddy.  :)
0
Robert
Top achievements
Rank 1
answered on 04 Oct 2013, 02:45 PM
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.

:)
0
Matt Miller
Top achievements
Rank 1
answered on 08 Oct 2013, 01:10 PM
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?



0
Daniel
Telerik team
answered on 10 Oct 2013, 08:51 AM
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!
Tags
Grid
Asked by
Martin
Top achievements
Rank 1
Answers by
Martin
Top achievements
Rank 1
Daniel
Telerik team
Robert
Top achievements
Rank 1
Kelvin
Top achievements
Rank 1
Matt Miller
Top achievements
Rank 1
Share this question
or