gpt4 book ai didi

javascript - 在发送给 Controller 时使用js时,将modelstate错误返回到 View

转载 作者:行者123 更新时间:2023-12-02 16:13:43 25 4
gpt4 key购买 nike

我正在将js对象从我的视图发送到mvc控制器中的post操作

$.post("/home/someaction", { obj: myData }, function(data) {
alert(data);
});


现在在控制器动作内,我想对modelstate错误显示错误消息并将视图返回到填充数据

[HttpPost]
public ActionResult someAction(MyModel obj)
{
if (!ModelState.IsValid)
{
ModelState.AddModelError("", "Error occured");
return View(obj);
}
...
}


这不起作用,我将整个视图作为html源返回给调用控制器的js函数。我想在验证摘要中显示错误,就像发送普通剃刀表格时一样

最佳答案

您的someAction是否是返回一个JsonResult的Ajax方法。使用View()方法返回ViewResult,它是一个呈现的html页面。

现在,这是从操作方法返回Json的常见要求。我的建议是使用JsonResult操作类型。

https://msdn.microsoft.com/en-us/library/system.web.mvc.jsonresult%28v=vs.118%29.aspx

现在使用JsonResult操作结果类型将确保您具有JSON结果,它不会以任何有意义的状态数据响应您的ajax请求。那取决于你。从AJAX角度再次处理ModelState由您决定。这看似令人生畏,但实现Ajax处理程序和包装程序来处理此问题可能非常容易。

首先,我们需要了解我们将要处理什么类型的错误以及我们将如何处理它们。在我构建的大多数应用程序中,通常都将ActionResult子类化,以允许我扩展对Ajax-Requests的响应方式。

让我们从请求生命周期开始

现在,典型的请求遵循这种生命周期:


发送到服务器的Ajax请求
服务器验证请求


401、30x未经授权的\重定向。表示无效的响应并重定向浏览器

调用Ajax方法:返回响应代码


200:响应正常
400:响应无效。 (确定可能不是正确的状态代码。但是,嘿!)
500:需要做更多的测试



在解释请求模型之前,响应代码400是一个非常灰色的区域,因为它可能表示很多东西。您可能会考虑使用代码500501,因为它们表明它们是服务器错误。但是,我通常喜欢以不同的方式处理这些错误,因为它们通常意味着更深层次的问题,应该以不同的方式进行处理。

现在,根据上述模型,我们完成了对服务器的请求,服务器将消化该请求并做出相应的响应。在典型的应用程序中,如果未授权用户,则ajax请求应返回401 Unauthorized结果,如果请求的资源已移动,则应返回30x响应。

一旦知道请求是有效的并且已通过身份验证,我们就可以继续通过action方法处理请求。如上所述,我喜欢(同意)对ActionResult类进行子类化并相应地处理响应。现在,这里的计划(以及这完全是个人的行为)是将标准[结构化]对象返回给我们的Java脚本调用方法。子类化ActionResult类型时,我们必须实现ExecuteResult方法。这是最终返回给客户端的方法。我个人最喜欢的JSON框架是Json.Net,因此我们必须引用Package Json.Net

这是我们最初的AjaxResult类:

public class AjaxResult : ActionResult
{
public object Data { get; set; }

public bool Completed { get; set; }

public string Message { get; set; }

public bool AllowGet { get; set; }

public override void ExecuteResult(ControllerContext context)
{

var result = new JsonResult
{
Data = new
{
Completed = this.Completed,
Message = this.Message,
Data = this.Data
}
};
result.JsonRequestBehavior = this.AllowGet ? JsonRequestBehavior.AllowGet : JsonRequestBehavior.DenyGet;
result.ExecuteResult(context);
}
}


因此,此简单类具有4个属性。其中三个属性定义了对客户端的标准响应。您可以将其视为一个接口,其中每个Ajax请求都将包含3个属性


已完成:如果响应完成或失败,则以bool指示。
消息:请求消息。这可能是来自失败请求或简单“感谢”响应的错误消息。可以基于每个实例实现此属性
数据:可序列化以返回给客户端的对象。现在,它可以是原始值,对象或复杂数组。只要可以序列化,就可以安全地返回。


