Cannot read property length of undefined error happens only in server - kendo-grid

I am using MVC and Kendo Grid. I am facing an issue where we have common functions for all our master tables and stores the result set to a cache based on dealersystemId.
There are different dealersystemId, so data will be stored in the cache for each of dealersystemId.
So whenever a call required for a master table, it always uses cache rather than going to call master tables, if there is no data in the cache for a particular master table only then it hit the database, otherwise reads from the cache.
We have a screen it shows all data from the cache, and the user will be able to delete stored cache for each dealersystemid. So here when a user clicks on 'clearcache' button for a dealersystemId, a Jquery ajax will happen and it deletes data from the cache for a dealersystemid, and remaining data in the cache will be shown in the Kendo grid.
Function which clears cache data code as mentioned below,
public List<SystemPreferenceModel> ClearAllSysPreference(string dealerSystemID,bool selfClear = true)
{
try
{
List<SystemPreferenceModel> systemPreferenceModel = null;
List<mtSystemPreference> appSystemPrefModel = null;
appSystemPrefModel = (List<mtSystemPreference>)CachingProvider.Instance.GetItem("GetAllSysPreference2");
if (appSystemPrefModel != null)
{
systemPreferenceModel = new List<SystemPreferenceModel>();
IGenericDataRepository<mtSystemPreference> appSysPrefRepository = new GenericDataRepository<mtSystemPreference>(UserModelSession);
appSystemPrefModel.RemoveAll(x => x.dealerSystemId == Convert.ToInt64(dealerSystemID));
systemPreferenceModel = GetSystemPreferenceData(appSystemPrefModel);
CachingProvider.Instance.AddItem("GetAllSysPreference2", appSystemPrefModel, string.Empty);
}
var appSettings = ConfigurationManager.AppSettings;
string server1 = appSettings["Server1"];
string server2 = appSettings["Server2"];
if (selfClear == true && !server1.Contains("localhost"))
{
string Server1IPAddress = server1.Split(':')[1].Substring(2);
if (UserModelSession.ServerIPAddress != Server1IPAddress)
{
server2 = server1;
}
NetTcpBinding tcpb;
string PropagationEndPoint = "";
PropagationEndPoint = server2 + "/CommonComponent";
tcpb = new NetTcpBinding();
tcpb.Security.Mode = SecurityMode.None;
EndpointAddress ep = null;
ep = new EndpointAddress(PropagationEndPoint);
using (ChannelFactory<ICommonComponent> factory = new ChannelFactory<ICommonComponent>(tcpb))
{
ICommonComponent proxy = factory.CreateChannel(ep);
using (OperationContextScope scope = new OperationContextScope((IContextChannel)proxy))
{
OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader("usermodel", "utp_ns", ""));
proxy.ClearAllSysPreference(dealerSystemID, false);
}
}
}
return systemPreferenceModel;
}
catch (Exception ex)
{
bool rethrow = BusinessLogicExceptionHandler.HandleExcetion(ref ex);
if (rethrow)
{
throw ex;
}
return null;
}
}
It works fine in local. View as follows
<div id="dvSysPref">
<div style="padding-bottom:0px; padding-top:5px;">
#(Html.Kendo().Grid(Model.mtSystemPreferenceViewModel)
.Name("SystemPreferenceGrid")
.Selectable()
.Columns(columns =>
{
columns.Bound(model => model.entityType).Width("50px").Title("EntityType");
columns.Bound(model => model.entityId).Width("150px").Title("EntityID");
columns.Bound(model => model.dealerSystemId).Width("150px").Title("Dealer SystemID");
columns.Bound(model => model.name).Width("150px").Title("name");
columns.Bound(model => model.valInt).Width("50px").Title("ValInt");
columns.Bound(model => model.valString).Width("150px").Title("ValString");
columns.Bound(model => model.createdDate).Width("150px").ClientTemplate("#= kendo.toString(createdDate, \"MM/dd/yy hh:mm tt\") #").Title("createdDate");
columns.Bound(model => model.lastUpdatedDate).Width("150px").ClientTemplate("#= kendo.toString(lastUpdatedDate, \"MM/dd/yy hh:mm tt\") #").Title("LastUpdatedDate");
columns.Bound(model => model.isActive).Width("150px").Title("IsActive");
columns.Bound(model => model.valBin).Width("100px").Title("ValBin");
})
.HtmlAttributes(new { style = "font-size: 14px; font-family: 'Segoe UI'; min-height: 100px; table-layout: fixed;" })
.Pageable(pg =>
pg.Refresh(true)
.PageSizes(new int[] { 10, 30, 50, 100, 200 })
.Enabled(true)
.PreviousNext(true)
.Numeric(false)
.Input(true)
.Messages(m => m.Page("Page ")
.Of(" of {0}")
)
)
.Navigatable()
.Filterable()
.Scrollable(scr => scr.Height(400))
.Sortable(sort => sort.SortMode(GridSortMode.SingleColumn))
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.NoRecords("No Records Found")
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.ServerOperation(false)
.Model(model =>
{
model.Id(p => p.mtSystemPreferenceId);
model.Field(p => p.entityType);
model.Field(p => p.entityId);
model.Field(p => p.name);
model.Field(p => p.valInt);
model.Field(p => p.valString);
model.Field(p => p.createdDate);
model.Field(p => p.createdBy);
model.Field(p => p.lastUpdatedDate);
model.Field(p => p.lastUpdatedBy);
model.Field(p => p.dealerSystemId);
model.Field(p => p.isActive);
model.Field(p => p.valBin);
}
)
.Read(read => read.Action("ReadSystemPreferenceListGrid", "ClearCache"))
)
)
</div>
<div style="padding-bottom:0px; padding-top:5px;">
#(Html.Kendo().DropDownList()
.Name("DealerSystemSysPreferenceList")
.BindTo(Model.SystemPreferenceDealerSystemViewModelList)
.DataTextField("DealerSystemID")
.DataValueField("ID")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("LoadSystemSysPreferenceListDropdown", "ClearCache");
})
.ServerFiltering(true);
})
.Events(e =>
{
e.DataBound("onSystemPreferenceDataBound");
})
.OptionLabel("Select Dealer System ID")
.HtmlAttributes(new { style = "width: 30%" })
)
<input type="button" id="btnSysPreferenceClearCache" class="btn btn-default btn-primary" title="Search" value="Clear Cache" />
<div>
<span id="dvSystemPreferenceListvalidMesg" class="k-widget k-tooltip k-tooltip-validation k-invalid-msg field-validation-error" role="alert" style="display:none;text-align:left;position:absolute;margin:0px!important;padding:1px!important;bottom: 400px;"><span class="k-icon k-warning"> </span> Please select a dealer system ID</span>
</div>
</div>
JQuery ajax code,
function onSystemPreferenceDataBound(e) {
$("#btnSysPreferenceClearCache").click(function () {
var dealerSystemID = $("#DealerSystemSysPreferenceList").data("kendoDropDownList").text();
if (dealerSystemID != "Select Dealer System ID") {
$.ajax({
type: "GET",
url: '/ClearCache/ClearSystemPreferenceListCache',
data: { dealerSystemID: dealerSystemID },
pageSize: 20,
cache: false,
pageable: true,
success: function (src) {
alert('Systempreference Cache has been cleared for dealerSystemId '+dealerSystemID);
var dealerDropdown = [];
var dropdownList = [];
if (src.Data.length > 0) {
for (var i = 0; i < src.Data.length; i++) {
dropdownList.push({ text: src.Data[i].dealerSystemId, value: i });
}
//Removes duplicates from dropdown
dealerDropdown = dropdownList.reduce(function (item, e1) {
var matches = item.filter(function (e2)
{ return e1.text == e2.text });
if (matches.length == 0) {
item.push(e1);
}
return item;
}, []);
dealerDropdown.unshift({ text: "Select Dealer System ID", value: "0" });
}
else {
dealerDropdown = [
{ text: "Select Dealer System ID", value: "0" },
];
}
var dataSource = new kendo.data.DataSource({
data: src,
pageSize: 20,
schema: {
type: "json",
data: "Data",
total: "Total",
model: {
fields: {
mtSystemPreferenceId: { type: "number" },
entityType: { type: "number" },
name: { type: "string" },
dealerSystemId: { type: "number" },
valInt: { type: "number" },
valString: { type: "string" },
createdDate: { type: "date" },
createdBy: { type: "number" },
lastUpdatedDate: { type: "date" },
lastUpdatedBy: { type: "number" },
isActive: { type: "bool" },
}
}
}
});
$('#SystemPreferenceGrid').data('kendoGrid').setDataSource(dataSource);
$("#DealerSystemSysPreferenceList").kendoDropDownList({
dataTextField: "text",
dataValueField: "value",
dataSource: dealerDropdown
});
}
});
}
else {
alert('Please select a DealerSystemID');
}
});
}
my Controller code as follows,
public ActionResult ClearUsersListCache(string dealerSystemID)
{
SupportViewModel supportVM = new SupportViewModel();
UsersViewModel usersListModel = new UsersViewModel();
supportVM.userViewModelList = new List<UsersViewModel>();
List<UserModel> UserListInfoModel = new List<UserModel>();
List<DealerSystemViewModel> dealerSystemViewmodel = new List<DealerSystemViewModel>();
supportVM.UsersDealerSystemViewModelList = new List<DealerSystemViewModel>();
DTNAUserModel dtnaUserModel = (DTNAUserModel)System.Web.HttpContext.Current.Session["DTNAConnectUser"];
DTNAUserModel systemUserLoginModel = new DTNAUserModel();
try
{
using (BusinessLayerServiceFactory<ICommonComponent> commonComponentServiceFactory = new BusinessLayerServiceFactory<ICommonComponent>())
{
ICommonComponent commonComponent = commonComponentServiceFactory.Instantiate();
using (OperationContextScope ocs = new OperationContextScope((IContextChannel)commonComponent))
{
OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader(commonComponentServiceFactory.UserModelName, commonComponentServiceFactory.UserModelNameSpace, commonComponentServiceFactory.SerializedUserModel));
UserListInfoModel = commonComponent.ClearAllUsers(dealerSystemID);
}
}
if (UserListInfoModel != null)
{
foreach (var user in UserListInfoModel)
{
UsersViewModel userViewModel = new UsersViewModel();
{
{
userViewModel.Gid = user.Gid;
userViewModel.mtUserId = user.mtUserId;
userViewModel.BranchId = user.BranchId;
userViewModel.DeptId = user.DeptId;
userViewModel.UserId = user.UserId;
userViewModel.DmsUserId = user.DmsUserId;
userViewModel.DealerSystemId = user.DealerSystemId;
userViewModel.Description = user.Description;
userViewModel.Email = user.Email;
userViewModel.Role = user.Role;
userViewModel.isActive = user.isActive;
userViewModel.Password = user.Password;
userViewModel.RecActive = user.RecActive;
userViewModel.Facility = user.Facility;
}
supportVM.userViewModelList.Add(userViewModel);
}
}
for (int i = 0; i < UserListInfoModel.Count; i++)
{
supportVM.UsersDealerSystemViewModelList.Add(new DealerSystemViewModel { DealerSystemID = UserListInfoModel[i].DealerSystemId.ToString(), ID = Convert.ToInt64(i + 1) });
}
//This removes duplicates
supportVM.UsersDealerSystemViewModelList = supportVM.UsersDealerSystemViewModelList.GroupBy(i => i.DealerSystemID).Select(g => g.First()).ToList();
}
var result = new DataSourceResult()
{
Data = supportVM.userViewModelList.OrderByDescending(x => x.mtUserId), // Process data (paging and sorting applied)
Total = supportVM.userViewModelList.Count // Total number of records
};
var jsonResult = Json(result, JsonRequestBehavior.AllowGet);
jsonResult.MaxJsonLength = int.MaxValue;
return jsonResult;
}
catch (Exception ex)
{
bool rethrow = UserInterfaceExceptionHandler.HandleException(ref ex);
if (rethrow)
{
throw ex;
}
return null;
}
}
However, when it got deployed we are able to see one javascript error 'Can not read property length of undefined'. This error happens only in the server not in local. When I debugged I could see that in Jquery success function controller returns view instead data which causes this error. Hence in the data return in success function is undefined, hence in 'src.Data.length' length property comes as undefined.
SystemPreferenceGrid
Please note I have attached a screenshot for the same error happens for one more grid we have.
But we could not reproduce this issue in local. So could anyone help me in fixing this issue?

