【问题标题】:How to return ModelState errors to Kendo grid in MVC Web API post method?如何在 MVC Web API 发布方法中将 ModelState 错误返回到 Kendo 网格?
【发布时间】:2013-07-21 08:05:54
【问题描述】:

我找不到发布/更新方法返回验证错误的 Kendo + MVC Web API 示例。似乎没有可以使以下代码工作的 Kendo 扩展。

public HttpResponseMessage Post([ModelBinder(typeof(Prototype.WebApi.ModelBinders.DataSourceRequestModelBinder))][DataSourceRequest] DataSourceRequest request, User user)
    {
        if (this.ModelState.IsValid)
        {               
           //save               
        }
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState.ToDataSourceResult());            
    }

因为此上下文中的 ModelState 是 System.Web.Http.ModelBinding.ModelStateDictionary,而 Kendo 扩展需要 System.Web.Mvc.ModelStateDictionary。

那么从 Web API 向 Kendo 返回 ModelState 错误的最佳方式是什么?

【问题讨论】:

    标签: c# validation asp.net-web-api kendo-ui


    【解决方案1】:

    这对我们来说非常有用,尽管我们从来没有看到 ModelState 错误并且通常会省略那部分...

    剑道网格

    @model SysMaintViewModel
    @(Html.Kendo().Grid<BuildingModel>()
        .Name("BuildingsGrid")
        .Columns(columns =>
        [Stuff Omitted]
        .DataSource(dataSource => dataSource
            .Ajax()
    >>>     .Events(e => e.Error("error_handler"))
            .Model(model =>
            {
                model.Id(m => m.Id);
                model.Field(m => m.ProjectId).DefaultValue(Model.ProjectId);
                model.Field(m => m.IsActive).DefaultValue(true);
            })
            .Create(create => create.Action("CreateBuilding", "SysMaint"))
            .Read(read => read.Action("ReadBuildings", "SysMaint", Model))
            .Update(update => update.Action("UpdateBuilding", "SysMaint"))
            .Destroy(destroy => destroy.Action("DestroyBuilding", "SysMaint"))
        )
    )
    

    控制器

    [HttpPost]
    public JsonResult UpdateBuilding([DataSourceRequest]DataSourceRequest request, BuildingModel modelIn)
    {
        var building = new BuildingModel();
        if (ModelState.IsValid)
        {
            try
            {
                building = _presentationService.UpdateBuilding(modelIn);
            }
            catch (Exception e)
            {
                ModelState.AddModelError(string.Empty, e.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);
        }
        var buildings = (new List<BuildingModel> {building}).ToDataSourceResult(request, ModelState);
        return Json(buildings, JsonRequestBehavior.AllowGet);
    }
    

    更新的控制器

    我们发现这个流程工作得更好一些,它向 Elmah 添加了错误日志记录(通用示例)...

    [HttpPost]
    public JsonResult Update([DataSourceRequest]DataSourceRequest request, MyObjectModel modelIn)
    {
        try
        {
            if (ModelState.IsValid)
            {
                var myObject = _presentationService.Update(modelIn, User.Identity.Name);
                var myObjectList = new List<MyObjectModel> { myObject };
                return Json(myObjectList.ToDataSourceResult(request, ModelState), JsonRequestBehavior.AllowGet);
            }
            else
            {
                var myObjectList = new List<MyObjectModel> { modelIn };
                return Json(myObjectList.ToDataSourceResult(request, ModelState), JsonRequestBehavior.AllowGet);
            }
        }
        catch (Exception e)
        {
            Elmah.ErrorSignal.FromCurrentContext().Raise(e);
            ModelState.AddModelError(string.Empty, e.Message);
            var myObjectList = new List<MyObjectModel> { modelIn };
            return Json(myObjectList.ToDataSourceResult(request, ModelState), JsonRequestBehavior.AllowGet);
        }
    }
    

    通用 JavaScript 和剑道窗口

    @(Html.Kendo().Window()
        .Name("alertWindow")
        .Title("Status Message from Server")
        .Draggable()
        .Resizable()
        .Width(400)
        .Height(200)
        .Modal(true)
        .Visible(false)
    )
    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 = "Errors:\n";
            $.each(e.errors, function (key, value) {
                if ('errors' in value) {
                    $.each(value.errors, function () {
                        message += this + "\n";
                    });
                }
            });
            showAlertWindow(message);
        }
    }
    

    奖金

    我们的 BaseModel 也有一个 ErrorMessage 参数,我们将其他类型的错误放入检查页面加载是否应该为其他任何内容打开相同的警报窗口。

    $(document).ready(function () {
        if ("@Model.ErrorMessage" != "") {
            showAlertWindow("@Model.ErrorMessage");
        }
    });
    

    当出现错误时,它的演示效果非常好 - 让我们的内部用户不会惊慌失措。希望对您有所帮助。

    【讨论】:

    • 谢谢,但您的控制器是常规 MVC 控制器还是 Web api 控制器(即继承自 ApiController)。我的观点是这条线不会在 Web API 中编译,因为 ApiController 中的 ModelState 与 MVC 控制器不同。 var building = (new List {building}).ToDataSourceResult(request, ModelState);
    • 简而言之,使用:ModelState.AddModelError(string.Empty, errMsg); 并获取 error_handler JavaScript 函数,并将 .Events(e =&gt; e.Error("error_handler")) 添加到您的网格中。在error_handler 中,您也可以只弹出一个alert() 而不是showAlertWindow(message);
    • 希望我能投票 100 次!很好的解释,效果很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 2018-01-16
    • 1970-01-01
    • 2017-11-01
    相关资源
    最近更新 更多