使用JQuery Ajax进行MVC5错误处理

时间:2022-11-29 13:58:40

Let's say I have a standard form setup with a ViewModel and validation like this.

假设我有一个带有ViewModel的标准表单设置和这样的验证。

ViewModel

public class EditEventViewModel
{
    public int EventID { get; set; }
    [StringLength(10)]
    public string EventName { get; set; }
}

Form in the View

视图中的表单

@using (Html.BeginForm(null, null, FormMethod.Post, new {id="editEventForm"}))
{
    @Html.AntiForgeryToken()

    @Html.LabelFor(model => model.EventName)
    @Html.EditorFor(model => model.EventName)
    @Html.ValidationMessageFor(model => model.EventName)
}

Controller

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "EventName")] EventViewModel model)
{
    //Get the specific record to be updated
    var eventRecord = (from e in db.Event
                       where e.EventID == model.EventID
                       select e).SingleOrDefault();

    //Update the data
    if (ModelState.IsValid)
    {
        eventRecord.EventName = model.EventName;
        db.SaveChanges();            
    }

    return RedirectToAction("Index");
}

Now, if I do a regular form submit and enter an EventName with a string length over 10, the model error will be triggered and I'll be notified in the validation message in the view.

现在,如果我执行常规表单提交并输入字符串长度超过10的EventName,将触发模型错误,并在视图中的验证消息中通知我。

But, I prefer to submit my forms with JQuery AJax like this.

但是,我更喜欢像这样用JQuery AJax提交表单。

$.ajax({
    type: "POST",
    url: "/EditEvent/Edit",
    data: $('#editEventForm').serialize(),
    success: function () {

    },
    error: function () {

    }
});

With this way, I add some javascript on the client side to validate before the submit, but I'd still like the data annotations in the ViewModel as a backup. When this reaches the controller, it's still checked with if (ModelState.IsValid). If it's not valid, then the data is not written to the database, just as designed.

通过这种方式,我在客户端添加一些javascript以在提交之前进行验证,但我仍然希望ViewModel中的数据注释作为备份。当它到达控制器时,仍然使用if(ModelState.IsValid)进行检查。如果它无效,则数据不会像设计的那样写入数据库。

Now, I want to know what I can do if the ModelState is not valid, when posting with JQuery. This will not trigger the regular validation, so what can I do to send back information that an error has occurred?

现在,我想知道当使用JQuery发布时ModelState无效时我能做些什么。这不会触发常规验证,因此我该怎么做才能发回错误信息?

if (ModelState.IsValid)
{
    eventRecord.EventName = model.EventName;
    db.SaveChanges();            
}
else
{
    //What can I do here to signify an error?
}

Update With Further Information

更新更多信息

I already have custom errors set up in Web.config

我已经在Web.config中设置了自定义错误

<customErrors mode="On">

That routes errors to the Views/Shared/Error.cshtml file, where I'm outputting information about the error that got the request there. Is there anyway my model state error (or any error) in the controller could be sent here?

这会将错误路由到Views / Shared / Error.cshtml文件,在那里我输出有关在那里获得请求的错误的信息。无论如何,我的模型状态错误(或任何错误)可以在这里发送?

@model System.Web.Mvc.HandleErrorInfo

@{
    Layout = null;
    ViewBag.Title = "Error";
}

<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>

<p>
    Controller: @Model.ControllerName   <br />
    Action: @Model.ActionName           <br />
    Exception: @Model.Exception.Message
</p>

UPDATE again

Here's another update working with pieces of all of the responses. In my controller, I put this in the else statement throw new HttpException(500, "ModelState Invalid"); (else - meaning that the ModelState is not valid)

这是另一个更新处理所有响应的部分。在我的控制器中,我把它放在else语句中抛出新的HttpException(500,“ModelState Invalid”); (否则 - 意味着ModelState无效)