Related

Why json file is created automatically after every event in database in my project

This is part of the generated json file: "EventType":"PlantimsDbContext","Environment":{"UserName":"m-shirzadeh","MachineName":"DESKTOP-RVSF8C4","DomainName":"IOECC"
my project sturtup:
services.Configure(options =>
{
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddIdentity<AppUser, AppRole>()
.AddEntityFrameworkStores<PlantimsDbContext>()
.AddDefaultTokenProviders();
services
.AddMvc()
//.AddSessionStateTempDataProvider()
.AddNewtonsoftJson(op => op.SerializerSettings.ContractResolver = new DefaultContractResolver());
services.AddCors();
services.AddKendo();
services.AddDbContext<PlantimsDbContext>(options =>
options.UseSqlServer(
Environment.GetEnvironmentVariable("PlantimsCnn2")));
services.AddRouteAnalyzer();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromDays(3);
});
services.AddAuthentication(options =>
{
}).AddCookie(options =>
{
options.LoginPath = "/login";
options.LogoutPath = "/logout";
});
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue;
});
services.AddSignalR();
services.AddLogging(c => c.ClearProviders());
services.AddLogging(
builder =>
{
builder.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("NToastNotify", LogLevel.Warning)
.AddConsole();
});

No data of first load

I'm new to NgRx, and trying to retrieve and cache paginated table data using Effects and http request.
But on any first time page load (if page isn't cached already) I got empty page, even though if I do console.log of state object, I see data inside?
When I go on previous page, data is there, so I'm guessing something in async world I'm doing wrong, but can't figure out what :/
here is my initialization in
component.ts
ngAfterViewInit() {
this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
this.store.dispatch(new ListLoad(this.getQueryParams()));
return this.store.pipe(select('list'));
}),
map((state: State) => {
this.isLoadingResults = false;
this.resultsLength = state.totalRecords;
return this.cacheKey in state.data ? state.data[this.cacheKey] : [];
}),
catchError((err) => {
this.isLoadingResults = false;
this.resultsLength = 0;
return observableOf([]);
})
)
.subscribe((data: any[]) => {
return this.data = data
});
}
and here is my effect definition
effects.ts
#Effect()
loadData = this.actions$.pipe(
ofType(actions.actionTypes.ListLoad),
mergeMap((action: actions.actionTypes.ListLoadSuccess) => this.service.getAll(action.payload).pipe(
map(
response => {
let apiResponse = new ApiResponse(response);
let cacheKey = JSON.stringify(action.payload);
return apiResponse.isSuccess ?
new actions.ListLoadSuccess({ key: cacheKey, data: apiResponse.data }) :
new actions.ListLoadFailed(`code: ${apiResponse.status.error_code}; message: ${apiResponse.status.error_message}`);
}
),
catchError(err => observableOf(new actions.ListLoadFailed(err)))
))
)
In addition to this, I would like to cancel http request, if page containing the data is present in NgRx store
I was able to resolve it. Issue was that I was updating property of store which is object, by adding new property to it. Store does not emit event that fragment is updated, so Select subscription is not triggered. I've introduced another boolean param for loading state, which I listen for changes, and if loading is false (page is loaded), I select desired fragment.
I've also added extra code for page caching
component.ts
ngOnInit() {
this.isLoadingResults$ = this.store.pipe(
select(state => state.stateFragment.isListLoading),
takeWhile(() => this.componentActive) //unsubscribe
);
this.store.dispatch(new ListLoad());
this.isLoadingResults$.pipe(
filter((isLoading:boolean) => !isLoading),
switchMap(() => this.store.pipe(
select(state => state.stateFragment),
takeWhile(() => this.componentActive) //unsubscribe
)),
map(...)
).subscribe(...);
//Other stuff here
}
effects.ts
#Effect()
load$ = this.actions$.pipe(
ofType(actions.actionTypes.ListLoad),
withLatestFrom(this.store.pipe(select(state.stateFragment))),
filter(([action, store]) => {
let isPageCached: boolean = action.payload in store.stateFragment;
if (isPageCached) {
this.store.dispatch(new actions.ListLoaded()); //for sake of changing loading state
}
return !isPageCached;
}),
switchMap(([action, store]) => {
return this.service.getAll(action.payload).pipe(
map(
response => {
let apiResponse = new ApiResponse(response);
return apiResponse.isSuccess ?
new actions.ListLoadSuccess({ key: action.payload, data: apiResponse.getData(), totalRecords: apiResponse.getTotalCount() }) :
new actions.ListLoadFailed(`code: ${apiResponse.status.error_code}; message: ${apiResponse.status.error_message}`);
}
),
catchError(err => observableOf(new actions.ListLoadFailed(err)))
);
}
), share()
)
reducer.ts
export function reducer(state = initialState, action: Actions) {
switch (action.type) {
case actionTypes.ListLoad:
return {
...state,
isListLoading: true
};
case actionTypes.ListLoaded:
return {
...state,
isListLoading: false
};
case actionTypes.ListLoadSuccess:
state.listData[action.payload.key] = action.payload.data;
return {
...state,
isListLoading: false,
listData: state.listData,
listTotal: action.payload.totalRecords
};
case actionTypes.ListLoadFailed:
return {
...state,
isListLoading: false,
error: action.payload
};
case actionTypes.ListClear:
return {
...state,
listData: {},
listTotal: 0
};;
default:
return state;
}
}

