如何在 MVC Web API 发布方法中将 ModelState 错误返回到 Kendo 网格?

Posted

技术标签:

【中文标题】如何在 MVC Web API 发布方法中将 ModelState 错误返回到 Kendo 网格?【英文标题】:How to return ModelState errors to Kendo grid in MVC Web API post method? 【发布时间】: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 错误的最佳方式是什么?

【问题讨论】:

【参考方案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); ***.com/questions/9494966/… 简而言之,使用:ModelState.AddModelError(string.Empty, errMsg); 并获取 error_handler JavaScript 函数,并将 .Events(e =&gt; e.Error("error_handler")) 添加到您的网格中。在error_handler 中,您也可以只弹出一个alert() 而不是showAlertWindow(message); 希望我能投票 100 次!很好的解释,效果很好。

以上是关于如何在 MVC Web API 发布方法中将 ModelState 错误返回到 Kendo 网格?的主要内容,如果未能解决你的问题,请参考以下文章

如何在mvc5中将文化设置为全局

如何使用 Web API 来对 MVC 应用程序进行身份验证

如何使用 Web API 来对 MVC 应用程序进行身份验证

使用 Header 的 Web Api 版本控制,我们如何使用 Net Framework MVC Api 在 Swagger UI 上使用它

如何在 Spring MVC 中将请求映射到 HTML 文件?

如何在 Web API 中将 HttpResponse 设置为 HttpResponseMessage