That triggers my custom errors in Web.config to send to the Views/Shared/Error.cshtml, (kind of) but this only shows up in FireBug like this. The actual page doesn't go anywhere. Any idea how I get this on the parent page? If this doesn't make sense, I've been using the setup described here, to send to my custom error page. The fact that this is an AJAX call is making this work a little differently.

这会在Web.config中触发我的自定义错误以发送到Views / Shared / Error.cshtml,(种类),但这只会在FireBug中显示出来。实际的页面不会去任何地方。知道如何在父页面上得到这个吗?如果这没有意义,我一直在使用这里描述的设置,发送到我的自定义错误页面。事实上这是一个AJAX调用,这使得这项工作略有不同。

使用JQuery Ajax进行MVC5错误处理

6 个解决方案

#1


4  

Right now, your controller just swallows any errors - if the model isn't valid, it just doesn't save and never gives any feedback to the caller. You could fix this and have it return an error to jQuery by actually returning an error:

现在,您的控制器只是吞下任何错误 - 如果模型无效,它只是不保存,并且从不向调用者提供任何反馈。您可以通过实际返回错误来修复此问题并让它向jQuery返回错误:

return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Some meaningful message");

Lots of options about what you want to handle and how much detail to return, but the main point is your controller should provide a response that is appropriate for the actual action it performed.

关于你想要处理什么以及要返回多少细节的许多选项,但重点是你的控制器应该提供适合它所执行的实际操作的响应。

UPDATE

In response to your "Update Again" section - I wouldn't return a 500 - this means "internal server error". If you are going to return an error, a 400 (bad request) is probably more appropriate. Regardless, the problem you have with your ajax call is that it is receiving the error response from the web server (not your main browser window). If I had to guess, the error is being handled server-side and you are jquery is receiving the html response from your custom error.

为了回应你的“再次更新”部分 - 我不会返回500 - 这意味着“内部服务器错误”。如果要返回错误,则400(错误请求)可能更合适。无论如何,您对ajax调用的问题是它从Web服务器(而不是您的主浏览器窗口)收到错误响应。如果我不得不猜测,错误是在服务器端处理的,你是jquery从你的自定义错误接收html响应。

If you are going to leave the automatic error handling in place, you should probably only use it for unhandled errors. Therefore, in your controller, you would handle the invalid model by returning an non-error response indicating this state (I think someone else mentioned a json response). Then, all responses would be successful, but the content would tell your application how to behave (redirect appropriately, etc...).

如果您要保留自动错误处理,则应该仅将其用于未处理的错误。因此,在您的控制器中,您将通过返回指示此状态的非错误响应来处理无效模型(我认为其他人提到了json响应)。然后,所有响应都会成功,但内容会告诉您的应用程序如何表现(适当地重定向等等)。

#2


2  

Because you want the error content back, I would suggest returning a JSON response (the alternative is a partial view, but that would mean making your JS use delegated handlers, resetting the form validation, etc.). In this case you'll want to detect and return JSON if the POST is AJAX and return a normal view/redirect otherwise. If all validation should be done client-side and it's ok to not have the error text, you could probably return an exception result and use the error handler for the .ajax() call to update the page. I've found that browser support for getting the response text on errors is inconsistent, though, so if you want the actual errors, you'll want to return a 200 OK response with the messages in JSON. My choice would probably depend on the exact use case - for example if there were several errors that I could only detect server-side I'd probably use an OK response with error content. If there were only a few or all errors should be handled client-side, then I'd go the exception route.

因为你想要回复错误内容,我建议你返回一个JSON响应(替代是部分视图,但这意味着让你的JS使用委托处理程序,重置表单验证等)。在这种情况下,如果POST是AJAX,您将需要检测并返回JSON,否则返回普通视图/重定向。如果所有验证都应在客户端完成,并且没有错误文本,则可能会返回异常结果并使用.ajax()调用的错误处理程序来更新页面。我发现浏览器支持获取错误的响应文本是不一致的,所以如果你想要实际的错误,你会想要用JSON中的消息返回200 OK响应。我的选择可能取决于具体的用例 - 例如,如果有几个错误我只能检测到服务器端,我可能会使用带有错误内容的OK响应。如果只有少数或全部错误应该在客户端处理,那么我将进入异常路由。