What's the best way to mock a nested function?

consider a function
exports.projectNotifyLaunch = (admin, functions) => {
return functions.database.ref("/projects/{pid}").onCreate(snap => {
const { title } = snap.val();
const notification = {
title: `${title} just launched!`,
body: `We just heard about a new cryptocurrency project called ${title}`
};
return admin.messaging().sendToTopic("premium", { notification });
});
};
How should I mock deeply nested functions such as
functions.database.ref("/projects/{pid}").onCreate(snap => {});
or
admin.messaging().sendToTopic("premium", { notification });
in Jest? I want to fire off the snap=>{} callback and assert against the value of notification.
I was able to make this work
This works but it's quite verbose. I'm wondering if there is a better way, or a type of testing I'm not aware of with Jest.
describe("send notification to premium users on new project", () => {
// INPUTS
const snap = {
val: () => ({
title: "Test Title"
})
};
const functions = {
database: {
ref: () => ({
onCreate: callback => callback(snap)
})
}
};
// outputs
let topicStub = null;
let notificationStub = null;
const admin = {
messaging: () => ({
sendToTopic: (topic, notification) => {
topicStub = topic;
notificationStub = notification;
}
})
};
projectNotifyLaunch(admin, functions);
test("title is correct", () => {
expect(notificationStub.notification.title).toBe(
"Test Title just launched!"
);
});
test("topic is premium", () => {
expect(topicStub).toBe("premium");
});
});

