このトピックでダニエルが抱えていたのと同じ問題がありますが、彼の解決策はうまくいきません。
だからユースケース。ユーザーは 2 つの新しいレコードを次々に追加します。
- グリッドの「新規レコード追加」ボタンを押す
- フィールドに入力します (name="Alex"、amount=10、comment="first")。
- レコード 1 の準備ができました。「保存」を押します。(データはコントローラに送信され、データベースに送信されます)
ユーザーはグリッドに 1 つのレコードを表示します
もう一度「新しいレコードを追加」ボタンを押します
- フィールドに入力します (name="Bob"、amount=20、comment = "second")。
レコード 1 の準備ができました。「保存」を押します。データはコントローラに送信され、データベースよりも送信されます。この瞬間に何かが起こり、グリッドは Ajax リクエストをレコード 1 のデータとともにコントローラーに再度送信します。
ユーザーがグリッドを更新し、3 つのレコードを表示する
「アレックス | 10 | 最初」 (重複レコード) ID = 1
「ボブ | 20 | 秒」 ID = 2
「アレックス | 10 | 最初」 ID = 1
彼らは、新しいレコードでデータ ソースを正しくバインド/更新するために ID を返すことを推奨しています。そして、それを返します (データベースからの新しい ID は、bouns エンティティに応答して返されます)! これは役に立ちません。最初のレコードを追加してF5でページを更新し、その後2番目のレコードを追加した場合にのみ、すべて問題ありません。しかし、別のものを追加すると、3番目のレコード - 問題が再び発生します
コントローラーのコード:
[HttpPost]
public JsonResult Create(BonusDto bonusDto)
{
BonusAggregate bonus;
if (bonusDto.Amount <= 0)
throw new ArgumentOutOfRangeException("Amount should be more than 0");
if (bonusDto.EmployeeId <= 0)
throw new ArgumentNullException("You should specify an existing employee");
using (var dbContext = new DatabaseContext())
{
BonusesRepository = new BonusesRepository(dbContext);
var employeeRepository = new EmployeesRepository(dbContext);
bonus = new BonusFactory(employeeRepository).Create(bonusDto);
BonusesRepository.Save(bonus);
}
HttpContext.Response.StatusCode = (int)HttpStatusCode.Created;
return Json(bonus); // try to return ID after bonus was saved
}
UI コード
// creates bonuses grid control
$("#bonusesGrid").kendoGrid({
dataSource: bonusesDataSource,
toolbar: ["create"],
editable: "inline",
columns: [
"BonusId",
"EmployeeId",
{
field: "EmployeeLastName",
editor: employeeAutocompletingEditor,
template: "#=EmployeeLastName#"
},
"Amount",
{
field: "Comment",
titel: "Comment",
editor: textareaEditor,
filterable: {
operators: {
number: {
contains: "Contains"
}
}
}
},
{
command: ["edit"],
title: " "
}
],
save: function(e) {
if (newValueEmployeeId !== undefined &&
newValueEmployeeLastName !== undefined &&
newValueEmployeeLastName !== "") {
setNewValueEmployeeIdAndLastName(newValueEmployeeId, newValueEmployeeLastName);
gridDataSource.model.EmployeeId = newValueEmployeeId; // it's a hack to bind model and autocomplete control
gridDataSource.model.EmployeeLastName = newValueEmployeeLastName;
} else {
gridDataSource.model.EmployeeId = currentValueEmployeeId;
gridDataSource.model.EmployeeLastName = currentValueEmployeeLastName;
}
},
edit: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
},
cancel: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
}
});
ボーナス データ ソース:
// bind json result from /Bonuses/GetPagedJsonBonuses
var bonusesDataSource = new kendo.data.DataSource({
transport: {
read: {
url: "@Url.Action("GetPagedJsonBonuses", "Bonuses")",
type : "GET",
contentType: "application/json",
dataType: "json",
cache: false
},
create: {
url: "@Url.Action("Create", "Bonuses")",
dataType: "json",
type: "POST"
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
// correct format for conversion
var d = new Date(options.Date);
options.Date = kendo.toString(d, dateFormat);
// updates the BonusDTO.EmployeeId with selected value
if (newValueEmployeeId !== undefined)
options.EmployeeId = newValueEmployeeId;
}
if(operation === "read") {
options.filter = setFormattedFilterDate(options.filter);
}
return options;
}
},
pageSize: 15,
serverPaging: true,
serverSorting: true,
serverFiltering: true,
error: showErrorMessage,
schema: {
data: "Data", // PagedResponse.Data
total: "TotalCount", // PagedResponse.TotalCount
model: {
id: "BonusId", // Data
fields: {
EmployeeId: { type: "number" },
EmployeeLastName: {
type: "string",
editable: true,
nulable: false,
validation: { required: {message: "Employee's last name is required"}}
},
Date: {
type: "date",
editable: true,
nullable: false,
validation: {
required: { message: "Date is required to be set" }
}
},
Amount: {
type: "number",
editable: true,
nullable: false,
defaultValue: 1,
validation: {
required: { message: "Amount is required to be set" }
}
},
Comment: { type: "string", editable: true }
} // fields
} // model
}// schema
});