Circular Reference- LINQ to SQL - asp.net-mvc

HI
I am using telerik mvc grid with ajax binding
<%Html.Telerik().Grid<UserManagement.Models.setupEmployee>()
.Name("setupEmployees")
.DataBinding(dataBinding => dataBinding
//Ajax binding
.Ajax()
//The action method which will return JSON
.Select("_AjaxBindingEmployee", "UM")
).
Columns(colums =>
{
colums.Bound(o => o.EmployeeName).Title("Name");
colums.Bound(o => o.setupDesignation.Title).Title("Designation");
colums.Bound(o => o.Gender);
colums.Bound(o => o.DOB);
colums.Bound(o => o.EmployeeID).Format(
%><%Html.ActionLink("Edit", "Edit", new { Id = "{0}" }).ToString()).Encoded(false);
})
.Pageable()
.Sortable()
.Filterable()
.PrefixUrlParameters(false)
.Render();
%>
when i try to populate the grid with
return db.setupEmployees
i get the following error
A circular reference was detected while serializing an object of type. As i have relationship of this table with other tables.
To avoid this i may have two options either i use viewmodel or disable the relationships which is not possible. Any other sugession from your side
Regards

The associations created in the LinqToSql designer are under your control.
You can remove them (does not change the database).
You can edit them so they generate single sided properties instead of dual facing properties (does not change the database).
You can edit them so they generate no properties at all (does not change database).
The designer's file is a mapping file, it does not change the database.

Related

Kendo UI Grid, sorting datasource groups

I have a page that has a Kendo grid on it.
It is calling an ajaz web request to get its data.
Once the data has been returned it is grouped in the frontend.
The problem I am having is sorting the groups. What is the best way to do this?
My MVC view code looks something like this...
.DataSource(dataSource => dataSource
.Ajax()
.Group(groups =>
{
groups.Add(c => c.groupingField);
})
.Read(...))
I have tried to use the sort method but am not sure where to put it when the data is coming from an ajax call.
I found that adding the below line to the datasource call solved my problem...
.Sort(sort => sort.Add("FIELD_NAME").Ascending())
You need to provide groups in correct order in .Group() method. I don't have mvc version installed but for example it should be ok:
var groupList = new List<string> { "Gr1", "Gr2" };
.DataSource(dataSource => dataSource
.Ajax()
.Group(groups =>
{
groupList.Select(x => groups.Add(x));
})
.Read(...))

kendo grid - dynamic column with cell format from database

I have a SQL Table result.
ProductNumber ProductNumberColorClass OrderNumber OrderNumberColorClass
I am trying to use Kendo to render this information. Basically i need the output as
ProductNumber OrderNumber
Data value and Apply Css class( ProductNumberColorClass )
Basically this is a report with a lot of columns. The user can select only the columns that he wants to see.
I am able to render the grid using the examples from the web site. I am not able to apply.
My application is Asp.net mvc application
Update
I will try your feedback. This is my code. Basically i wanted to avoid coding for each column as the list is big around 50 . the report can be customized so the user can hide some columns. .So i used a loop. however in this scenario, the clienttemplate is not work. I am not very sure, if it is a code issue too.
If you can find what is wrong in my code it will help me learn about the issue too.
meanwhileI am going to manually type the columns and add a attribute as visible
#(Html.Kendo().Grid <DataTransferObjects.ViewModels.UserReportDataModel>()
.Name("Grid")
.HtmlAttributes(new { style = "height: 550px;" })
.Pageable(pageable => pageable
.Input(true)
.Numeric(false)
)
.Sortable()
.Scrollable(
scr => scr.Height(430)
)
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("GetReportData", "ShortTermPlanner").Data("AdditionnalParameters"))
.PageSize(20)
.ServerOperation(false)
)
.Columns(columns =>
{
var colIndex = 0;
foreach (var col in Model.lstHeaderInformation)
{
if (col.SqlColumnName == "ProductNumber")
{
columns.Bound(col.SqlColumnName)
.Title(col.ColumnHeader)
.Filterable(false)
.Visible(col.IsVisible)
.Width(1190)
.ClientTemplate("<div style='background-color:red; text-align:center;width:70px'> #= ProductNumber # </div>");
}
else
{
columns.Bound(col.SqlColumnName)
.Title(col.ColumnHeader)
.Filterable(true)
.Visible(true)
.Width(300)
.Locked(true)
.HtmlAttributes(new { #class = "selectedRow" });
}
}
})
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
)
Update 2 Adding the clienttemplate and specifying the column information worked. Thanks
However i am curious, is there a better way where i can loop through a 3 table which defines the column name, title and class that needed to be displayed and applied to my report.
what i am looking is
MY Report -- Select * from Report
My header table Select colname, title, class from reportcoldefinication
so now for each matching colname from reportcoldefinication
and Report. add a col to the grid with the class applied.
You can use the template functionality for columns in the Kendo grid.
columns.Template(#<div class= '#=ProductNumberColorClass #'> #= ProductNumber#<div/>)
Have implemented one in the example in the below link. Its implemented using JQuery but you can use the razor syntax for kendo for achieving the same.
http://dojo.telerik.com/ukIma/3

Kendo MVC Grid Default Sort by Multiple Column Fails

#(Html.Kendo().Grid<...>()
.Columns(columns =>
{
columns.Bound(j => j.Type);
columns.Bound(j => j.Code);
})
.Sortable(s => s.Enabled(true))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Sort(p => { p.Add("Code").Ascending(); p.Add("Type").Ascending(); })
.Model(model => model.Id(j => j.ID))
.Read(...)
.ServerOperation(true)
)
)
I have a Kendo MVC Grid as above and want to sort it first by type, then by code.
I have found such implementation on official Telerik forum: Default Grid Sorting
However it seems it fails to work...
The records are sorted by two columns, and apparently it is sorted by Type, but it fails to sort by Code afterwards...As Default should after CG...
What am I missing and how can I fix the problem?
For anyone else looking for a solution, using the model property names worked for me, i.e.
.Sort(s =>
{
s.Add("Code").Ascending();
s.Add("Type").Ascending();
})
Try this way
.Sort(p=> {p.Add(s=>s.Code).Ascending(); p.Add(s=>s.Type).Ascending();})