Why my this.state is null?

I'm new with React and i'm trying to render a json from a websocket.
Right now i'm able to get the json from the websocket using this :
componentWillMount() {
this.ws = new WebSocket('ws://10.77.0.79:1234')
this.ws.onmessage = e => this.setState({data: Object.values((e.data))})
this.ws.onerror = e => this.setState({ error: 'WebSocket error' })
this.ws.onclose = e => !e.wasClean && this.setState({ error: `WebSocket error: ${e.code} ${e.reason}` })
}
And then i need to map this json, right now i'm using this:
render() {
// this is my json from websocket
var json2 = {"Auth":{"status":"true","user":"gesplan","pass":"root"}}
var arr = [];
Object.keys(json2).forEach(function(key) {
arr.push(json2[key]);
});
return <ul>{arr.map(item => <MyAppChild key={item.status} label={item.status} value={item.user} pass={item.pass} />)} {this.state.data} </ul>;
}
}
class MyAppChild extends React.Component {
render() {
return <li>{this.props.label + " - " + this.props.value + this.props.pass } </li>;
}
}
With this i can render the values of the var json2.
How can i do it with my this.state.data? when i change json2 for this.state.data it return a null, but how can the state be null if i am rendering it normally?
Set your initial state to an empty array first. Append data when new data comes in:
constructor() {
this.state = {
data: []
}
}
componentWillMount() {
this.ws = new WebSocket('ws://10.77.0.79:1234')
this.ws.onmessage = e => this.setState({
data: [].concat(this.state.data, JSON.parse(e.data).Auth)
})
this.ws.onerror = e => this.setState({ error: 'WebSocket error' })
this.ws.onclose = e => !e.wasClean && this.setState({ error: `WebSocket error: ${e.code} ${e.reason}` })
}
render() {
return (
<ul>
{this.state.data.map(item =>
<MyAppChild key={item.status} label={item.status} value={item.user} pass={item.pass} />)
}
</ul>
);
}

kendo grid not binding data correctly