第四个属性 AllowGet只是告诉 JsonResult是否接受get请求。但是,您应该已经适当地处理了。

现在,我们声明了“接口”,可以根据需要在操作结果中使用它。如下面的例子:

[HttpPost]
public AjaxResult DoAjaxWork(AjaxModel model)
{
if (model == null)
{
return new AjaxResult
{
AllowGet = false,
Completed = false,
Message = "The model is null",
};
}
if (!ModelState.IsValid)
{
var error = this.ModelState.FirstOrDefault(x => x.Value.Errors.Count > 0).Value.Errors.First().ErrorMessage;
return new AjaxResult
{
AllowGet = false,
Message = error,
Completed = false
};
}
return new AjaxResult { Completed = true };
}


现在,在这个简单的Action方法中, AjaxModel类只有一个标记为 Required的字段。在执行过程中(通常),我们检查 null模型,然后检查 ModelState.IsValid标志以确保模型有效。如果不是,我们通过将 Completed标志设置为 false来返回不完整的响应。然后,我们可以适当地在客户端上消化此情况。

客户页面非常简单,但是我们必须记住,我们基本上将在每个结果上消化一个结构化的类。因此,一个简单的请求看起来像:

function sendRequest() {
var requestData = {
myData: 'abcded'
}
$.ajax({
url: '@Url.Action("DoAjaxWork", "Default")',
data: JSON.stringify(requestData),
success: function (data) {
if (!data.Completed) {
alert(data.Message);
return;
}
alert('All Ok Boss')
},
error: function (jqXHR, textStatus, errorThrown) {
if (jqXHR.readyState == 0 || jqXHR.status == 0)
return; // it's not really an error
var errorStr = errorThrown;
switch (jqXHR.status) {
case 301:
case 302:
errorStr = "Redirected";

case 404:
errorStr = 'Not Found';
break;

case 500:
errorStr = 'There was an error completing the server request. The server operation failed.';
break;

case 401:
errorStr = errorThrown; //handle invalid request
break;

default:
errorStr = textStatus + ' ' + errorThrown;
break;
}
alert(errorStr);
}
});
}


神圣的蝙蝠侠多数民众赞成在很多简单的方法的Javascript。是的,但是大多数脚本都围绕错误处理。现在忍受了。因此,我们有一个非常基本的方法来调用AjaxHandler,该方法将根据我们理解的接口返回一个对象。 Ajax的最大部分是正确处理我们的错误。而且我必须说,通过一个非常引人注目的错误框发出警报并不完全是用户友好的,我们明白了这一点。让我们分解一下。

我们发出请求,服务器响应。如果它的状态代码为 200,则单击 success函数调用,然后让我们查看结构化对象,以确定请求是否实际上为 Completed;否则,我们将显示返回的错误消息。否则,我们将继续完成的逻辑。

到目前为止很好。现在,我们有了响应接口,可以扩展服务器响应,以在出现错误时返回 400错误代码并消化模型状态。为此,我们需要对错误处理程序进行一些扩展。首先,让我们在ajax调用中进行这些假设。


可能不是调用请求的HTML浏览器
并非所有错误情况都相同


现在让我们处理Ajax Authentication的最大问题。理想情况下,您将把我们在这里学到的知识抽象化到较低的水平,但是现在我们将在操作级别进行处理。我们需要使我们的 AjaxResponse遵循我们设计的界面。到目前为止,我们的接口对每个请求都返回一个 200 Completed响应。让我们用一个多于 200 Completed的响应来响应。我们将保留 Completed属性,但现在添加一个属性 StatusCode(并使该属性 virtual成为将来的证明)。

这是我们新的 AjaxResult类:

