While using the RadGrid in Batch Mode, I am trying to do some complex client side validation on save. To do so, I am using the ClientEvents-OnCommand to handle it. What I've discovered is that if I cancel the OnCommand event (args.set_cancel(true)) the save is canceled as expected, but when I go to save again (passing validation), what the OnBatchEditCommand command receives on the server side is an UPDATE, not an Insert, and that UPDATE command's newValues and oldValues are both null.
We are currently using version 2014.3.1209.40 I'd like to know if this has been fixed in a newer version before I upgrade our solution, as that will require a full regression test.
Here is my test jig that shows the issue.
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestRadGrid.Default" UnobtrusiveValidationMode="None" %><%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %><!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title></title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script> <telerik:RadCodeBlock runat="server"> <script type="text/javascript"> var isValidatingGrid = false; function gridCommand(sender, args) { if (args.get_commandName() !== 'BatchEdit') return; var failValidationChk = $('#failValidation'); if (failValidationChk.prop("checked")) { args.set_cancel(true); return; } else { //good to save return; } } </script> </telerik:RadCodeBlock></head><body> <form id="form1" runat="server"> <asp:ScriptManager ID="theScriptManager" runat="server"></asp:ScriptManager> <div>Fail Validation<input id="failValidation" type="checkbox"/></div> <div> <telerik:RadGrid ID="EventSubjects" CssClass="eventSubjectsGrid" AutoGenerateColumns="False" GridLines="Both" AllowPaging="True" PagerStyle-AlwaysVisible="true" OnNeedDataSource="EventSubjects_NeedDataSource" OnBatchEditCommand="EventSubjects_BatchEditCommand" ValidationSettings-EnableValidation ="true" Skin="Sunset" runat="server" GroupPanelPosition="Top"> <ClientSettings AllowKeyboardNavigation="true"> <Selecting AllowRowSelect="True" /> <ClientEvents OnCommand="gridCommand"/> </ClientSettings> <MasterTableView CommandItemDisplay="Bottom" DataKeyNames="LocationID" EditMode="Batch" > <BatchEditingSettings EditType="Cell" /> <Columns><telerik:GridEditCommandColumn ButtonType="ImageButton" UniqueName="EditCommandColumn1"> <HeaderStyle Width="20px"></HeaderStyle> <ItemStyle CssClass="MyImageButton"></ItemStyle> </telerik:GridEditCommandColumn> <telerik:GridBoundColumn DataField="Location" FilterControlAltText="Filter Location column" HeaderText="Location" MaxLength="50" UniqueName="Location"> <ColumnValidationSettings EnableRequiredFieldValidation="True"> <RequiredFieldValidator Display="Dynamic" ForeColor="Red" ErrorMessage="This field is required"></RequiredFieldValidator> </ColumnValidationSettings> </telerik:GridBoundColumn> <telerik:GridTemplateColumn DataField="Barcode" HeaderText="Barcode" UniqueName="BarcodeColumn"> <ItemTemplate> <asp:Label runat="server" ID="lblBarcode" Text='<%# Eval("Barcode") %>' ></asp:Label> </ItemTemplate> <EditItemTemplate> <asp:TextBox runat="server" ID="txtBarcode" Text='<%# Bind("Barcode") %>'></asp:TextBox> <asp:CustomValidator ID="CustomValidatortxtBarcode" runat="server" ErrorMessage="Barcode already used" ControlToValidate="txtBarcode" Display="Dynamic" OnServerValidate="CustomValidatortxtBarcode_ServerValidate" > </asp:CustomValidator> </EditItemTemplate> </telerik:GridTemplateColumn> </Columns> </MasterTableView> </telerik:RadGrid> </div> </form></body></html>
Default.aspx.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using Telerik.Web.UI;namespace TestRadGrid{ public partial class Default : System.Web.UI.Page { protected global::System.Web.UI.HtmlControls.HtmlForm form1; protected global::System.Web.UI.ScriptManager theScriptManager; protected global::Telerik.Web.UI.RadGrid EventSubjects; public class AreaStops { public int LocationID { get; set; } public string Location { get; set; } public string Barcode { get; set; } } public static List<AreaStops> s_AreaStopsData = new List<AreaStops>(); static Default() { s_AreaStopsData.Add(new AreaStops() { LocationID = 1, Location = "lions", Barcode = "223" }); s_AreaStopsData.Add(new AreaStops() { LocationID = 2, Location = "tigers", Barcode = "456" }); s_AreaStopsData.Add(new AreaStops() { LocationID = 3, Location = "bears", Barcode = "789" }); s_AreaStopsData.Add(new AreaStops() { LocationID = 4, Location = "ducks", Barcode = "123" }); } protected void Page_Load(object sender, EventArgs e){ } protected void EventSubjects_NeedDataSource(object sender, Telerik.Web.UI.GridNeedDataSourceEventArgs e) { EventSubjects.DataSource = s_AreaStopsData; } protected void EventSubjects_BatchEditCommand(object sender, Telerik.Web.UI.GridBatchEditingEventArgs e) { System.Diagnostics.Debug.WriteLine("Batch update"); foreach (GridBatchEditingCommand curCommand in e.Commands) { System.Diagnostics.Debug.WriteLine(curCommand.Type); if (curCommand.NewValues == null || curCommand.OldValues == null){ System.Diagnostics.Debug.WriteLine("new or old data missing"); return; } string newLocation = (string)curCommand.NewValues["Location"]; string newBarcode = (string)curCommand.NewValues["Barcode"]; if (newBarcode.Contains('G')) { e.Canceled = true; curCommand.Canceled = true; return; } if (curCommand.Type == GridBatchEditingCommandType.Update) { AreaStops stop = s_AreaStopsData.FirstOrDefault(ars => ars.LocationID == (int)curCommand.OldValues["LocationID"]); if (stop != null) { stop.Location = newLocation; stop.Barcode = newBarcode; } else { s_AreaStopsData.Add(new AreaStops() { LocationID = s_AreaStopsData.Count + 1, Location = newLocation, Barcode = newBarcode }); } } else { s_AreaStopsData.Add(new AreaStops() { LocationID = s_AreaStopsData.Count + 1, Location = newLocation, Barcode = newBarcode }); } } } protected void CustomValidatortxtBarcode_ServerValidate(object source, ServerValidateEventArgs args) { bool isValid = !args.Value.Contains('F'); args.IsValid = isValid; } }}