I have a mvc application with a kendo Grid
Here's the view code
#using Domain.Agromilieu2.Wui.Resources.Bedrijfsgegevens.Views
#using Domain.Agromilieu2.Wui.Models.BeheerTeksten
#model TekstenViewModel.Main
#{
Layout = WebCore.Views.Layouts.Extended;
}
<h2>Teksten</h2>
#(Html.Kendo().Window()
.Name("alertWindow")
.Title("Status Message from Server")
.Draggable()
.Resizable()
.Width(400)
.Height(200)
.Modal(true)
.Visible(false)
.Actions(actions => actions.Close())
)
#Html.WebCore().Popup.CustomButtons("popupDemo", "Waarde", Html.Kendo().Editor().Name("waardeEditor").HtmlAttributes(new { #class = "editorStyle" }).Tools(tools => tools
.Clear()
.Bold().Italic().Underline().Strikethrough()
.JustifyLeft().JustifyCenter().JustifyRight().JustifyFull()
.InsertUnorderedList().InsertOrderedList()
.Outdent().Indent()
.CreateLink().Unlink()
.InsertImage()
.SubScript()
.SuperScript()
.TableEditing()
.ViewHtml()
.Formatting()
.FontName()
.FontSize()
.FontColor().BackColor()
).ToHtmlString(), new[]{new PopupButton("popupDemoAnnuleren", "Cancel", false),new PopupButton("popupDemoOk", "OK")})
<div class="infoPanel">
<div id='divSousMenu'>
<div>
<h2 class="zoekCriteria">ZOEKCRITERIA</h2>
<h4 class="resourceSet">Resource Set:</h4>
#(Html.Kendo().ComboBoxFor(model => model.Filter.userName)
.Name("resourcesSetComboBox")
.DataTextField("Naam")
.DataValueField("ID")
.Filter(FilterType.Contains)
.HtmlAttributes(new { #class = "comboStyle" })
.DataSource(source =>
{
source.Read(read =>
{
read.Action(MVC.BeheerTeksten.ActionNames.ResourceSetsIntoCombo_Read, MVC.BeheerTeksten.Name)
.Data("onAdditionalData");
})
.ServerFiltering(true);
})
.AutoBind(false)
)
</div>
<div class='gewijzigdItem'>
<h4 class="gewijzigdDoor">Gewijzigd door:</h4>
#(Html.Kendo().ComboBox()
.Name("usersSetComboBox")
.DataTextField("DisplayName")
.DataValueField("UserName")
.Filter(FilterType.Contains)
.HtmlAttributes(new { #class = "comboStyle" })
.DataSource(source =>
{
source.Read(read =>
{
read.Action(MVC.BeheerTeksten.ActionNames.GebruikersIntoCombo_Read, MVC.BeheerTeksten.Name)
.Data("onAdditionalData");
})
.ServerFiltering(true);
})
.AutoBind(false)
)
</div>
<div class='vanItem'>
<h4 class="van">Van:</h4>
#(Html.Kendo().DateTimePicker()
.Name("vanTimepicker")
.Max(DateTime.Today)
.Events(events => events.Change("onVanTimeChange"))
.HtmlAttributes(new { #class = "dateTimePickerStyle;" })
)
</div>
<div class='totItem'>
<h4 class="tot">Tot:</h4>
#(Html.Kendo().DateTimePicker()
.Name("totTimepicker")
.Max(DateTime.Today)
.Events(events => events.Change("onTotTimeChange"))
.HtmlAttributes(new { #class = "dateTimePickerStyle;" })
)
</div>
</div>
</div>
<div class="separator"></div>
#*<hr />*#
<div class="zoekResultatLine">
<h2 class="zoekResultat">ZOEKRESULTAAT</h2>
</div>
#(Html.Kendo().Grid<TekstenViewModel.Tekst>()
.Name("Grid")
.Columns(columns =>
{
columns.Template(#<text></text>).ClientTemplate("<input type='checkbox'/>").Width(10).Hidden(!Model.Administrator);
columns.Bound(product => product.RESOURCE_SET_NAAM).Width(125).ClientTemplate("#= RESOURCE_SET_NAAM#");
columns.Bound(product => product.Naam).Width(125).ClientTemplate("#= Naam#");
columns.Bound(product => product.Waarde).Width(125).ClientTemplate("<div id='editorDiv'><div class='input'>#=Waarde#</div><div class='editor'>" +
Html.WebCore().LinkButton(type: ButtonType.MeerActies, htmlAttributes: new { onclick = "openPopupDemo('#: Waarde #', '#: ID #', 'Waarde')" }));
columns.Bound(product => product.Opmerking).Width(250).ClientTemplate("<div id='editorDiv'><div class='input'>#=Opmerking#</div><div class='editor'>" +
Html.WebCore().LinkButton(type: ButtonType.MeerActies, htmlAttributes: new { onclick = "openPopupDemo('#: Opmerking #', '#: ID #', 'Opmerking')" }));
columns.Template(#<text></text>).ClientTemplate("<div id='deleteDiv'><div class='delete'><a class=\"delete iconBtn\" onclick=\"deleteResourceItem(#: ID #, '#: Naam #')\"></a></div></div>").Width(10).Hidden(!Model.Administrator);
})
.Pageable()
.Sortable()
.Filterable()
.Events(events => events.Edit("onCellEdit").DataBinding("onDataBinding"))
.Groupable()
.Navigatable()
.Editable(editable => editable.Mode(GridEditMode.InCell).DisplayDeleteConfirmation(false))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.Events(e => e.Error("error_handler"))
.Model(model =>
{
model.Id(product => product.ID);
model.Field(product => product.Naam).Editable(Model.Administrator);
model.Field(product => product.Opmerking).Editable(Model.Administrator);
model.Field(product => product.Waarde).Editable(!Model.ReadOnly);
model.Field(product => product.RESOURCE_SET_ID).DefaultValue(Model.SetID);
model.Field(product => product.Type).DefaultValue(Domain.Agromilieu2.Common.Objects.Entities.Resources.ResourceType.GLOBAL_RESOURCES);
model.Field(product => product.Taal).DefaultValue(Domain.Agromilieu2.Common.Agromilieu2Constants.Resources.DEFAULT_TAAL_CODE);
})
.Create(create => create.Action(MVC.BeheerTeksten.ActionNames.ResourceItems_Create, MVC.BeheerTeksten.Name))
.Read(read => read.Action(MVC.BeheerTeksten.ActionNames.ResourceItems_Read, MVC.BeheerTeksten.Name, new { setID = Model.SetID }).Data("onReadAdditionalData"))
.Update(update => update.Action(MVC.BeheerTeksten.ActionNames.ResourceItems_Update, MVC.BeheerTeksten.Name))
.Destroy(destroy => destroy.Action(MVC.BeheerTeksten.ActionNames.ResourceItems_Delete, MVC.BeheerTeksten.Name))
)
)
#Html.WebCore().Popup.Remove("confirmResourceItemPopup", "Verwijderen resource item", "")
#section Scripts
{
#Scripts.Render(Links.Bundles.Scripts.BeheerTeksten.Teksten)
<script type="text/javascript">
function onCellEdit(e) {
var grid = $("#Grid").data("kendoGrid");
var row = $(e.container).closest("tr");
var colIdx = $("td", row).index($(e.container));
var columname = e.sender.columns[colIdx].field;
e.container.find("[name='" + columname + "']").toggleClass('editInput');
}
function onDataBinding(e) {
var grid = $("#Grid").data("kendoGrid");
if ($("#resourcesSetComboBox").data("kendoComboBox").value() == "")
grid.showColumn(1);
else
grid.hideColumn(1);
}
function onVanTimeChange() {
var vanTimeValue = kendo.toString($("#vanTimepicker").data("kendoDateTimePicker").value(), "dd/MM/yyyy HH:mm:ss.ffff")
$("#totTimepicker").data("kendoDateTimePicker").min(vanTimeValue);
}
function onTotTimeChange() {
var totTimeValue = kendo.toString($("#totTimepicker").data("kendoDateTimePicker").value(), "dd/MM/yyyy HH:mm:ss.ffff")
$("#vanTimepicker").data("kendoDateTimePicker").max(totTimeValue);
}
function onAdditionalData() {
var code = window.location.pathname.split('/');
return {
toepassingsCode: code[5]
};
}
function onReadAdditionalData() {
var resourceID = $.urlParam('setID');
if (resourceID) {
$("#resourcesSetComboBox").data("kendoComboBox").value(resourceID);
$("#resourcesSetComboBox").data("kendoComboBox").enable(false);
}
else
resourceID = $("#resourcesSetComboBox").data("kendoComboBox").value();
var user = $.urlParam('userName');
if (user) {
$("#usersSetComboBox").data("kendoComboBox").value(user);
$("#usersSetComboBox").data("kendoComboBox").enable(false);
}
else
user = $("#usersSetComboBox").data("kendoComboBox").value();
var vanTimeValue = $.urlParam('vanTime');
if (vanTimeValue) {
$("#vanTimepicker").data("kendoDateTimePicker").value(new Date(Date.parse(vanTimeValue, "dd/MM/yyyy HH:mm:ss")));
$("#vanTimepicker").data("kendoDateTimePicker").enable(false);
}
else
var vanTimeValue = kendo.toString($("#vanTimepicker").data("kendoDateTimePicker").value(), "dd/MM/yyyy HH:mm:ss.ffff")
var totTimeValue = $.urlParam('totTime');
if (totTimeValue) {
$("#totTimepicker").data("kendoDateTimePicker").value(totTimeValue);
$("#totTimepicker").data("kendoDateTimePicker").enable(false);
}
else
var totTimeValue = kendo.toString($("#totTimepicker").data("kendoDateTimePicker").value(), "dd/MM/yyyy HH:mm:ss.ffff")
return {
setID: resourceID,
userName: user,
vanTime: vanTimeValue,
totTime: totTimeValue
};
}
$.urlParam = function (name) {
var enc = decodeURI(window.location.href);
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(enc);
if (results != null)
return results[1];
}
function deleteResourceItem(resourceItemID, resourceItemName) {
domain.Agromilieu2.Wui.BeheerTeksten.Teksten.deleteResourceItem(resourceItemID, resourceItemName);
}
var selectedGridRowID = 0;
var selectedGridColumnName;
function openPopupDemo(gridCellContent, gridIdentifier, columnIdentifier) {
var editor = $("#waardeEditor").data("kendoEditor")
if (('#Html.Raw(Json.Encode(Model.ReadOnly))' == "false" && '#Html.Raw(Json.Encode(Model.Administrator))' == "false" && columnIdentifier != "Waarde") || '#Html.Raw(Json.Encode(Model.ReadOnly))' == "true")
editor.body.contentEditable = false;
else
editor.body.contentEditable = true;
editor.value(htmlDecode(gridCellContent));
domain.WebCore.popup.show("popupDemo");
selectedGridRowID = gridIdentifier;
selectedGridColumnName = columnIdentifier;
};
function htmlDecode(value) {
return $('<div/>').html(value).text();
}
function htmlEncode(value) {
return $('<div/>').text(value).html();
}
function htmlEscape(str) {
return String(str)
.replace(/"/g, '"')
.replace(/'/g, ''')
}
domain.WebCore.popup.configure("popupDemo")
.click(function (b) {
var grid = $("#Grid").data("kendoGrid");
var editor = $("#waardeEditor").data("kendoEditor")
var parentItem = grid.dataSource.get(selectedGridRowID);
parentItem.set(selectedGridColumnName, htmlEscape(htmlEncode(editor.value())));
});
function showAlertWindow(message) {
var alertWindow = $('#alertWindow').data('kendoWindow');
alertWindow.content(message);
alertWindow.refresh();
alertWindow.center();
alertWindow.open();
}
function error_handler(e) {
if (e.errors) {
var message = "";
$.each(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
showAlertWindow(message);
}
}
$(function () {
domain.Agromilieu2.Wui.BeheerTeksten.Teksten.init(
{
deleteResourceItemUrl: "#Url.Action(MVC.BeheerTeksten.ResourceItems_Delete())",
deleteResourceItemMessage: "<p>Bent u zeker dat u '{0}' wil verwijderen?</p><p><strong>Opgelet!</strong><br>Hierbij worden ook alle teksten verbonden aan deze resource set verwijderd.</p>",
ResourceItems_ReadUrl: "#Url.Action(MVC.BeheerTeksten.ResourceItems_Read())"
});
});
</script>
}
And here's my controller's code.
// GET /Agromilieu2/Beheer/Teksten/Teksten
[HttpGet]
[Domain.BasisArchitectuur.Framework.MVC.ActionFilters.MenuItem("Teksten")]
[IsAgromilieuActieAllowed(ActieClaims.TekstenRaadpleger)]
public virtual ActionResult Teksten(string toepassingsCode = null, long? setID = null, string taalCode = null, string resourceType = null, string user = null)
{
bool admin = SecurityHelper.IsActieAllowed(ActieClaims.TekstenAdmin);
LayoutService.SubTitle = DetailResources.TITEL_Header;
if (admin)
{
LayoutService.SubmitActions = new List<LinkButton>
{
new LinkButton { ButtonType = ButtonType.Toevoegen, CssClass = "myToevoegenButton", IsDisabled = setID == null, ClientId = "teste" },
new LinkButton { ButtonType = ButtonType.Delete, CssClass = "myVerwijderenButton" },
new LinkButton { ButtonType = ButtonType.Zoeken, CssClass = "primair myZoekenButton" }
};
}
else
{
LayoutService.SubmitActions = new List<LinkButton>
{
new LinkButton { ButtonType = ButtonType.Zoeken, CssClass = "primair myZoekenButton" }
};
}
if (string.IsNullOrEmpty(toepassingsCode))
{
return RedirectToAction(MVC.BeheerTeksten.Toepassingen());
}
else
{
if (!string.IsNullOrEmpty(resourceType) && resourceType == ResourceType.REFE_RESOURCES)
{
return RedirectToAction(MVC.BeheerTeksten.RefeTeksten(toepassingsCode, setID, taalCode));
}
else
{
if (string.IsNullOrEmpty(taalCode))
{
taalCode = Agromilieu2Constants.Resources.DEFAULT_TAAL_CODE;
}
LayoutService.SubTitle = string.Format("Beheer Teksten - {0}",
BL.Resources.Resources.GetToepassingen().First(x => x.Code == toepassingsCode).Omschrijving);
TekstenViewModel.Main model = new TekstenViewModel.Main
{
DefaultTaal = Agromilieu2Constants.Resources.DEFAULT_TAAL_CODE,
Filter = new TekstenViewModel.ZoekCriteria
{
ResourceSet_ID = setID,
Taal = taalCode,
userName = user
},
ToepassingsCode = toepassingsCode,
SetID = setID,
ReadOnly = !(SecurityHelper.IsActieAllowed(ActieClaims.TekstenAdmin) || SecurityHelper.IsActieAllowed(ActieClaims.TekstenBeheer)),
Administrator = SecurityHelper.IsActieAllowed(ActieClaims.TekstenAdmin)
};
return View(model);
}
}
}
[HttpPost]
[Domain.BasisArchitectuur.Framework.MVC.ActionFilters.MenuItem("Teksten")]
[IsAgromilieuActieAllowed(ActieClaims.TekstenRaadpleger)]
public virtual ActionResult ResourceItems_Read([DataSourceRequest]DataSourceRequest request, long? setID, string userName, string vanTime, string totTime, string taalCode = Agromilieu2Constants.Resources.DEFAULT_TAAL_CODE)
{
DateTime? newVanTime = null;
DateTime? newTotTime = null;
if(!String.IsNullOrEmpty(vanTime))
newVanTime = DateTime.Parse(vanTime);
if (!String.IsNullOrEmpty(totTime))
newTotTime = DateTime.Parse(totTime);
TekstenViewModel.ZoekCriteria searchCriteria = new TekstenViewModel.ZoekCriteria
{
ResourceSet_ID = setID,
type_Code = ResourceType.GLOBAL_RESOURCES,
Taal = taalCode,
userName = userName,
vanTime = newVanTime,
totTime = newTotTime
};
List<TekstenViewModel.Tekst> resourceItemsList = new List<Models.BeheerTeksten.TekstenViewModel.Tekst>();
resourceItemsList = GetResourceItemsList(searchCriteria);
return Json(resourceItemsList.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
[AcceptVerbs(HttpVerbs.Post)]
[Domain.BasisArchitectuur.Framework.MVC.ActionFilters.MenuItem("Teksten")]
[IsAgromilieuActieAllowed(ActieClaims.TekstenBeheren)]
public virtual ActionResult ResourceItems_Create([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<TekstenViewModel.Tekst> resourceItems)
{
List<ResourceItemDto> entities = new List<ResourceItemDto>();
if (ModelState.IsValid)
{
try
{
using (IProxy<IResourceService> proxy = _proxyFactory.Create<IResourceService>())
{
foreach (TekstenViewModel.Tekst tekstenViewModel in resourceItems)
{
ResourceItemDto resourceItem = new ResourceItemDto
{
ResourceItem_ID = tekstenViewModel.ID,
ResourceSet_ID = tekstenViewModel.RESOURCE_SET_ID,
Naam = HttpUtility.HtmlDecode(tekstenViewModel.Naam),
Opmerking = HttpUtility.HtmlDecode(tekstenViewModel.Opmerking),
Waarde = HttpUtility.HtmlDecode(tekstenViewModel.Waarde),
Type_Code = tekstenViewModel.Type,
Taal_Code = tekstenViewModel.Taal,
ResourceWaarde_ID = tekstenViewModel.WAARDE_ID
};
entities.Add(resourceItem);
}
proxy.Client.CheckIfNameExists(entities);
proxy.Client.AddOrUpdateResourceItem(entities.AsEnumerable());
}
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
}
else
{
var errMsg = ModelState.Values
.Where(x => x.Errors.Count >= 1)
.Aggregate("Model State Errors: ", (current, err) => current + err.Errors.Select(x => x.ErrorMessage));
ModelState.AddModelError(string.Empty, errMsg);
}
//ModelState.AddModelError("Naam", );
//resourceItems = GetResourceItemsList(new TekstenViewModel.ZoekCriteria { Taal = resourceItems.FirstOrDefault().Taal, ResourceSet_ID = resourceItems.FirstOrDefault().RESOURCE_SET_ID });
return Json(entities.ToDataSourceResult(request, ModelState));
}
[AcceptVerbs(HttpVerbs.Post)]
[Domain.BasisArchitectuur.Framework.MVC.ActionFilters.MenuItem("Teksten")]
[IsAgromilieuActieAllowed(ActieClaims.TekstenBeheren)]
public virtual ActionResult ResourceItems_Update([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<TekstenViewModel.Tekst> resourceItems)
{
List<ResourceItemDto> entities = new List<ResourceItemDto>();
if (ModelState.IsValid)
{
try
{
using (IProxy<IResourceService> proxy = _proxyFactory.Create<IResourceService>())
{
foreach (TekstenViewModel.Tekst tekstenViewModel in resourceItems)
{
ResourceItemDto resourceItem = new ResourceItemDto
{
ResourceItem_ID = tekstenViewModel.ID,
ResourceSet_ID = tekstenViewModel.RESOURCE_SET_ID,
Naam = HttpUtility.HtmlDecode(tekstenViewModel.Naam),
Opmerking = HttpUtility.HtmlDecode(tekstenViewModel.Opmerking),
Waarde = HttpUtility.HtmlDecode(tekstenViewModel.Waarde),
Type_Code = tekstenViewModel.Type,
Taal_Code = tekstenViewModel.Taal,
ResourceWaarde_ID = tekstenViewModel.WAARDE_ID
};
entities.Add(resourceItem);
}
proxy.Client.AddOrUpdateResourceItem(entities.AsEnumerable());
}
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
}
else
{
var errMsg = ModelState.Values
.Where(x => x.Errors.Count >= 1)
.Aggregate("Model State Errors: ", (current, err) => current + err.Errors.Select(x => x.ErrorMessage));
ModelState.AddModelError(string.Empty, errMsg);
}
return Json(resourceItems.ToDataSourceResult(request, ModelState));
}
[HttpDelete]
[IsAgromilieuActieAllowed(ActieClaims.TekstenBeheren)]
public virtual ActionResult ResourceItems_Delete(long? id)
{
using (IProxy<IResourceService> proxy = _proxyFactory.Create<IResourceService>())
{
proxy.Client.DeleteResourceItemRecursively(id);
}
return Content(CoreService.LastMainScreenUrl ?? MvcConfig.DefaultStartupUrl);
}
[HttpPost]
[IsAgromilieuActieAllowed(ActieClaims.TekstenBeheren)]
public virtual ActionResult ResourceItems_Delete( [Bind(Prefix="models")] List<TekstenViewModel.Tekst> resourceItems)
{
using (IProxy<IResourceService> proxy = _proxyFactory.Create<IResourceService>())
{
foreach(TekstenViewModel.Tekst resourceItem in resourceItems )
{
proxy.Client.DeleteResourceItemRecursively(resourceItem.ID);
}
}
return Content(CoreService.LastMainScreenUrl ?? MvcConfig.DefaultStartupUrl);
}
[HttpGet]
[IsAgromilieuActieAllowed(ActieClaims.TekstenRaadpleger)]
public virtual JsonResult ResourceSetsIntoCombo_Read(string toepassingsCode)
{
ResourceWcfDataServiceProxy proxy = DependencyResolver.Current.GetService<ResourceWcfDataServiceProxy>();
IEnumerable<ResourceSetsViewModel.ResourceSet> sets =
Enumerable.Repeat(new ResourceSetsViewModel.ResourceSet { Naam = "Maak een selectie" }, 1).Union(proxy.ResourceSetSet
.Where(s => s.ToepassingsCode == toepassingsCode)
.Select(s => new
{
ID = s.ID,
Naam = s.Naam,
Opmerking = s.Opmerking,
Type = s.Type.Code
}).ToList()
.Select(s => new ResourceSetsViewModel.ResourceSet
{
ID = s.ID,
Naam = s.Naam,
Opmerking = s.Opmerking,
Type = s.Type
}));
return Json(sets.ToList(), JsonRequestBehavior.AllowGet);
}
[HttpGet]
[IsAgromilieuActieAllowed(ActieClaims.TekstenRaadpleger)]
public virtual JsonResult GebruikersIntoCombo_Read(string toepassingsCode)
{
IEnumerable<TekstenViewModel.UserInfo> journalingUsers;
using (IProxy<IResourceService> proxy = _proxyFactory.Create<IResourceService>())
{
journalingUsers = Enumerable.Repeat(new TekstenViewModel.UserInfo { UserName = null, DisplayName = "Maak een selectie" }, 1)
.Union(proxy.Client.GetUsers(toepassingsCode).Select(x => new TekstenViewModel.UserInfo { UserName = x, DisplayName = x }));
}
return Json(journalingUsers.ToList(), JsonRequestBehavior.AllowGet);
}
When I update, read or delete, everything works fine. When I create, it's like I'm not getting back the right data in the grid.
I mean, I create a new record and press Save, it calls the savechanges event of the grid. So far so good, but if I press Save again, it calls the savechanges event again and I get this error.
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
Here's a picture of the grid before creating a new record.
Here's a picture of the grid after inserting a new record
The first record should be the last. Have no idea why this is happening.