public partial class AjaxResult : ActionResult
{
public AjaxResult()
{
this.StatusCode = 200;
}

public virtual int StatusCode { get; set; }

public virtual object Data { get; set; }

public virtual bool Completed { get; set; }

public virtual string Message { get; set; }

public virtual bool AllowGet { get; set; }

public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");

if (!this.AllowGet && String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
throw new InvalidOperationException("Ajax GET request not allowed.");
object responseData = new
{
Completed = this.Completed,
Message = this.Message,
Data = this.Data
};
HttpResponseBase response = context.HttpContext.Response;
response.Clear();
response.ContentType = "application/json";
response.StatusCode = this.StatusCode;
if (200 != response.StatusCode)
response.Write("{}"); //not valid.. you get no data!!!
else
response.Write(JsonConvert.SerializeObject(responseData));

}
}


返回非200响应的示例(在这种情况下为未经授权)

public AjaxResult DoAjaxWork(AjaxModel model)
{
if (User == null) //do your own user validation tests
{
return new AjaxResult{ StatusCode = 401 };
}
//rest of our method

}


是的,看起来很性感。...是的,我们可以取消已完成的标志,但现在就保留它。您将看到我们不再使用 JsonResult类型,但是现在有了我们自己的类型(尽管遵循.Net类型 https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/JsonResult.cs)。这个新班级的工作与上一班课完全相同,只是它响应不断变化的状态码。因此,众所周知,对于大多数AjaxRequest,只有 200实际上是有效的状态代码(如果要缓存结果,请寻求其他建议)。

因此,现在我们可以将 StatusCode以外的 200返回给客户端。现在,您可以在这里决定通过返回非200的 StatusCode并在ajax错误处理程序中处理该错误或使用 CompletedFlag来处理错误,来一般性地处理服务器验证错误和状态码。

松了一口气

我们已经完成了无聊的部分。至此,我们应该在您的客户端(喜欢该客户端)和服务器(恶意服务器)之间采用一个公共接口。

现在我们有了这个通用的接口,可以扩展它以处理 ModelState错误。可以采用它来满足您的需求。让我们向 AjaxResult类添加一个方法。

public static AjaxResult Failed(ModelStateDictionary modelState, string titleMessage = "", bool allowGet = false)
{
StringBuilder errorBuilder = new StringBuilder();
if (!string.IsNullOrEmpty(titleMessage))
errorBuilder.AppendLine(titleMessage);

modelState.Where(x => x.Value.Errors != null && x.Value.Errors.Count > 0).SelectMany(x => x.Value.Errors).ToList().ForEach(e =>
{
string errorLine = null;
if (e.ErrorMessage != null)
errorLine = string.Concat("", e.ErrorMessage);
if (e.Exception != null)
errorLine = string.Concat(errorLine, "Exception:", e.Exception.Message);
errorBuilder.Append(errorLine);
});

return new AjaxResult
{
Completed = false,
StatusCode = 200, //Your call here.. 200 = check completed flag, else handle it in the error handler
AllowGet = false,
Data = null,
Message = errorBuilder.ToString()
};
}


使用这种状态方法,我们可以简单地将 ModelStateDictionary发送到该类,它将结果标记为失败并适当地返回错误消息。现在,根据我们先前的Ajax请求模型,首先处理 Completed标志,该标志允许应用程序立即就错误发出警报。只是为了好玩,我们添加了 titleMessage变量,该变量允许我们在错误消息中添加 Header。毕竟,我们原始的Ajax处理程序仍然可以承受这些更改。我们可以从动作中调用方法:

if (!ModelState.IsValid)
return AjaxResult.Failed(this.ModelState, "There was one or more errors", false);


现在我们的ajax处理程序(已编写):

success: function (data) {
if (!data.Completed) {
alert(data.Message);
return;
}
alert('All Ok Boss')
}


将相应地响应错误模型状态。现在,我们的 AjaxResult类使您可以过滤除 200以外的状态代码中的数据,并做出相应的响应。

可能错过了问题的重点。

但是,进一步讲,您“可以”实现 400状态代码并将 JavaScript ajax调用包装到您自己的扩展中,并全局处理大多数错误和问题。

关于javascript - 在发送给 Controller 时使用js时,将modelstate错误返回到 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29892738/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com