The custom error handler shouldn't be used or needed for this.

不应使用或需要自定义错误处理程序。

MVC with status result

具有状态结果的MVC

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "EventName")] EventViewModel model)
{
    //Get the specific record to be updated
    var eventRecord = (from e in db.Event
                       where e.EventID == model.EventID
                       select e).SingleOrDefault();

    if (eventRecord == null)
    {
        if (Request.IsAjaxRequest())
        {
            return new HttpStatusCodeResult(HttpStatusCode.NotFound, "Event not found.");
        }

        ModelState.AddModelError("EventID", "Event not found.");
    }

    //Update the data
    if (ModelState.IsValid)
    {
        eventRecord.EventName = model.EventName;
        db.SaveChanges();            

        if (Request.IsAjaxRequest())
        {
            return Json(new { Url = Url.Action("Index") });
        }

        return RedirectToAction("Index");
    }

    if (Request.IsAjaxRequest())
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest, /* ... collate error messages ... */ "" );
    }

    return View(model);
}

Example JS with status result

带状态结果的示例JS

$.ajax({
   type: "POST",
   url: "/EditEvent/Edit",
   data: $('#editEventForm').serialize(),
})
.done(function(result) {
     window.location = result.Url;
})
.fail(function(xhr) {
    switch (xhr.status) {  // examples, extend as needed
       case 400:
          alert('some data was invalid. please check for errors and resubmit.');
          break;
       case 404:
          alert('Could not find event to update.');
          break;
    }     
});

MVC with error content

MVC有错误内容

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "EventName")] EventViewModel model)
{
    //Get the specific record to be updated
    var eventRecord = (from e in db.Event
                       where e.EventID == model.EventID
                       select e).SingleOrDefault();

    if (eventRecord == null)
    {
        if (Request.IsAjaxRequest())
        {
            return Json(new { Status = false, Message = "Event not found." });
        }

        ModelState.AddModelError("EventID", "Event not found.");
    }

    //Update the data
    if (ModelState.IsValid)
    {
        eventRecord.EventName = model.EventName;
        db.SaveChanges();            

        if (Request.IsAjaxRequest())
        {
            return Json(new { Status = true, Url = Url.Action("Index") });
        }

        return RedirectToAction("Index");
    }

    if (Request.IsAjaxRequest())
    {
        return Json(new 
        {
            Status = false,
            Message = "Invalid data",
            Errors = ModelState.Where((k,v) => v.Errors.Any())
                               .Select((k,v) => new
                               {
                                   Property = k,
                                   Messages = v.Select(e => e.ErrorMessage)
                                               .ToList()
                               })
                               .ToList()
        });
    }

    return View(model);
}

Example JS with error content

示例JS包含错误内容

$.ajax({
   type: "POST",
   url: "/EditEvent/Edit",
   data: $('#editEventForm').serialize(),
})
.done(function(result) {
     if (result.Status)
     {
         window.Location = result.Url;
     }
     // otherwise loop through errors and show the corresponding validation messages
})
.fail(function(xhr) {
    alert('A server error occurred.  Please try again later.');     
});

#3


1  

If you're creating a RESTful service you should return an appropriate http code that indicates the data wasn't saved. Probably a 400.

如果您正在创建RESTful服务,则应返回适当的http代码,以指示未保存数据。可能是400。

Otherwise I would say return whatever makes sense to you and check for that value on the client side to determine if the call failed.

否则我会说返回任何有意义的东西并在客户端检查该值以确定呼叫是否失败。

#4


0  

What you need is a little change to your code. Because you are using ajax communication to send the data to the server you don't need to use form posting. Instead you can change the return type of your action method to JsonResult and use Json() method to send the result of the data processing.

