为什么更新master-detail GridView内容会抛出FormatException,同时细节网格仍然打开?

时间:2016-07-21 08:49:09

标签: c# asp.net-mvc gridview asp.net-mvc-5 devexpress

背景

我使用EF 6 Database First& amp; amp; DevExpress 15.2。下面给出的项目结构(随意重现):

模型(ProjectModel.cs)

namespace Project.Models
{
    // EF data context
    public class ProjectContext : DbContext
    {
        public ProjectContext : base("DatabaseConnection") 
        { 
        }
        public DbSet<Receipt> Receipts { get; set; }
        public DbSet<SoldList> SoldLists { get; set; }
    }

    [Table("Receipt")]
    public class Receipt
    {
        [Key]
        public int ReceiptID { get; set; }
        public String SessionID { get; set; }
        public String MemberID { get; set; }
        public String MemberName { get; set; }
        public DateTime ReceiptDate { get; set; }
        public String TransID { get; set; }
        public decimal TotalPrice { get; set; }
        public decimal RemainingCredit { get; set; }
        public bool? UseRemainingCredit { get; set; }
    }

    [Table("SoldList")]
    public class SoldList
    {
        [Key]
        public int ItemID { get; set; }
        public String SessionID { get; set; }
        public String MemberID { get; set; }
        public int TransID { get; set; }
        public decimal TotalPrice{ get; set; }
        public bool? UseRemainingCredit { get; set; }
    }
}

Controller(MasterController.cs)

namespace Project.Controllers
{
    public class MasterController : Controller
    {
        public ViewResult Transaction()
        {
            using (var DB = new ProjectContext())
            {
                var model = (from record in DB.Receipts select record).ToList();
                return View(model);
            }
        }

    // master grid partial view
    public PartialViewResult PVTransaction()
    {
        using (var DB = new ProjectContext())
        {
            var model = (from record in DB.Receipts select record).ToList();
            return PartialView("_MasterTrans", model);
        }
    }

    // detail grid partial view
    public PartialViewResult PVDetails(String sessionID, String memberID, String transID)
    {
        ViewData["TransID"] = transID;
        // edit: adding forgotten IDisposable context declaration 
        using (var DB = new ProjectContext())
        {
            var model = (from list in DB.SoldLists where list.TransID == transID && list.MemberID == memberID && list.SessionID == sessionID select list).ToList();
            return PartialView("_DetailTrans", model);
        }
    }

