简体   繁体   English

使用AJAX提交部分页面时出错

[英]Error on submitting partial page using AJAX

Recently, I quite often get errors that work in dev but not in production, and this is the one. 最近,我经常遇到在开发人员中有效但在生产中无效的错误,这就是一个。 When submitting partial page using AJAX I've got error "500 Internal Server Error" . 使用AJAX提交部分页面时,出现错误“ 500 Internal Server Error”。 The detail that captured by Firebug: Firebug捕获的详细信息:

Exception details 例外详情

Controller: TimeKeeper 控制器:TimeKeeper
Action: Edit 行动:编辑
Message: There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'StateID'. 消息:没有类型为“ IEnumerable <SelectListItem>”的ViewData项目具有键“ StateID”。
StackTrace: 堆栈跟踪:

Exception:    at System.Web.Mvc.Html.SelectExtensions.GetSelectData(HtmlHelper htmlHelper, String name)
   at System.Web.Mvc.Html.SelectExtensions.SelectInternal(HtmlHelper htmlHelper, ModelMetadata metadata, String optionLabel, String name, IEnumerable`1 selectList, Boolean allowMultiple, IDictionary`2 htmlAttributes)
   at System.Web.Mvc.Html.SelectExtensions.DropDownList(HtmlHelper htmlHelper, String name, IEnumerable`1 selectList, String optionLabel, Object htmlAttributes)
   at ASP._Page_Views_TimeKeeper__Edit_cshtml.Execute() in c:\inetpub\wwwroot\[appname]\Views\TimeKeeper\_Edit.cshtml:line 64
   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
   at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
   at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)
   at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
   at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<>c__DisplayClass2b.<BeginInvokeAction>b__1c()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult)

_Edit.cshtml (Partial): _Edit.cshtml(部分):

@model appname.ViewModels.TimeKeeperEditViewModel

<link href="@Url.Content("~/Content/datepicker.css")" rel="stylesheet" type="text/css" />
<link href="@Url.Content("~/Content/datepicker3.css")" rel="stylesheet" type="text/css" />

<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
    <h4 class="modal-title" id="myModalLabel">Edit Time Keeper</h4>
</div>

@using (Ajax.BeginForm("Edit", "TimeKeeper",
    new AjaxOptions
    {
        InsertionMode = InsertionMode.Replace,
        HttpMethod = "POST",
        OnComplete = "editTimeKeeperComplete",
        UpdateTargetId = "timeKeeperList"
    }))
{
    @Html.ValidationSummary(true)
    @Html.HiddenFor(model => model.TimeKeeperID)
    @Html.HiddenFor(model => model.BillingID)

    <div class="modal-body">
        <div class="form-horizontal">
            <div class="form-group">
                <div class="col-md-4">
                    <label for="billingRate" class="control-label">Billing Rate</label>
                </div>
                <div class="col-md-8">
                    @Html.EditorFor(model => model.BillingRate, new { htmlAttributes = new { @class = "form-control" } })
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-4">
                    <label for="billingStartDate" class="control-label">Billing Start Date</label>
                </div>
                <div class="col-md-8">
                    @Html.EditorFor(model => model.BillingStartDate, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-4">
                    <label for="status" class="control-label">Status</label>
                </div>
                <div class="col-md-8">
                    @Html.DropDownList("StateID", null, String.Empty, new { @class = "form-control" })
                </div>
            </div>
        </div>
    </div>

    <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal" id="btnClose">Close</button>
        <button type="submit" class="btn btn-primary" id="btnSave">Save changes</button>
    </div>
}

<script type="text/javascript">
    $(document).ready(function () {
        $("#BillingStartDate").datepicker({
            format: "dd/mm/yyyy",
            todayBtn: "linked",
            autoclose: true,
            todayHighlight: true
        });
    });
</script>

This code to populate StateID: 这段代码填充StateID:

private void PopulateStateDropDownList(object selectedState = null)
        {
            var statesQuery = from s in db.States
                              where s.RowStatus == true && s.StateGroupID == 1
                              orderby s.Name
                              select new
                              {
                                  StateID = s.StateID,
                                  Name = s.Name
                              };

            ViewBag.StateID = new SelectList(statesQuery, "StateID", "Name", selectedState);
        }

Post action code: 动作后代码:

[HttpPost]
        public ActionResult Edit(TimeKeeperEditViewModel timeKeeperEditVM)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    LogHelper.logger.Info("Model Valid");
                    TimeKeeper timeKeeper = db.TimeKeepers.Find(timeKeeperEditVM.TimeKeeperID);
                    timeKeeper.BillingRate = timeKeeperEditVM.BillingRate;
                    timeKeeper.BillingStartDate = timeKeeperEditVM.BillingStartDate;
                    timeKeeper.BillingEndDate = timeKeeperEditVM.BillingEndDate;
                    timeKeeper.StateID = timeKeeperEditVM.StateID;

                    LogHelper.logger.Info("Save");
                    db.Entry(timeKeeper).State = EntityState.Modified;
                    db.SaveChanges();

                    LogHelper.logger.Info("Get Timekeepers");
                    Billing billing = db.Billings.Find(timeKeeperEditVM.BillingID);
                    BillingTimeKeeperViewModel billingVM = new BillingTimeKeeperViewModel()
                    {
                        BillingID = billing.BillingID,
                        TimeKeepers = billing.TimeKeepers
                    };

                    LogHelper.logger.Info("Return");
                    return PartialView("_List", billingVM.TimeKeepers);
                }
                else
                {
                    LogHelper.logger.Info("Model is not Valid");
                    return PartialView("_Edit");
                }
            }
            catch (Exception ex)
            {
                LogHelper.logger.Error(ex);
                return RedirectToAction("Index", "Error", ex);
            }
        }

I'm using NLog to see the problem. 我正在使用NLog来查看问题。 There is no error, but the ModelState.IsValid is false 没有错误,但是ModelState.IsValid为false

UPDATE 更新

I placed log before if (ModelState.IsValid) to print out BillingRate, BillingStartDate, BillingEndDate, and StateID. 我将日志放在if (ModelState.IsValid)之前以打印出BillingRate,BillingStartDate,BillingEndDate和StateID。 It's caused by BillingEndDate is null if I fill day more than 12 for example 13/1/2014, but If I fill with 12/1/2014 the ModelState.IsValid is true. 这是由BillingEndDate引起的,如果我填写的日期超过12天(例如2014年1月1日),则为null,但如果我填写的是2014年1月1日,则ModelState.IsValid为true。

So my conclusion, it caused by date format. 所以我的结论是由日期格式引起的。 The problem is I prohibited to change server date format. 问题是我禁止更改服务器日期格式。 Any suggestion? 有什么建议吗?

It is generally bad to pass drop down lists through the viewbag. 通过视图包传递下拉列表通常是不好的。 I would recommend putting that into the model 我建议将其放入模型中

public List<SelectListItem> StateList { get; set; }

then populate this list with your database call 然后用您的数据库调用填充此列表

foreach(var temp in statesQuery){
    model.StateList.Add(new SelectListItem() { Text = temp.Name, Value = temp.StateID });
}

then on your view change your drop down list to 然后在您的视图上将您的下拉列表更改为

@Html.DropDownListFor(x => x.StateID, Model.StateList)

you can set the drop down on the controller by setting model.StateID and the selected value from the drop down will be tied to that field on post back 您可以通过设置模型在控制器上设置下拉菜单。StateID和从下拉菜单中选择的值将在回发时绑定到该字段

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM