Javascript 在发送到控制器时使用js将modelstate错误返回到视图
我将js对象从我的视图发送到mvc控制器内部的post操作Javascript 在发送到控制器时使用js将modelstate错误返回到视图,javascript,c#,.net,Javascript,C#,.net,我将js对象从我的视图发送到mvc控制器内部的post操作 $.post("/home/someaction", { obj: myData }, function(data) { alert(data); }); 现在,在控制器操作中,我想在modelstate错误上显示错误消息,并将视图返回到填充数据 [HttpPost] public ActionResult someAction(MyModel obj) { if (!ModelState.IsValid) {
$.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函数。我想在validationsummary上显示错误,就像发送普通razor表单时一样是否可以将错误消息返回为
JSON
消息,以便:
[HttpPost]
public ActionResult someAction(MyModel obj)
{
if (!ModelState.IsValid)
{
ModelState.AddModelError("", "Error occured");
return Json("Error occured", JsonRequestBehavior.AllowGet);
}
...
}
这应该适用于您提供的JavaScript
作为一种扩展思路,如果你开始做一些新的事情,你可以看看AngularJS和WebAPI,它们将为你处理很多这方面的事情。你的
someAction
是否被怀疑是一个返回JsonResult
的Ajax方法。使用View()
方法返回一个ViewResult
,它是一个呈现的html页面
现在,这是从操作方法返回Json
的常见要求。我的建议是使用JsonResult
操作类型
现在使用JsonResult
操作结果类型将确保您有一个JSON结果,它不会用任何有意义的状态数据响应ajax请求。这取决于你。再次从AJAX的角度处理ModelState
,这取决于您。这看起来令人望而生畏,但实现ajax处理程序和包装器来处理这一问题非常容易
首先,我们需要了解我们将要处理的错误类型以及我们将如何处理它们。在我构建的大多数应用程序中,我通常将ActionResult
子类化,以允许我扩展响应Ajax请求的方式
让我们从请求生命周期开始
现在,典型的请求遵循这种生命周期:
- 发送到服务器的Ajax请求
- 服务器对请求进行身份验证
- 401,30倍未授权\重定向。指示无效响应并重定向borwser
- 调用Ajax方法:返回响应代码
- 200:回答可以
- 400:响应无效。(ok可能不是正确的状态代码。但是嘿!)
- 500:需要做更多的测试
400
是一个非常灰色的区域,因为它可能意味着很多事情。您可以考虑使用代码500
或501
,因为它们表明它们是服务器错误。然而,我通常喜欢以不同的方式处理这些错误,因为它们通常意味着更深层次的问题,应该以不同的方式处理
现在,根据上面的模型,我们完成了对服务器的请求,服务器对请求进行消化并做出相应的响应。在典型应用中,如果用户未经授权,ajax请求应返回401 Unauthorized
结果,如果请求的资源已移动,则应返回30x
响应
一旦我们知道请求是有效的并经过身份验证,我们就可以继续使用action方法处理请求。如上所述,我喜欢(是的意见)对ActionResult
类进行子类化,并相应地处理响应。现在这里的计划(这完全是个人的表现)是将标准的[structured]对象返回到java脚本调用方法。当子类化ActionResult
类型时,我们必须实现executesult
方法。这是最终返回给客户机的方法。我个人最喜欢的JSON
框架是JSON.Net
,因此我们必须有一个对包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);
}
}
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));
}
}
这个简单的类有4个属性。其中三个属性定义了对客户端的标准响应。您可以将其视为一个接口,其中每个Ajax请求将包含3个属性
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 };
}
现在,在这个简单的操作方法中,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
状态码,我们点击成功按钮
public AjaxResult DoAjaxWork(AjaxModel model)
{
if (User == null) //do your own user validation tests
{
return new AjaxResult{ StatusCode = 401 };
}
//rest of our method
}
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()
};
}
if (!ModelState.IsValid)
return AjaxResult.Failed(this.ModelState, "There was one or more errors", false);
success: function (data) {
if (!data.Completed) {
alert(data.Message);
return;
}
alert('All Ok Boss')
}