Kendo ListView:在刷新浏览器会话之前不会反映添加/创建

问题描述

我正在使用 MVC 和 Kendo (UI v2018.3.1017) ListView 来管理我称为“MaximoList”的列表。为了使列表可用于多个控制器,我利用了 MVC 提供的“TempData”对象。在创建(和销毁)时,我看到 MaximoList 对象正确反映了更改。但是为了反映 UI 中的更改,我必须刷新 (F5) (Chrome) 浏览器。

对控件的 CSHTML 引用相当简单:

    <div class="col-md-3">
      <div class="form-group">
        <label style="white-space: nowrap;">Maximo Id's</label>
        <a id="btnAddMaximoEntry" onclick=window.allIsos.addMaximoEntry() href="#" title='Add Maximo' style='margin-left: 8px'><i class='fa fa-upload'></i></a>
        <div class="" id="divMaximoList">
        </div>
      </div>
    </div>

控件的JS定义为:

function addMaximoListView(isoId,outageId) {
  maximoListDataSource = new kendo.data.DataSource({
    transport: {
      read: { url: "/request/GetMaximoList",type: "GET",dataType: "json",cache: false },create: { url: "/request/AddMaximoEntry",type: "Post",destroy: { url: "/request/DeleteMaximoEntry",type: "POST",update: {},parameterMap: function (data,type) {
        if (type == "read") { return { IsoId: isoId,OutageId: outageId }; }
        if (type == "create") { return { MaximoId: data.MaximoId }; }
        if (type == "destroy") { return { id: data.Id }; }
      },sortable: true,pageable: true,},requestEnd: function (e) {
      console.log(e.type);
      console.log(e.response);
    },columns: [
      { field: "Id",Title: "Id",width: "0px" },{ field: "MaximoId",Title: "MaximoId",width: "50px" },{ command: ["edit","destroy"],title: "&nbsp;",width: "250px" }
    ],autoSync: false,schema: {
      model: {
        id: "Id",fields: {
          Id: { editable: false },MaximoId: { editable: true,type: "string" },}
      },});
  var getTemplate = ""
    + "<div>"
    + "    <a onclick=window.allIsos.deleteMaximo(#:Id#) href='\\#'><i class='fa fa-trash'></i></a>"
    + '#:MaximoId#</div>';
  var editTemplate = ""
    + "<div>"
    + "  <input type='text' data-bind='value: MaximoId' name='MaximoId' required='required' />"
    + "  <div>"
    + "    <a class='k-button k-update-button' href='\\#'><span class='k-icon k-i-check'></span></a>"
    + "    <a class='k-button k-cancel-button' href='\\#'><span class='k-icon k-i-cancel'></span></a>"
    + "  </div>"
    + "</div>";
  $("#divMaximoList").kendoListView({
    template: kendo.template(getTemplate),editTemplate: kendo.template(editTemplate),dataSource: maximoListDataSource,pageSize: 5,dataBound: function (e) {
      console.log("ListView is bound and ready to render.");
    }
  });
};

将项目添加到列表的JS定义是:

var addMaximoEntry = function () {
  var listView = $("#divMaximoList").data("kendoListView");
  listView.add();
};

重新启动后调试本地应用程序,这里是从 API/数据库公开测试数据的控件:

enter image description here

我点击了我的 ADD 按钮,在接受输入之前,请注意我的新 MaximoId 输入的值为“NotWorking”:

enter image description here

接受输入后,请注意控件添加了一个新条目,但它是原始项目之一的幽灵:

enter image description here

但是,在刷新页面 (F5) 后,请注意当 GET 从服务器端 TempData 对象中拉出时,服务器正确接收到实际的“NotWorking”项目,并且将更新后的 TempData 对象传递到 UI(其中包括新条目):

enter image description here

创建/添加的 API 方法如下 - 我正在返回 UI,更新的 MaximoList 对象的 JSON 表示并使用该更新的对象,刷新到 TempData["MaximoList"]:

[HttpPost,Route("AddMaximoEntry")]
public ActionResult AddMaximoEntry(string MaximoId)
{
  var ignoreCase = StringComparison.InvariantCultureIgnoreCase;
  try
  {
    List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();

    var maximoId = MaximoId;// unnecessary variable,but used for testing against multiple method confgurations

    var maximoEntry = new MaximoEntry();
    maximoEntry.MaximoId = maximoId;

    if (maximoList.Where(s => s.MaximoId.Equals(maximoEntry.MaximoId,ignoreCase)).FirstOrDefault() == null)
      maximoList.Add(maximoEntry);

    TempData["MaximoList"] = maximoList as List<MaximoEntry>;
    return Json(maximoList,JsonRequestBehavior.AllowGet);
  }
  catch (Exception ex)
  {
    var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
    return new JsonResult
    {
      Data = new
      {
        id = 0,Success = false,Msg = "Something went wrong while adding to the Maximo List. Please contact system support!"
      }
    };
  }
}

API GET 如下:

[HttpGet,Route("GetMaximoList")]
public ActionResult GetMaximoList(int IsoId,int OutageId)
{
  try
  {
    List<MaximoEntry> maximoList = ODataGetMaximoList(IsoId,OutageId);
    return Json(maximoList,Msg = "Something went wrong while getting Maximo List. Please contact system support!"
      }
    };
  }
}

解决方法

最初,ADD(CREATE) 的 API 方法传回了 Maximo 条目的整个 List(JSON 数组)。

解决方案是仅传回最初传递给 ADD(CREATE) 方法的 model 对象的更新版本,包括新分配的“id”值。新创建的条目将具有负索引值,稍后我将在 MERGE 语句中在数据库级别使用该值(即,主键的负值不应存在于数据库表中)以同步数据库。

如果还不清楚,我正在使用 TempData["MaximoList"] 对象来维护跨 API 控制器的 Kendo ListView 控件的状态。将控制状态保存到 DB(利用 TempData 对象)将发生在更通用的控制器方法中,该方法不管理状态(添加/删除/等)到 TempData 对象。

我还重新设计了 DESTROY (Delete) 组件以仅在成功的 API 调用时从 (UI) 列表中删除已删除的项目,并通过删除一些不需要的控件集来清理 JS反映 TempData 对象的状态。

我的 ADD 方法的 API 方法现在是:

[HttpPost,Route("AddMaximoEntry")]
public JsonResult AddMaximoEntry(MaximoEntry model)
{
  var ignoreCase = StringComparison.InvariantCultureIgnoreCase;
  try
  {
    List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();

    var minId = maximoList.Where(w => w.id <= 0);
    model.id = minId.Count() == 0 ? -1 : minId.Select(s => s.id).Min() - 1;

    if (maximoList.Where(s => s.maximoId.Equals(model.maximoId,ignoreCase)).FirstOrDefault() == null)
      maximoList.Add(model);

    TempData["MaximoList"] = maximoList as List<MaximoEntry>;
    return Json(model,JsonRequestBehavior.AllowGet);
  }
  catch (Exception ex)
  {
    var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
    return new JsonResult
    {
      Data = new
      {
        Success = false,Msg = "Something went wrong while adding to the Maximo List. Please contact system support!"
      }
    };
  }
}

我还更新了我的 DELETE 方法,作为 HTTPDELETE 方法,并返回一个状态指示器以提醒调用 JS 操作结果:

[HttpDelete,Route("DeleteMaximoEntry")]
public JsonResult DeleteMaximoEntry(int id)
{
  try
  {
    List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();

    var itemToRemove = maximoList.SingleOrDefault(r => r.id == id);
    if (itemToRemove != null)
      maximoList.Remove(itemToRemove);

    TempData["MaximoList"] = maximoList as List<MaximoEntry>;

    return Json(new { success = true,responseText = $"id {id} deleted from TempData object" });
  }
  catch (Exception ex)
  {
    var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
    return new JsonResult
    {
      Data = new
      {
        Success = false,Msg = $"Something went wrong while deleteing Maximo Entry (id {id}). Please contact system support!"
      }
    };
  }
}

SELECT(READ)和CREATE(Add)的JS控件定义为:

function addMaximoListView(isoId,outageId) {
  maximoListDataSource = new kendo.data.DataSource({
    transport: {
      batch: false,//default is false
      read: { dataType: "json",cache: false,type: "GET",url: "/request/GetMaximoList" },create: { dataType: "json",type: "POST",url: "/request/AddMaximoEntry" },parameterMap: function (data,type) {
        if (type == "read") { return { IsoId: isoId,OutageId: outageId }; }
        if (type == "create") { return { model: data }; }
      },},requestEnd: function (e) {
      console.log(e.type);
      console.log(e.response);
    },autoSync: false,serverFiltering: true,schema: {
      model: {
        id: "id",fields: {
          maximoId: { editable: true,type: "string" },}
      },});
  var getTemplate = ""
    + "<div>"
    + "  <a onclick=window.allIsos.deleteMaximo(#:id#) href='\\#'><i class='fa fa-trash'></i></a>"
    + "  #:maximoId#"
    + "</div > ";
  var editTemplate = ""
    + "<div>"
    + "  <input type='text' data-bind='value: maximoId' name='MaximoId' required='required' />"
    + "  <div>"
    + "    <a class='k-button k-update-button' href='\\#'><span class='k-icon k-i-check'></span></a>"
    + "    <a class='k-button k-cancel-button' href='\\#'><span class='k-icon k-i-cancel'></span></a>"
    + "  </div>"
    + "</div>";

  $("#divMaximoList").kendoListView({
    template: kendo.template(getTemplate),editTemplate: kendo.template(editTemplate),dataSource: maximoListDataSource,dataBound: function (e) {
      console.log("ListView is bound and ready to render.");
    }
  });
};

对于DESTROY(DELETE),我添加了这些JS方法(希望将这些元素嵌入到控件定义中):

var deleteMaximo = function (id) {
  executeDeleteMaximo(id,"Are you sure you want to delete this Maximo entry?");
}

function executeDeleteMaximo(id,confirmMsg) {
  common.LoadingGif("#mainView",false);
  common.ConfirmDialog(true,confirmMsg,function (reason) {
      if (reason == "NO") {
        common.LoadingGif("#mainView",true);
        return false;
      }
      $.ajax({
        type: "DELETE",data: { id: id },url: "/request/DeleteMaximoEntry",success: function (response) {
          var data = response;
          if (data.success) {
            var myDataSource = $("#divMaximoList").data().kendoListView.dataSource;
            var item = myDataSource.get(id);//need a check before attempting remove
            myDataSource.remove(item);

          }
          common.LoadingGif("#mainView",true);
          window.scrollTo(0,0);
        },error: function (jqXHR,textStatus,errorThrown) {
          var e = errorThrown;
        }
      });
    });
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...