Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在发送到控制器时使用js将modelstate错误返回到视图_Javascript_C#_.net - Fatal编程技术网

Javascript 在发送到控制器时使用js将modelstate错误返回到视图

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) {

我将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函数。我想在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')
    }