    [HttpPost]
    [ValidateInput(false)]
    public PartialViewResult EditTrans(Receipt item)
    {
        using (var DB = new ProjectContext())
        {
            var model = (from record in DB.Receipts select record).ToList();
            try
            {
                var match = DB.Receipts.FirstOrDefault(x => x.ReceiptID == item.ReceiptID);
                if (match != null)
                {
                    var sum = DB.SoldLists.Where(x => x.TransID == match.TransID).Select(x => x.TotalPrice).Sum();
                    var useRemaining = DB.SoldLists.Where(x => x.TransID == match.TransID).Select(x => x.UseRemainingCredit).FirstOrDefault();
                    if (item.TotalPrice - match.RemainingCredit != sum && (useRemaining == null || useRemaining == false))
                    {
                        // other unrelated code
                    }
                    else
                    {
                        match.SessionID = item.SessionID;
                        match.MemberID = item.MemberID;
                        // other data update definitions

                        this.UpdateModel(match);
                        DB.SaveChanges();
                        ViewBag.Success = "Selected data edited successfully.";
                    }
                }
            }
            catch (Exception e)
            {
                ViewBag.Error = "Problem on editing with error message: \'" + e.Message + "\'";
            }
            return PartialView("_MasterTrans", model);
        }
    }
}

查看(Transaction.cshtml)

@using Project.Models
<script type="text/javascript">
    function onMasterInit(s, e) {
        MasterGrid.PerformCallback();
    }
    function endMasterCallback(s, e) {
        if (s.cpMasterMsg) {
            alert(s.cpMasterMsg);
            delete s.cpMasterMsg;
            MasterGrid.Refresh();
        }
        else if (s.cpErrorMsg) {
            alert(s.cpErrorMsg);
            delete s.cpErrorMsg;
            MasterGrid.Refresh();
        }
    }
</script>
<label class="description">Transaction List</label>
@using (Html.BeginForm()) 
{
    Html.RenderAction("PVTransaction", "Master");
}

部分视图(_MasterTrans.cshtml)

@using Project.Models
@{
    GridViewExtension grid = Html.DevExpress().GridView(settings =>
    {
        settings.Name = "MasterGrid";
        settings.CallbackRouteValues = new { Controller = "Master", Action = "PVTransaction" };
        settings.Width = Unit.Percentage(100);
        settings.CommandColumn.ShowEditButton = true;
        settings.CommandColumn.ShowUpdateButton = true;
        settings.CommandColumn.ShowCancelButton = true;
        settings.SettingsBehavior.AllowFocusedRow = true;
        settings.SettingsBehavior.AllowSelectByRowClick = true;
        settings.SettingsBehavior.ConfirmDelete = true;
        settings.SettingsContextMenu.Enabled = true;
        settings.SettingsContextMenu.EnableRowMenu = DefaultBoolean.True;
        settings.SettingsContextMenu.EnableColumnMenu = DefaultBoolean.True;
        settings.SettingsEditing.Mode = GridViewEditingMode.PopupEditForm;
        settings.SettingsEditing.UpdateRowRouteValues = new { Controller = "Master", Action = "EditTrans" };

        settings.SettingsText.ConfirmDelete = "Remove selected data?";
        settings.SettingsText.ContextMenuExpandDetailRow = "Show Details";
        settings.SettingsText.ContextMenuCollapseDetailRow = "Hide Details";
        settings.ClientSideEvents.Init = "onMasterInit";
        settings.ClientSideEvents.EndCallback = "endMasterCallback";
        settings.CustomJSProperties = (s, e) =>
        {
            if (ViewBag.Success != null)
            {
                e.Properties["cpMasterMsg"] = ViewBag.Success.ToString();
                e.Properties["cpErrorMsg"] = ViewBag.Error.ToString();
            }
        };

        // begin detail gridview
        settings.SettingsDetail.AllowOnlyOneMasterRowExpanded = false;
        settings.SettingsDetail.ShowDetailButtons = true;
        settings.SettingsDetail.ShowDetailRow = true;
        settings.SetDetailRowTemplateContent(content =>
        {
            ViewContext.Writer.Write(@"<p style=""font-size:14px; text-decoration:underline"">Transaction Detail of " + DataBinder.Eval(content.DataItem, "MemberName") + " at " + String.Format("{0:yyyy/MMMM/dd}", DataBinder.Eval(content.DataItem, "ReceiptDate")) + ", Session ID: " + DataBinder.Eval(content.DataItem, "SessionID") + "</p>");

            // this line throws FormatException on editing master grid while detail grid still open
            Html.RenderAction("PVDetails", "Master", new { sessionID = DataBinder.Eval(content.DataItem, "SessionID"), memberID = DataBinder.Eval(content.DataItem, "MemberID"), transID = DataBinder.Eval(content.DataItem, "TransID")}); 
        });

        // end of detail gridview

        settings.KeyFieldName = "ReceiptID";
        settings.Columns.Add(column => 
        {
            column.FieldName = "ReceiptID";
            column.Caption = "Receipt ID";
        }
        // other columns with similar construction
        // including SessionID, MemberID, MemberName, ReceiptDate, TransID columns
    }
}
@grid.Bind(Model).GetHtml()

部分视图(_DetailTrans.cshtml)

@using Project.Models
@{
    GridViewExtension grid = Html.DevExpress().GridView(settings =>
    {
        settings.Name = "DetailGrid" + ViewData["TransID"]; // using transaction ID column from master grid to generate unique detail grid name
        settings.CallbackRouteValues = new { Controller = "Master", Action = "PVDetails" };

        settings.SettingsDetail.MasterGridName = "MasterGrid";
        settings.KeyFieldName = "ItemID";

        settings.Columns.Add(column =>
        {
            column.Name = "ItemID";
            column.Caption = "Item ID";
        });
        // other columns with similar construction
    }
}
@grid.Bind(Model).GetHtml()

问题陈述

主网格视图提供编辑交易数据和详细网格视图按主网格中的值显示项目列表。当用户点击Edit按钮时,弹出编辑窗口会显示提供可编辑数据。

TransID属性包含随机的40位十六进制数字,确保有效的交易。

如果隐藏了详细网格,则所有编辑操作都可以正常工作,但如果用户尝试编辑&amp;当详细网格视图仍然打开时(使用折叠符号)更新主网格内容时,抛出了FormatException(参见详细信息)。

尽管视图抛出异常,但编辑后的数据已成功保存,但会重定向到自定义错误页面。我在附加信息中给出了关键字搜索,没有结果。

例外详细信息

An exception of type 'System.FormatException' occurred in System.Web.dll was caught.

HResult: -2146233033
Source: DevExpress.Web.v15.2
Additional information: Unexpected 'O' at 0
Stack Trace (simplified):

   at DevExpress.Web.Internal.JsonReader.ReadCore()
   at DevExpress.Web.Internal.JsonReader.Read(String jsonString)
   at DevExpress.Web.Internal.HtmlConvertor.FromJSON(String jsonString)
   at DevExpress.Web.Mvc.Internal.ExtensionValueProvidersFactory.GetValueProvider(ModelBindingContext bindingContext, String propertyName)
   at DevExpress.Web.Mvc.DevExpressEditorsBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
   at DevExpress.Web.Mvc.Internal.ContentControl`1.RenderInternal(HtmlTextWriter writer)
   at DevExpress.Web.Mvc.Internal.ContentControl`1.Render(HtmlTextWriter writer)
   at DevExpress.Web.Mvc.ExtensionBase.RenderControl(Control control)
   at DevExpress.Web.Mvc.ExtensionBase.RenderCallbackResultControl()
   at DevExpress.Web.Mvc.GridViewExtension.RenderCallbackResultControl()
   at DevExpress.Web.Mvc.ExtensionBase.RenderCallbackResult()

预期结果

我希望所有编辑操作都能在每个细节网格状态下正常运行。

欢迎任何帮助和建议,提前谢谢。

0 个答案:

没有答案