An example declaration of a template column (where SequenceId is a field on the main entity set and Sequence.Name is the EF navigation property):
<
telerik:GridTemplateColumn
UniqueName
=
"SequenceId"
DataField
=
"SequenceId"
SortExpression
=
"Sequence.Name"
HeaderText
=
"Sequence"
>...</
telerik:GridTemplateColumn
>
This displays as expected and can be filtered and edited correctly (see full code below). But clicking on the header to sort the column by the friendly text (via the navigation property) results in the following exception being thrown:
"Input string was not in a correct format.Couldn't store <First Sequence> in Sequence.Name Column. Expected type is Int32."
As part of troubleshooting this issue, I have added handlers for the EntityDataSource OnSelected and OnSelecting events and confirmed in a debug session that:
1. The SortExpression is correctly set in the OnSelecting event (e.g. "Sequence.Name ASC").
2. The returned Results collection in the OnSelected event is correctly sorted/ordered.
But when the Results collection is bound to the grid, it errors as listed above, and no sorting occurs.
Note: I can get sorting to work as expected by setting DataField="Sequence.Name" in the GridTemplateColumn, but then inserting and updating fails with this exception:
"A property named 'Sequence.Name' was not found on the entity during an insert, update, or delete operation. Check to ensure that properties specified as binding expressions are available to the data source."
Is there any way to get this to work with both? Sort based on a navigation property and insert/update based on the data model foreign key ID?
This issue can be reproduced with the following code:
Entity Framework Models:
public
partial
class
SortTest
{
public
int
SortTestId {
get
;
set
; }
public
string
Description {
get
;
set
; }
public
Nullable<
int
> SequenceId {
get
;
set
; }
public
virtual
Sequence Sequence {
get
;
set
; }
}
public
partial
class
Sequence
{
public
Sequence()
{
this
.SortTests =
new
HashSet<SortTest>();
}
public
int
SequenceId {
get
;
set
; }
public
string
Name {
get
;
set
; }
public
virtual
ICollection<SortTest> SortTests {
get
;
set
; }
}
An aspx page containing a simple RadGrid and EntityDataSource declarations:
<
telerik:RadAjaxPanel
runat
=
"server"
ID
=
"RadAjaxPanel1"
>
<
telerik:RadGrid
ID
=
"ResultGrid"
DataSourceID
=
"SortTestsEntitySource"
runat
=
"server"
AllowSorting
=
"True"
AllowFilteringByColumn
=
"true"
AutoGenerateColumns
=
"false"
>
<
MasterTableView
CommandItemDisplay
=
"Top"
DataKeyNames
=
"SortTestId"
EditMode
=
"Batch"
PageSize
=
"20"
TableLayout
=
"Auto"
Width
=
"95%"
HeaderStyle-Width
=
"100px"
>
<
BatchEditingSettings
EditType
=
"Row"
></
BatchEditingSettings
>
<
Columns
>
<
telerik:GridBoundColumn
DataField
=
"SortTestId"
HeaderText
=
"SortTestId"
></
telerik:GridBoundColumn
>
<
telerik:GridBoundColumn
DataField
=
"Description"
HeaderText
=
"Description"
></
telerik:GridBoundColumn
>
<
telerik:GridTemplateColumn
UniqueName
=
"SequenceId"
DataField
=
"SequenceId"
SortExpression
=
"Sequence.Name"
HeaderText
=
"Sequence"
>
<
FilterTemplate
>
<
telerik:RadComboBox
ID
=
"RadComboBoxModel"
DataSourceID
=
"SequencesEntitySource"
DataTextField
=
"Name"
DataValueField
=
"SequenceId"
AppendDataBoundItems
=
"true"
SelectedValue='<%# ((GridItem)Container).OwnerTableView.GetColumn("SequenceId").CurrentFilterValue %>'
runat="server" OnClientSelectedIndexChanged="SequencesIndexChanged">
<
Items
>
<
telerik:RadComboBoxItem
Text
=
"All"
/>
</
Items
>
</
telerik:RadComboBox
>
<
telerik:RadScriptBlock
ID
=
"RadScriptBlock1"
runat
=
"server"
>
<
script
type
=
"text/javascript"
>
function SequencesIndexChanged(sender, args) {
var tableView = $find("<%# ((GridItem)Container).OwnerTableView.ClientID %>");
tableView.filter("SequenceId", args.get_item().get_value(), "EqualTo");
}
</
script
>
</
telerik:RadScriptBlock
>
</
FilterTemplate
>
<
ItemTemplate
>
<%# Eval("Sequence.Name") %>
</
ItemTemplate
>
<
EditItemTemplate
>
<
telerik:RadDropDownList
style
=
"width:auto;"
runat
=
"server"
ID
=
"SequenceDropDown"
DataValueField
=
"SequenceId"
DataTextField
=
"Name"
DataSourceID
=
"SequencesEntitySource"
></
telerik:RadDropDownList
>
</
EditItemTemplate
>
</
telerik:GridTemplateColumn
>
</
Columns
>
</
MasterTableView
>
</
telerik:RadGrid
>
</
telerik:RadAjaxPanel
>
EntityDataSource Declarations:
<
asp:EntityDataSource
runat
=
"server"
ID
=
"SortTestsEntitySource"
ConnectionString
=
"name=TelerikSortTestEntities"
DefaultContainerName
=
"TelerikSortTestEntities"
OnSelecting
=
"SortTestsEntitySource_OnSelecting"
OnSelected
=
"SortTestsEntitySource_OnSelected"
EnableFlattening
=
"False"
EnableInsert
=
"False"
EnableUpdate
=
"True"
EnableDelete
=
"False"
EntitySetName
=
"SortTests"
EntityTypeFilter
=
"SortTest"
Include
=
"Sequence"
>
</
asp:EntityDataSource
>
<
asp:EntityDataSource
runat
=
"server"
ID
=
"SequencesEntitySource"
ConnectionString
=
"name=TelerikSortTestEntities"
DefaultContainerName
=
"TelerikSortTestEntities"
EntitySetName
=
"Sequences"
EntityTypeFilter
=
"Sequence"
>
</
asp:EntityDataSource
>
Code behind event handlers for the aspx page:
protected
void
SortTestsEntitySource_OnSelecting(
object
sender, EntityDataSourceSelectingEventArgs e)
{
// verify that e.SelectArguments.SortExpression is correct in a Watch window or Immediate Window etc.
}
protected
void
SortTestsEntitySource_OnSelected(
object
sender, EntityDataSourceSelectedEventArgs e)
{
// inspect the e.Results collection and verify it is correctly sorted/ordered
}
Exception full stack trace:
at System.Data.DataColumn.set_Item(Int32 record, Object value)
at System.Data.DataRow.set_Item(DataColumn column, Object value)
at System.Data.DataRow.set_Item(String columnName, Object value)
at Telerik.Web.UI.GridDataTableFromEnumerable.FillDataTableFromEnumerable(IQueryable enumerable)
at Telerik.Web.UI.GridDataTableFromEnumerable.FillData35()
at Telerik.Web.UI.GridDataTableFromEnumerable.FillData()
at Telerik.Web.UI.GridResolveEnumerable.Initialize()
at Telerik.Web.UI.GridResolveEnumerable.EnsureInitialized()
at Telerik.Web.UI.GridResolveEnumerable.get_DataTable()
at Telerik.Web.UI.GridEnumerableFromDataView..ctor(GridTableView owner, IEnumerable enumerable, Boolean CaseSensitive, Boolean autoGenerateColumns, GridColumnCollection presentColumns, String[] additionalField, Boolean retrieveAllFields, Boolean enableSplitHeaderText)
at Telerik.Web.UI.GridDataSourceHelper.CreateGridEnumerable(GridTableView owner, IEnumerable enumerable, Boolean caseSensitive, Boolean autoGenerateColumns, GridColumnCollection presentColumns, String[] additionalField, Boolean retrieveAllFields, Boolean enableSplitHeaderText)
at Telerik.Web.UI.GridDataSourceHelper.GetResolvedDataSource(GridTableView owner, Object dataSource, String dataMember, Boolean caseSensitive, Boolean autoGenerateColumns, GridColumnCollection presentColumns, String[] additionalField, Boolean retrieveAllFields, Boolean enableSplitHeaderText)
at Telerik.Web.UI.GridTableView.get_ResolvedDataSource()
at Telerik.Web.UI.GridTableView.CreateControlHierarchy(Boolean useDataSource)
at Telerik.Web.UI.GridTableView.CreateChildControls(IEnumerable dataSource, Boolean useDataSource)
at System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data)
at System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data)
at System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback)
at System.Web.UI.WebControls.DataBoundControl.PerformSelect()
at Telerik.Web.UI.GridTableView.PerformSelect()
at System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
at Telerik.Web.UI.GridTableView.DataBind()
at Telerik.Web.UI.GridSortCommandEventArgs.ExecuteCommand(Object source)
at Telerik.Web.UI.RadGrid.OnBubbleEvent(Object source, EventArgs e)
at System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args)
at Telerik.Web.UI.GridItem.OnBubbleEvent(Object source, EventArgs e)
at System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args)
at Telerik.Web.UI.GridItem.OnBubbleEvent(Object source, EventArgs e)
at Telerik.Web.UI.GridItem.FireCommandEvent(String commandName, Object commandArgument)
at Telerik.Web.UI.RadGrid.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)