Telerik Tabstrip not displaying inside Telerik Grid

I have a Telerik MVC grid with a single detail view.
Inside the detail view is a telerik tabstrip. When I select the grid row to display, the detail will open up completely empty.
I have copied the tabstrip code outside the grid, changing the name of the grid to a static name and rendering the grid instead of outputting it as an htmlstring, and it displays perfectly.
I've tried registering all required javascript files, no change.
I'm pretty stumped at this point. I've cleared out the entire tabstrip so it contains nothing but text, but no change.
Here's the code which i have:
<%: Html.Telerik().Grid(Model.AccessRequests)
.Name("gridAccessRequests")
.ColumnContextMenu()
.DataKeys(d => { d.Add(a => a.Access_Request_ID).RouteKey("id");})
.DataBinding(dataBinding => dataBinding
.Ajax()
.Select("AjaxBinding", "Home")
.Insert("Insert", "Home")
.Update("Save", "Home")
.Delete("Delete", "Home"))
.ToolBar(commands => commands.Insert())
.Editable(editing => editing
.InsertRowPosition(GridInsertRowPosition.Bottom)
.Mode(GridEditMode.PopUp))
.HtmlAttributes(new { style = "width:100%" })
.Selectable()
.Sortable(sorting => sorting
.OrderBy(sortOrder => sortOrder.Add(o => o.EMPLOYEE_NAME).Ascending()))
.Filterable(filtering => filtering
.Filters(filters => filters
.Add(o => o.RECORD_YEAR).IsEqualTo(Model.CurrentYear)))
.Pageable(paging =>
paging.PageSize(15)
.Style(GridPagerStyles.NextPreviousAndNumeric)
.Position(GridPagerPosition.Both))
.ClientEvents(events =>
{
events.OnEdit("onEdit");
events.OnRowDataBound("requests_onRowDataBound");
})
.DetailView(details => details.ClientTemplate(
Html.Telerik()
.TabStrip()
.Name("TabStrip_<#=id#>")
.SelectedIndex(0)
.Items(items =>
{
items.Add().Text("Assets").Content("Assets");
items.Add().Text("Locations").Content("Locations");
})
.ToHtmlString()
))
.Columns(col =>
{
col.Bound(c => c.Access_Request_ID).Title("ID");
col.Bound(c => c.RECORD_YEAR).Title("Year");
col.Bound(c => c.VERSION_NO).Title("Version");
col.Bound(c => c.EMPLOYEE_NAME).Title("Name");
col.Command(commands =>
{
commands.Edit()
.ButtonType(GridButtonType.Image);
commands.Delete()
.ButtonType(GridButtonType.Image);
commands.Custom("Clone")// the constructor accepts the name of the custom command (used to differentiate between multiple custom commands)
.Text("Clone")
// Specify which fields from the bound data item to include in the route (pass as action method arguments)
.DataRouteValues(route => route.Add(o => o.Access_Request_ID).RouteKey("requestId"))
.Ajax(true)
// Which action method to call
.Action("CloneRequest", "Home");
}).Width(145)
.IncludeInContextMenu(false);
})%>
Here is the standalone tabstrip:
<%
Html.Telerik().TabStrip()
// Make the Name unique
.Name("TabStrip")
.SelectedIndex(0)
.Items(items =>
{
items.Add().Text("Assets").Content("Assets");
items.Add().Text("Locations").Content("Locations");
})
.Render();
%>
Any Suggestion/ Solution/Demo will be helpful.
Thanks in advance!
UPDATE
I have figured out that the tabstrips are not displaying on initial load of the grid; after hitting the grid's refresh button or paging the tabstrips display and function correctly.
It appears that there is an invalid property value error being thrown after the grid is loaded but before any databinding is completed, but I still can't seem to pinpoint the exact problem. Again, hitting the grid's refresh button or paging will successfully databind all the rows.
When the page first loads, the grid is loaded via server side binding. The tab strips are defined in the client template which is not used during server binding. When you refresh the grid, it is loaded via ajax binding and the client template is used.
You need to make the grid load initially via ajax binding so you need to use a different constructor.
Change this:
Html.Telerik().Grid(Model.AccessRequests)
to this:
Html.Telerik().Grid<AccessRequests>() //Put in the appropriate type for AccessRequests

