I have a Asp.Net MVC project created from Syncfusion ASP.New MVC (Essential JS 2) VS template that is using Syncfusion's Data Grid. I can get the CrudUpdate event set in CrudUrl to fire at the server, however the value returned to CrudUpdate is empty. action parameter seems correctly set.
If I cast the value as Object, I get back a not-null, but VS cannot interrogate it. My guess is some weirdness in the way the value is cast or returned.
Has anyone got a complete working sample of the Syncfusion grid using the CrudUrl method with MVC (not asp). I am also guessing I may have some dependency issue.
View
#Html.EJS().Grid("CrudUrl").DataSource(dataManager => { dataManager.Url("/TestGrid2/UrlDatasource").CrudUrl("/TestGrid2/CrudUpdate").Adaptor("UrlAdaptor"); }).Columns(col =>
{
col.Field("RowKey").IsPrimaryKey(true).Add();
col.Field("PartitionKey").Add();
col.Field("sourceResourceId").Add();
col.Field("imagesLocation").Add();
col.Field("imagesResourceGroup").Add();
col.Field("imagePrefix").Add();
col.Field("imageVersion").Add();
}).AllowPaging().Toolbar(new List<string>() { "Search", "Add", "Edit", "Delete", "Update", "Cancel" }).EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true); }).Render()
Controller
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Script.Services;
using System.Web.Services;
using DB;
//using Microsoft.AspNetCore.Mvc;
using Syncfusion.EJ2.Base;
namespace VMSSManagmentConsole.Controllers
{
public class TestGrid2Controller : Controller
{
private ModelContainer db = new ModelContainer();
public ActionResult TestGrid2()
{
//var items = db.ManagementItems.ToList();
//ViewBag.dataSource = items;
return View();
}
public ActionResult UrlDatasource([FromBody]DataManagerRequest dm)
{
IEnumerable DataSource = db.ManagementItems.ToList();
DataOperations operation = new DataOperations();
int count = DataSource.Cast<ManagementItem>().Count();
if (dm.Skip != 0)
{
DataSource = operation.PerformSkip(DataSource, dm.Skip); //Paging
}
if (dm.Take != 0)
{
DataSource = operation.PerformTake(DataSource, dm.Take);
}
var result = (ActionResult)(dm.RequiresCounts ? Json(new { result = DataSource, count = count }) : Json(DataSource));
return result;
}
public ActionResult CrudUpdate([FromBody]ICRUDModel<ManagementItem> value, string action)
{
//if (value.action == "update")
//{
// var ord = value.value;
// ManagementItem val = db.ManagementItems.Where(or => or.RowKey == ord.RowKey).FirstOrDefault();
// val.imagePrefix = ord.imagePrefix;
// val.imagesLocation = ord.imagesLocation;
// val.imagesResourceGroup = ord.imagesResourceGroup;
// val.imageVersion = ord.imageVersion;
// val.sourceResourceId = ord.sourceResourceId;
//}
//else if (value.action == "insert")
//{
// db.ManagementItems.Add(value.value);
//}
//else if (value.action == "remove")
//{
// db.ManagementItems.Remove(db.ManagementItems.Where(or => or.RowKey == value.key.ToString()).FirstOrDefault());
// return Json(value);
//}
//return Json(value.value);
return null;
}
public class ICRUDModel<T> where T : class
{
public string action { get; set; }
public string table { get; set; }
public string keyColumn { get; set; }
public object key { get; set; }
public T value { get; set; }
public List<T> added { get; set; }
public List<T> changed { get; set; }
public List<T> deleted { get; set; }
public IDictionary<string, object> #params { get; set; }
}
}
}
Use the DataGrid scaffold wizard. On the third page select DataSourceType = "Remote Data". A page and controller will be created with the correct code.
For your reference, we have created a sample and perform CRUD actions. Please refer the attached sample for more information.
Sample: https://www.syncfusion.com/downloads/support/directtrac/general/ze/GridEJ2Mvc-914352281
The reported problem occurred when model mismatched. For Example, when we specify the number column field(EmployeeID) in grid but while inserting you did not specify the value for that column then it shows value as null in CrudUpdate, for this scenario you need to specify the nullable value for that field in model class as follows.
public class OrdersDetails
{
public OrdersDetails(int OrderID, string CustomerId, int EmployeeId, double Freight, bool Verified, DateTime OrderDate, string ShipCity, string ShipName, string ShipCountry, DateTime ShippedDate, string ShipAddress)
{
this.OrderID = OrderID;
this.CustomerID = CustomerId;
this.EmployeeID = EmployeeId;
. . . . .
}
public static List<OrdersDetails> GetAllRecords()
{
if (order.Count() == 0)
{
int code = 10000;
for (int i = 1; i < 10; i++)
{
order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6"));
. . . . .
}
}
return order;
}
public int? OrderID { get; set; }
public string CustomerID { get; set; }
public int? EmployeeID { get; set; } // it accept null value
. . . . .
}
}
If you still face the problem then share more details or below information that will helpful for us to validate further and provide a better solution as soon as possible.
• Did the problem occurred for both update and insert?
• Share package version details.
Regards,
Thavasianand S.
I am new to the Neo4jClient as well as Neo4J so was not sure how to query for the data and get a master detail like data in the neo4j. Let me explain this with an example:
lets suppose I have a graph as below:
root -[:DEFINES] -> Shipment 1
-[:HAS_CONSIGNMENT]->Consignment 1
-[:HAS_ITEM]->Load Item 11
-[:HAS_ITEM]->Load Item 12
-[:HAS_CONSIGNEE]->Consignee 1
-[:HAS_CONSIGNMENT]->Consignment 2
-[:HAS_ITEM]->Load Item 21
-[:HAS_ITEM]->Load Item 22
-[:HAS_CONSIGNEE]->Consignee 2
now suppose I want to get all the graph t o populate my Domain Model like below
public class Shipment
{
public List<Consignment> Consignments {get; set;}
}
public class Consignment
{
public List<LoadItem> LoadItems {get; set;}
public Consignee ShippedTo {get; set;}
}
public class LoadItem
{
}
i know that I can probably build a Cypher query like below
How to retrieve connected graph using neo4jclient
query = client.Cypher.Start(new { root = client.RootNode }).
Match("root-[:DEFINES]->load-[:HAS_CONSIGNMENT]->consignments -[:HAS_ITEM]->loadItem").Match("consignments-[:HAS_CONSIGNEE]->consignee").
Where((Load load) => load.Id == myId).
Return(
(load,consignments, loaditems)=>
new {
loadInfo = load.As<Node<Load>>(),
consignments = consignments.CollectAs<Consignment>(),
loadItems = loaditems.CollectAs<LoadItem>()
});
but I am not sure how this can be converted to represent the second level of list that gives me that Consignment 2 has Load Item 21 & 22 where as Consignment 1 has Item 11 & 12.
can some one please help me understand how this works as I primarily have been working in the EF and the graph query is really new to me.
Regards
Kiran
Right, this is the way I've got this working (I'm pretty sure Tatham will come along with a better answer - so hold out for a bit)
public static ICollection<Shipment> Get()
{
var query = GraphClient.Cypher
.Start(new {root = GraphClient.RootNode})
.Match(
string.Format("root-[:{0}]->shipment-[:{1}]-consignments-[:{2}]->loadItem", Defines.TypeKey, HasConsignment.TypeKey, HasItem.TypeKey),
string.Format("consignments-[:{0}]->consignee", HasConsignee.TypeKey)
)
.Return((shipment, consignments, loadItem, consignee) =>
new
{
Shipment = shipment.As<Node<Shipment>>(),
Consignment = consignments.As<Consignment>(),
LoadItem = loadItem.CollectAs<LoadItem>(),
Consignee = consignee.As<Consignee>(),
});
var results = query.Results.ToList();
var output = new List<Node<Shipment>>();
foreach (var result in results)
{
var shipmentOut = output.SingleOrDefault(s => s.Reference == result.Shipment.Reference);
if (shipmentOut == null)
{
shipmentOut = result.Shipment;
shipmentOut.Data.Consignments = new List<Consignment>();
output.Add(shipmentOut);
}
result.Consignment.LoadItems = new List<LoadItem>();
result.Consignment.LoadItems.AddRange(result.LoadItem.Select(l => l.Data));
shipmentOut.Data.Consignments.Add(result.Consignment);
}
return output.Select(s => s.Data).ToList();
}
This will get you all the Shipments and Consignments etc.
However I note you do: .Where((Load load) => load.Id == myId) which implies you know the shipment id.
As a consequence, we can simplify the code a little bit - as we don't need to use 'root', and we can pass in the Shipment ID.
public static Shipment Get2(NodeReference<Shipment> shipmentNodeReference)
{
var query = GraphClient.Cypher
.Start(new {shipment = shipmentNodeReference})
.Match(
string.Format("shipment-[:{0}]-consignments-[:{1}]->loadItem", HasConsignment.TypeKey, HasItem.TypeKey),
string.Format("consignments-[:{0}]->consignee", HasConsignee.TypeKey)
)
.Return((shipment, consignments, loadItem, consignee) =>
new {
Shipment = shipment.As<Node<Shipment>>(),
Consignment = consignments.As<Consignment>(),
LoadItem = loadItem.CollectAs<LoadItem>(),
Consignee = consignee.As<Consignee>(),
});
var results = query.Results.ToList();
//Assuming there is only one Shipment returned for a given ID, we can just take the first Shipment.
Shipment shipmentOut = results.First().Shipment.Data;
shipmentOut.Consignments = new List<Consignment>();
foreach (var result in results)
{
result.Consignment.ShippedTo = result.Consignee;
result.Consignment.LoadItems = new List<LoadItem>();
result.Consignment.LoadItems.AddRange(result.LoadItem.Select(l => l.Data));
shipmentOut.Consignments.Add(result.Consignment);
}
return shipmentOut;
}
For your info, the DataElements I was using were:
public class Shipment
{
public string Id { get; set; }
public List<Consignment> Consignments { get; set; }
public override string ToString() { return Id; }
}
public class Consignment
{
public string Id { get; set; }
public List<LoadItem> LoadItems { get; set; }
public Consignee ShippedTo { get; set; }
public override string ToString() { return Id; }
}
public class Consignee
{
public string Name { get; set; }
public override string ToString() { return Name; }
}
public class LoadItem
{
public string Item { get; set; }
public override string ToString() { return Item; }
}
With relationships all defined like:
public class HasConsignment : Relationship, IRelationshipAllowingSourceNode<Shipment>, IRelationshipAllowingTargetNode<Consignment>
{
public const string TypeKey = "HAS_CONSIGNMENT";
public HasConsignment() : base(-1) {}
public HasConsignment(NodeReference targetNode): base(targetNode) {}
public HasConsignment(NodeReference targetNode, object data) : base(targetNode, data) {}
public override string RelationshipTypeKey { get { return TypeKey; } }
}
(with obvious changes where needed)
I am working on SOA based project and i got got a situation where I am sending the whole array of object to server and then I have to see which of the objects are new and which one I have to update, hence I am looking for some generic function which can get me the list with update , delete or insert attribute
I was facing the same problem where I was sending entity with multiple children entities. The challenge was to figure out what child entity has been updated, added or deleted. Here what I did.
Implemented IObjectWithState with ChildEntity. (Inspired from one of pluralsight entityframework video)
Pull the server side version of entity.
Invoked FindDifference to get the difference of Child entities on client and server
IList<ClassTicket> clientSideTickets = /// What received from client
IList<ClassTicket> serverSideTickets = /// What received from database
var diffTickets = FindDifference(clientSideTickets ,serverSideTickets ,
(ticket1, ticket2) => ticket1.Id == ticket2.Id,(ticket1, ticket2) => ticket1.Name == ticket2.Name && ticket1.NoOfTicketsAvailable == ticket2.NoOfTicketsAvailable && ticket1.Price == ticket2.Price);
public interface IObjectWithState
{
State State { get; set; }
}
// My Child Entity
public class ClassTicket: IObjectWithState
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public short NoOfTicketsAvailable { get; set; }
public State State { get; set; }
}
public static IEnumerable<T> FindDifference<T>(IEnumerable<T> clientList, IEnumerable<T> serverList, Func<T, T, bool> identityDetector, Func<T, T, bool> changeDetector) where T : IObjectWithState
{
var finalList = new List<T>();
var clientItems = clientList as T[] ?? clientList.ToArray();
var serverItems = serverList as T[] ?? serverList.ToArray();
foreach (var clientItem in clientItems)
{
bool foundInServerList = false;
foreach (var serverItem in serverItems)
{
if(identityDetector(clientItem, serverItem))
{
foundInServerList = true;
clientItem.State = !changeDetector(clientItem, serverItem) ? State.Modified : State.Unchanged;
finalList.Add(clientItem);
break;
}
}
if(!foundInServerList)
{
clientItem.State = State.Added;
finalList.Add(clientItem);
}
}
foreach (var serverItem in serverItems)
{
var foundInClientList = clientItems.Any(clientItem => identityDetector(serverItem, clientItem));
if (!foundInClientList)
{
serverItem.State = State.Deleted;
finalList.Add(serverItem);
}
}
return finalList;
}
I have a simple model, it is Entity Framework 5 Code First, ActiveEntity is an abstract class with an int Id property and a bool IsActive field.
public class License:ActiveEntity
{
public string LicenseName { get; set; }
public LicenseType LicenseType { get; set; }
public State State { get; set; }
public DateTime DateIssued { get; set; }
public int ValidFor { get; set; }
}
public class LicenseType:ActiveEntity
{
[StringLength(100),Required]
public string Description { get; set; }
}
public class State:ActiveEntity
{
[StringLength(2)]
[Required]
public string Name { get; set; }
[Display(Name = "Long Name")]
[Required, StringLength(25)]
public string LongName { get; set; }
}
Breeze makes a call to GetLicenses on the LicenseController:
[BreezeController]
public class LicenseController : ApiController
{
private readonly EFContextProvider<LicensingContext> db = new EFContextProvider<LicensingContext>();
[HttpGet]
public string Metadata()
{
return db.Metadata();
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return db.SaveChanges(saveBundle);
}
[HttpGet]
public IQueryable<License> GetLicenses()
{
//for debugging purposes
var retVal = db.Context.Licenses
.Include(l => l.State)
.Include(l=>l.LicenseType);
return retVal;
}
}
The db context returns the appropriate data but it does not appear in the response.
I don't have enough reputation points to post an image but the license type and state are in the context's response.
However the controller's response does not contain the licensetype object for the first three objects.
[{"$id":"1","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"Low Voltage","State":{"$id":"2","$type":"Volt.Telecom.Licensing.Models.State, Volt.Telecom.Licensing.Models","Name":"FL","LongName":"Florida","IsActive":false,"Id":23},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":1},{"$id":"3","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"Contractors","State":{"$ref":"2"},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":2},{"$id":"4","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"General Contractors","State":{"$ref":"2"},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":3},{"$id":"5","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"Low Voltage","LicenseType":{"$id":"6","$type":"Volt.Telecom.Licensing.Models.LicenseType, Volt.Telecom.Licensing.Models","Description":"Low Voltage","IsActive":false,"Id":1},"State":{"$id":"7","$type":"Volt.Telecom.Licensing.Models.State, Volt.Telecom.Licensing.Models","Name":"CA","LongName":"California","IsActive":false,"Id":35},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":4},{"$id":"8","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"Contractors","LicenseType":{"$id":"9","$type":"Volt.Telecom.Licensing.Models.LicenseType, Volt.Telecom.Licensing.Models","Description":"Contractors","IsActive":false,"Id":2},"State":{"$ref":"7"},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":5},{"$id":"10","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"General Contractors","LicenseType":{"$id":"11","$type":"Volt.Telecom.Licensing.Models.LicenseType, Volt.Telecom.Licensing.Models","Description":"General Contractors","IsActive":false,"Id":3},"State":{"$ref":"7"},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":6}]
Here is the home.js file on the client.
define(['services/logger'], function (logger) {
var system = require('durandal/system');
var serviceName = 'api/License';
// manager is the service gateway and cache holder
var manager = new breeze.EntityManager(serviceName);
var vm = {
activate: getLicenses,
title: 'Licenses',
licenses: ko.observableArray(),
includeExpired: ko.observable(false),
save: saveChanges,
show: ko.observable(false)
};
//vm.includeExpired.subscribe(getLicenses);
function getLicenses() {
log("querying Licenses", null, true);
var query = breeze.EntityQuery.from("GetLicenses");
//if (!vm.includeExpired()) {
// query = query.where("DateIssued.AddDays(ValidFor*-1)" > new Date(Date.now()));
//}
return manager
.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
// reload vm.todos with the results
function querySucceeded(data) {
log("queried Licenses", null, true);
vm.licenses(data.results);
vm.show(true); // show the view
}
}
function queryFailed(error) {
log("Query failed: " + error.message, null, true);
}
function saveChanges() {
return manager.saveChanges()
.then(function () { log("changes saved", null, true); })
.fail(saveFailed);
}
function saveFailed(error) {
log("Save failed: " + error.message, null, true);
}
function log(msg, data, showToast) {
logger.log(msg, data, system.getModuleId(vm), showToast);
}
return vm;
//#endregion
});
Any thoughts as to why this would occur and only for the first three items, any help would be appreciated. I like breeze as a potential for some spa's we need to write but this has caused me some concern.
Update 1
If I change the order of the LicenseType_id in the database it works, the initial order was 123123
if it is changed to 312123 or 321123 all six are correct in the response
[{"$id":"1","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"Low Voltage","LicenseType":{"$id":"2","$type":"Volt.Telecom.Licensing.Models.LicenseType, Volt.Telecom.Licensing.Models","Description":"General Contractors","IsActive":false,"Id":3},"State":{"$id":"3","$type":"Volt.Telecom.Licensing.Models.State, Volt.Telecom.Licensing.Models","Name":"FL","LongName":"Florida","IsActive":false,"Id":23},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":1},{"$id":"4","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"Contractors","LicenseType":{"$id":"5","$type":"Volt.Telecom.Licensing.Models.LicenseType, Volt.Telecom.Licensing.Models","Description":"Low Voltage","IsActive":false,"Id":1},"State":{"$ref":"3"},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":2},{"$id":"6","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"General Contractors","LicenseType":{"$id":"7","$type":"Volt.Telecom.Licensing.Models.LicenseType, Volt.Telecom.Licensing.Models","Description":"Contractors","IsActive":false,"Id":2},"State":{"$ref":"3"},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":3},{"$id":"8","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"Low Voltage","LicenseType":{"$ref":"5"},"State":{"$id":"9","$type":"Volt.Telecom.Licensing.Models.State, Volt.Telecom.Licensing.Models","Name":"CA","LongName":"California","IsActive":false,"Id":35},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":4},{"$id":"10","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"Contractors","LicenseType":{"$ref":"7"},"State":{"$ref":"9"},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":5},{"$id":"11","$type":"Volt.Telecom.Licensing.Models.License, Volt.Telecom.Licensing.Models","LicenseName":"General Contractors","LicenseType":{"$ref":"2"},"State":{"$ref":"9"},"DateIssued":"2012-11-18T00:00:00.000","ValidFor":1095,"IsActive":false,"Id":6}]
Edit: As of v 1.3.1 Breeze now DOES support inheritance.
The problem may be that Breeze does not yet support inheritance. There is a UserVoice suggestion here. Please vote on it. We take these suggestions very seriously.
To confirm that this is your issue, can you flatten the structure so that you do not need inheritance and see if the issue goes away.
I think that if something disappears between server to client its because Breeze retain null data column which can disorganize data structure and make knockout binding dysfunctional.
In opting to minimize Breeze performance you can place the attribute in the down level according to your need.
1 - BreezeWebApiConfig.cs level
2 - Controller level
3 - or HttGet level
This attribute works for me:
var jsonx = Breeze.WebApi.BreezeConfig.Instance;
jsonx.GetJsonSerializerSettings().NullValueHandling = Newtonsoft.Json.NullValueHandling.Include;