您需要的是对代码的一点改动。因为您使用ajax通信将数据发送到服务器,所以您不需要使用表单发布。相反,您可以将操作方法​​的返回类型更改为JsonResult,并使用Json()方法发送数据处理的结果。

[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Edit([Bind(Include = "EventName")] EventViewModel model)
{
    //Get the specific record to be updated
    var eventRecord = (from e in db.Event
                   where e.EventID == model.EventID
                   select e).SingleOrDefault();

    //Update the data
    if (ModelState.IsValid)
    {
        eventRecord.EventName = model.EventName;
        db.SaveChanges();  
        return Json(new {Result=true});          
    } 
    else
    {
        return Json(new {Result=false});
    }
}

Now you can use this action method for data processing.

现在,您可以使用此操作方法进行数据处理。

$.ajax({
type: "POST",
url: "/EditEvent/Edit",
data: $('#editEventForm').serialize(),
success: function (d) {
   var r = JSON.parse(d);
   if(r.Result == 'true'){
       //Wohoo its valid data and processed. 
       alert('success');
   }
   else{
       alert('not success');
       location.href = 'Index';
   }
},
error: function () {

}

});

#5


0  

You can send back an error message in the viewbag with a message about the items causing the error:

您可以在viewbag中发回一条错误消息,其中包含有关导致错误的项目的消息:

foreach (ModelState modelState in ViewData.ModelState.Values)
            {
                foreach (ModelError error in modelState.Errors)
                {
                //Add the error.Message to a local variable
                }
            }

ViewBag.ValidationErrorMessage = //the error message

#6


0  

For my unique situation, I decided to take a different approach. Since I have custom errors set up in Web.config, I'm able to handle any non-Ajax request errors automatically and have that information sent to Views/Shared/Error.cshtml. Suggested reading for that here.

对于我的独特情况,我决定采取不同的方法。由于我在Web.config中设置了自定义错误,因此我能够自动处理任何非Ajax请求错误,并将该信息发送到Views / Shared / Error.cshtml。建议在这里阅读。

I'm also able to handle application errors outside of MVC using the methods described here.

我还能够使用此处描述的方法处理MVC之外的应用程序错误。

I have also installed ELMAH to log any errors in my SQL database. Information about that here and here.

我还安装了ELMAH来记录我的SQL数据库中的任何错误。关于这里和这里的信息。

My original intention was to catch errors in the controllers the same way when I send an Ajax request, which I guess you can't do.

我的初衷是在发送Ajax请求时以相同的方式捕获控制器中的错误,我猜你做不到。

When I post a form in my application, the form is first checked on the client side with javascript validation. I know which fields I don't want to be blank and how many characters and what type of data to accept. If I find a field not matching that criteria, I send information about that error to a JQuery dialog to display that information to the user. If all of my criteria is met, then I finally submit the form to the controller and action.

当我在我的应用程序中发布表单时,首先在客户端使用javascript验证检查表单。我知道哪些字段我不想空白以及要接受多少个字符和哪种类型的数据。如果我发现某个字段与该条件不匹配,我会将有关该错误的信息发送到JQuery对话框,以向用户显示该信息。如果满足我的所有条件,那么我最终将表单提交给控制器和操作。

For this reason, I've decided to throw an exception in the controller if an error occurs. If the client-side validation finds no problem with the data being submitted and the controller still errors out, then I definitely want that error logged. Keep in mind that I'm also setting the data annotations on the ViewModel as a backup to the client-side validation. Throwing an exception will trigger the JQuery error function and will trigger ELMAH to log this error.

出于这个原因,如果发生错误,我决定在控制器中抛出异常。如果客户端验证发现提交的数据没有问题并且控制器仍然出错,那么我肯定希望记录该错误。请记住,我还将ViewModel上的数据注释设置为客户端验证的备份。抛出异常将触发JQuery错误函数,并将触发ELMAH记录此错误。

My controller would look like this.

我的控制器看起来像这样。

// POST: EditEvent/Edit
//Method set to void because it does not return a value
[HttpPost]
[ValidateAntiForgeryToken]
public void Edit([Bind(Include = "EventID, EventName")] EditEventViewModel model)
{
    //Get the specific record to be updated
    var eventRecord = (from e in db.Event
                       where e.EventID == model.EventID
                       select e).SingleOrDefault();

    //******************************************************************//
    //*** Not really sure if exceptions like this below need to be    **//
    //*** manually called because they can really bog down the code   **//
    //*** if you're checking every query.  Errors caused from         **//
    //*** this being null will still trigger the Ajax error functiton **//
    //*** and get caught by the ELMAH logger, so I'm not sure if I    **//
    //*** should waste my time putting all of these in.  Thoughts?    **//
    //******************************************************************//


    //If the record isn't returned from the query
    if (eventRecord == null)
    {
        //Triggers JQuery Ajax Error function
        //Triggers ELMAH to log the error
        throw new HttpException(400, "Event Record Not Found");
    }

    //If there's something wrong with the ModelState
    if (!ModelState.IsValid)
    {
        //Triggers JQuery Ajax Error function
        //Triggers ELMAH to log the error
        throw new HttpException(400, "ModelState Invalid");
    }

    //Update the data if there are no exceptions
    eventRecord.EventName = model.EventName;
    db.SaveChanges();
}

The ViewModel with data annotations looks like this.

带有数据注释的ViewModel如下所示。

public class EditEventViewModel
{
    public int EventID { get; set; } 
    [Required]
    [StringLength(10)]
    public string EventName { get; set; }
}

The JQuery Ajax call looks like this

JQuery Ajax调用看起来像这样

$.ajax({
    type: "POST",
    url: "/EditEvent/Edit",
    data: $('#editEventForm').serialize(),
    success: function () {
        //Triggered if everything is fine and data was written
    },
    error: function () {
        //Triggered with the thrown exceptions in the controller
        //I will probably just notify the user on screen here that something happened.
        //Specific details are stored in the ELMAH log, the user doesn't need that information.
    }
});

I used information from everyone's posts. Thanks to everyone for helping.

我使用了每个人帖子中的信息。感谢大家的帮助。

#1


4  

Right now, your controller just swallows any errors - if the model isn't valid, it just doesn't save and never gives any feedback to the caller. You could fix this and have it return an error to jQuery by actually returning an error:

现在,您的控制器只是吞下任何错误 - 如果模型无效,它只是不保存,并且从不向调用者提供任何反馈。您可以通过实际返回错误来修复此问题并让它向jQuery返回错误:

return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Some meaningful message");

Lots of options about what you want to handle and how much detail to return, but the main point is your controller should provide a response that is appropriate for the actual action it performed.

关于你想要处理什么以及要返回多少细节的许多选项,但重点是你的控制器应该提供适合它所执行的实际操作的响应。

UPDATE

In response to your "Update Again" section - I wouldn't return a 500 - this means "internal server error". If you are going to return an error, a 400 (bad request) is probably more appropriate. Regardless, the problem you have with your ajax call is that it is receiving the error response from the web server (not your main browser window). If I had to guess, the error is being handled server-side and you are jquery is receiving the html response from your custom error.

为了回应你的“再次更新”部分 - 我不会返回500 - 这意味着“内部服务器错误”。如果要返回错误,则400(错误请求)可能更合适。无论如何,您对ajax调用的问题是它从Web服务器(而不是您的主浏览器窗口)收到错误响应。如果我不得不猜测,错误是在服务器端处理的,你是jquery从你的自定义错误接收html响应。

If you are going to leave the automatic error handling in place, you should probably only use it for unhandled errors. Therefore, in your controller, you would handle the invalid model by returning an non-error response indicating this state (I think someone else mentioned a json response). Then, all responses would be successful, but the content would tell your application how to behave (redirect appropriately, etc...).

如果您要保留自动错误处理,则应该仅将其用于未处理的错误。因此,在您的控制器中,您将通过返回指示此状态的非错误响应来处理无效模型(我认为其他人提到了json响应)。然后,所有响应都会成功,但内容会告诉您的应用程序如何表现(适当地重定向等等)。

#2


2  

Because you want the error content back, I would suggest returning a JSON response (the alternative is a partial view, but that would mean making your JS use delegated handlers, resetting the form validation, etc.). In this case you'll want to detect and return JSON if the POST is AJAX and return a normal view/redirect otherwise. If all validation should be done client-side and it's ok to not have the error text, you could probably return an exception result and use the error handler for the .ajax() call to update the page. I've found that browser support for getting the response text on errors is inconsistent, though, so if you want the actual errors, you'll want to return a 200 OK response with the messages in JSON. My choice would probably depend on the exact use case - for example if there were several errors that I could only detect server-side I'd probably use an OK response with error content. If there were only a few or all errors should be handled client-side, then I'd go the exception route.

因为你想要回复错误内容,我建议你返回一个JSON响应(替代是部分视图,但这意味着让你的JS使用委托处理程序,重置表单验证等)。在这种情况下,如果POST是AJAX,您将需要检测并返回JSON,否则返回普通视图/重定向。如果所有验证都应在客户端完成,并且没有错误文本,则可能会返回异常结果并使用.ajax()调用的错误处理程序来更新页面。我发现浏览器支持获取错误的响应文本是不一致的,所以如果你想要实际的错误,你会想要用JSON中的消息返回200 OK响应。我的选择可能取决于具体的用例 - 例如,如果有几个错误我只能检测到服务器端,我可能会使用带有错误内容的OK响应。如果只有少数或全部错误应该在客户端处理,那么我将进入异常路由。

The custom error handler shouldn't be used or needed for this.

不应使用或需要自定义错误处理程序。

MVC with status result

具有状态结果的MVC

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "EventName")] EventViewModel model)
{
    //Get the specific record to be updated
    var eventRecord = (from e in db.Event
                       where e.EventID == model.EventID
                       select e).SingleOrDefault();

    if (eventRecord == null)
    {
        if (Request.IsAjaxRequest())
        {
            return new HttpStatusCodeResult(HttpStatusCode.NotFound, "Event not found.");
        }

        ModelState.AddModelError("EventID", "Event not found.");
    }

    //Update the data
    if (ModelState.IsValid)
    {
        eventRecord.EventName = model.EventName;
        db.SaveChanges();            

        if (Request.IsAjaxRequest())
        {
            return Json(new { Url = Url.Action("Index") });
        }

        return RedirectToAction("Index");
    }

    if (Request.IsAjaxRequest())
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest, /* ... collate error messages ... */ "" );
    }

    return View(model);
}