Kendo mvc grid batch mode dataItem.set clears the dirty flags

When I change an amount, tick the checkbox etc, it triggers some javascript, which includes some code to set another field on the dataItem, so dataItem.Set ("Amount", 0);
I can set it using dataItem.Amount = 0; , but then I also need to update the contents of the cell. When I do set I obviously don't want the dirty flag clearing from other cells, as I haven't clicked 'Save changes' yet, so they are still 'dirty'.
I can't find any documentation on the .set method.
Any advice would be appreciated.
#(Html.Kendo().Grid<OurViewModel>()
.Name("Grid")
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(a => a.ID);
model.Field(a => a.Reference).Editable(false);
model.Field(a => a.Narrative).Editable(false);
model.Field(a => a.Include).Editable(true);
model.Field(a => a.Amount).Editable(true);
})
.Batch(true)
.Read(read => read.Action("_Read", "Home"))
.Update(update => update.Action("_Update", "Home"))
.ServerOperation(false)
.Events(events =>
{
events.Change("onDataSourceChange");
})
)
.Columns(columns =>
{
columns.Bound(a => a.Reference).Title("Reference");
columns.Bound(a => a.Narrative).Title("Narrative");
columns.Template(#<text></text>).Title("Include?")
.ClientTemplate("<input type='checkbox' #= Include ? checked='checked': '' # onclick='updateAmount(this, \"#= ID#\")' />");
columns.Bound(a => a.Amount).Title("Amount");
})
.Events(events =>
{
events.Save("onSave");
events.SaveChanges("onSaveChanges");
})
.ToolBar(toolbar =>
{
toolbar.Save();
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
)
and the JS.
function updateAmount(cb, ourID) {
var checked = $(cb).is(':checked');
var grid = $('#Grid').data().kendoGrid;
var dataItem = grid.dataSource.get(ourID);
dataItem.set("Include", checked);
if (checked) {
dataItem.set("Amount", dataItem.get("OriginalAmount"));
} else {
dataItem.set("Amount", 0);
}
}
When calling the set method on an observable object (Note: Each dataItem in the dataSource in converted to a kendo ObservableObject when loaded) any widgets that our bound to the dataItem will be updated, in this case your grid is the bound widget.
If you set the value directly (i.e. dataItem.Amount = 0) none of the observable object's binding events will trigger and the grid (or any other widgets bound to the dataItem) will NOT update. You should always use set when modifying fields of an observable object in order to keep the UI up to date.
Within the dataSource, there are no dirty flags for the individual fields in the dataItem. The dataItem itself will have a field named "dirty" which will be set to true whenever ANY of its fields change. Changing more than 1 field will just keep setting dirty = true for the entire dataItem. You don't need to worry about tracking modified fields. Once a row is dirty it will stay dirty until you save the data.
When you save the contents of the grid (a.k.a. sync the dataSource) any (and only) rows with dirty = true will be sent to the server. Once saved, the dirty flags will be removed. On that note, you will want to refrain from using "dirty" as a table property in your database.
The kendo documentation at is pretty complete but I would highly recommend tracing through the kendo javascript code to really learn it. One last note, I started with the Kendo MVC approach hoping to leverage by C# knowledge but soon found it much easier to just code all the client side in JavaScript. All your C# code gets converted to rather verbose JavaScript anyway each time the server it hit. This puts unnecessary load on the server and makes client side debugging harder IMO.

Resources