Example JS with status result

带状态结果的示例JS

$.ajax({
   type: "POST",
   url: "/EditEvent/Edit",
   data: $('#editEventForm').serialize(),
})
.done(function(result) {
     window.location = result.Url;
})
.fail(function(xhr) {
    switch (xhr.status) {  // examples, extend as needed
       case 400:
          alert('some data was invalid. please check for errors and resubmit.');
          break;
       case 404:
          alert('Could not find event to update.');
          break;
    }     
});

MVC with error content

MVC有错误内容

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "EventName")] EventViewModel model)
{
    //Get the specific record to be updated
    var eventRecord = (from e in db.Event
                       where e.EventID == model.EventID
                       select e).SingleOrDefault();

    if (eventRecord == null)
    {
        if (Request.IsAjaxRequest())
        {
            return Json(new { Status = false, Message = "Event not found." });
        }

        ModelState.AddModelError("EventID", "Event not found.");
    }

    //Update the data
    if (ModelState.IsValid)
    {
        eventRecord.EventName = model.EventName;
        db.SaveChanges();            

        if (Request.IsAjaxRequest())
        {
            return Json(new { Status = true, Url = Url.Action("Index") });
        }

        return RedirectToAction("Index");
    }

    if (Request.IsAjaxRequest())
    {
        return Json(new 
        {
            Status = false,
            Message = "Invalid data",
            Errors = ModelState.Where((k,v) => v.Errors.Any())
                               .Select((k,v) => new
                               {
                                   Property = k,
                                   Messages = v.Select(e => e.ErrorMessage)
                                               .ToList()
                               })
                               .ToList()
        });
    }

    return View(model);
}

Example JS with error content

示例JS包含错误内容

$.ajax({
   type: "POST",
   url: "/EditEvent/Edit",
   data: $('#editEventForm').serialize(),
})
.done(function(result) {
     if (result.Status)
     {
         window.Location = result.Url;
     }
     // otherwise loop through errors and show the corresponding validation messages
})
.fail(function(xhr) {
    alert('A server error occurred.  Please try again later.');     
});

#3


1  

If you're creating a RESTful service you should return an appropriate http code that indicates the data wasn't saved. Probably a 400.

如果您正在创建RESTful服务,则应返回适当的http代码,以指示未保存数据。可能是400。

Otherwise I would say return whatever makes sense to you and check for that value on the client side to determine if the call failed.

否则我会说返回任何有意义的东西并在客户端检查该值以确定呼叫是否失败。

#4


0  

What you need is a little change to your code. Because you are using ajax communication to send the data to the server you don't need to use form posting. Instead you can change the return type of your action method to JsonResult and use Json() method to send the result of the data processing.

您需要的是对代码的一点改动。因为您使用ajax通信将数据发送到服务器,所以您不需要使用表单发布。相反,您可以将操作方法​​的返回类型更改为JsonResult,并使用Json()方法发送数据处理的结果。

[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Edit([Bind(Include = "EventName")] EventViewModel model)
{
    //Get the specific record to be updated
    var eventRecord = (from e in db.Event
                   where e.EventID == model.EventID
                   select e).SingleOrDefault();

    //Update the data
    if (ModelState.IsValid)
    {
        eventRecord.EventName = model.EventName;
        db.SaveChanges();  
        return Json(new {Result=true});          
    } 
    else
    {
        return Json(new {Result=false});
    }
}

Now you can use this action method for data processing.

现在,您可以使用此操作方法进行数据处理。

$.ajax({
type: "POST",
url: "/EditEvent/Edit",
data: $('#editEventForm').serialize(),
success: function (d) {
   var r = JSON.parse(d);
   if(r.Result == 'true'){
       //Wohoo its valid data and processed. 
       alert('success');
   }
   else{
       alert('not success');
       location.href = 'Index';
   }
},
error: function () {

}

});

#5


0  

You can send back an error message in the viewbag with a message about the items causing the error:

您可以在viewbag中发回一条错误消息,其中包含有关导致错误的项目的消息:

foreach (ModelState modelState in ViewData.ModelState.Values)
            {
                foreach (ModelError error in modelState.Errors)
                {
                //Add the error.Message to a local variable
                }
            }

ViewBag.ValidationErrorMessage = //the error message

#6


0  

For my unique situation, I decided to take a different approach. Since I have custom errors set up in Web.config, I'm able to handle any non-Ajax request errors automatically and have that information sent to Views/Shared/Error.cshtml. Suggested reading for that here.

对于我的独特情况,我决定采取不同的方法。由于我在Web.config中设置了自定义错误,因此我能够自动处理任何非Ajax请求错误,并将该信息发送到Views / Shared / Error.cshtml。建议在这里阅读。

I'm also able to handle application errors outside of MVC using the methods described here.

我还能够使用此处描述的方法处理MVC之外的应用程序错误。

I have also installed ELMAH to log any errors in my SQL database. Information about that here and here.

我还安装了ELMAH来记录我的SQL数据库中的任何错误。关于这里和这里的信息。

My original intention was to catch errors in the controllers the same way when I send an Ajax request, which I guess you can't do.

我的初衷是在发送Ajax请求时以相同的方式捕获控制器中的错误,我猜你做不到。

When I post a form in my application, the form is first checked on the client side with javascript validation. I know which fields I don't want to be blank and how many characters and what type of data to accept. If I find a field not matching that criteria, I send information about that error to a JQuery dialog to display that information to the user. If all of my criteria is met, then I finally submit the form to the controller and action.

当我在我的应用程序中发布表单时,首先在客户端使用javascript验证检查表单。我知道哪些字段我不想空白以及要接受多少个字符和哪种类型的数据。如果我发现某个字段与该条件不匹配,我会将有关该错误的信息发送到JQuery对话框,以向用户显示该信息。如果满足我的所有条件,那么我最终将表单提交给控制器和操作。

For this reason, I've decided to throw an exception in the controller if an error occurs. If the client-side validation finds no problem with the data being submitted and the controller still errors out, then I definitely want that error logged. Keep in mind that I'm also setting the data annotations on the ViewModel as a backup to the client-side validation. Throwing an exception will trigger the JQuery error function and will trigger ELMAH to log this error.

出于这个原因,如果发生错误,我决定在控制器中抛出异常。如果客户端验证发现提交的数据没有问题并且控制器仍然出错,那么我肯定希望记录该错误。请记住,我还将ViewModel上的数据注释设置为客户端验证的备份。抛出异常将触发JQuery错误函数,并将触发ELMAH记录此错误。

My controller would look like this.

我的控制器看起来像这样。

// POST: EditEvent/Edit
//Method set to void because it does not return a value
[HttpPost]
[ValidateAntiForgeryToken]
public void Edit([Bind(Include = "EventID, EventName")] EditEventViewModel model)
{
    //Get the specific record to be updated
    var eventRecord = (from e in db.Event
                       where e.EventID == model.EventID
                       select e).SingleOrDefault();

    //******************************************************************//
    //*** Not really sure if exceptions like this below need to be    **//
    //*** manually called because they can really bog down the code   **//
    //*** if you're checking every query.  Errors caused from         **//
    //*** this being null will still trigger the Ajax error functiton **//
    //*** and get caught by the ELMAH logger, so I'm not sure if I    **//
    //*** should waste my time putting all of these in.  Thoughts?    **//
    //******************************************************************//


    //If the record isn't returned from the query
    if (eventRecord == null)
    {
        //Triggers JQuery Ajax Error function
        //Triggers ELMAH to log the error
        throw new HttpException(400, "Event Record Not Found");
    }

    //If there's something wrong with the ModelState
    if (!ModelState.IsValid)
    {
        //Triggers JQuery Ajax Error function
        //Triggers ELMAH to log the error
        throw new HttpException(400, "ModelState Invalid");
    }

    //Update the data if there are no exceptions
    eventRecord.EventName = model.EventName;
    db.SaveChanges();
}

The ViewModel with data annotations looks like this.

带有数据注释的ViewModel如下所示。

public class EditEventViewModel
{
    public int EventID { get; set; } 
    [Required]
    [StringLength(10)]
    public string EventName { get; set; }
}

The JQuery Ajax call looks like this

JQuery Ajax调用看起来像这样

$.ajax({
    type: "POST",
    url: "/EditEvent/Edit",
    data: $('#editEventForm').serialize(),
    success: function () {
        //Triggered if everything is fine and data was written
    },
    error: function () {
        //Triggered with the thrown exceptions in the controller
        //I will probably just notify the user on screen here that something happened.
        //Specific details are stored in the ELMAH log, the user doesn't need that information.
    }
});

I used information from everyone's posts. Thanks to everyone for helping.

我使用了每个人帖子中的信息。感谢大家的帮助。