当前位置: 首页 > 面试题库 >

如何在返回PartialView的Ajax调用的控制器操作中处理模型状态错误

戚升
2023-03-14
问题内容

我有一个POST控制器操作,可返回部分视图。一切似乎都很简单。但。我使用加载它$.ajax(),将type设置为html。但是,当我的模型验证失败时,我认为我应该抛出一个带有模型状态错误的错误。但是我的答复总是返回500服务器错误。

如何报告回模型状态错误而又不返回Json并返回任何结果。我仍然想返回可以直接附加到某些HTML元素的局部视图。

编辑

我也想避免返回错误的局部视图。这在客户端上看起来很成功。让客户解析结果以查看其是否真正成功很容易出错。设计人员可能会更改部分视图的输出,仅此一项就会破坏功能。所以我想抛出一个异常,但是将正确的错误消息返回给ajax客户端。


问题答案:

我必须编写两个独立的部分,它们 可以完全按预期 自动运行。

因此,当控制器动作过程成功时,它应该返回部分视图;当事情不正常时,它应该引发带有一些失败细节的错误,以便客户端的事情可以区分成功和失败,而不是总是处理成功。

有两个主要部分可用于实现此目的:

  • *当出现问题时引发的 *自定义异常类 ,因此我们可以区分由于任何原因随时可能发生的一般异常以及与处理相关的错误(最明显的无效模型状态)
  • 异常操作过滤器 ,它捕获我们的自定义异常并根据该异常准备结果;从代码中可以看到,我们的自定义异常将保存有关模型状态错误的信息,因此此过滤器将能够返回自定义HTTP状态代码以及一些文本信息

然后到细节…

外部链接
:所有这些信息(详细说明以及所有代码)也都可以在我的博客上找到。最新的代码更新将始终在那里发布。

自定义异常类

本课提供两件事

  1. 轻松区分模型状态错误和常规异常
  2. 提供一些我以后可以使用的基本功能

此类稍后在我的自定义错误过滤器中使用。

public class ModelStateException : Exception
{
    public Dictionary<string, string> Errors { get; private set; }

    public ModelStateDictionary ModelState { get; private set; }

    public override string Message
    {
        get
        {
            if (this.Errors.Count > 0)
            {
                return this.Errors.First().Value;
            }
            return null;
        }
    }

    private ModelStateException()
    {
        this.Errors = new Dictionary<string, string>();
    }

    public ModelStateException(ModelStateDictionary modelState) : this()
    {
        this.ModelState = modelState;
        if (!modelState.IsValid)
        {
            foreach (KeyValuePair<string, ModelState> state in modelState)
            {
                if (state.Value.Errors.Count > 0)
                {
                    this.Errors.Add(state.Key, state.Value.Errors[0].ErrorMessage);
                }
            }
        }
    }
}

错误过滤器属性

当存在任何模型状态错误时,此属性有助于根据HTTP错误代码将错误返回给客户端。

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class HandleModelStateExceptionAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        if (filterContext.Exception != null && typeof(ModelStateException).IsInstanceOfType(filterContext.Exception) && !filterContext.ExceptionHandled)
        {
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Clear();
            filterContext.HttpContext.Response.ContentEncoding = Encoding.UTF8;
            filterContext.HttpContext.Response.HeaderEncoding = Encoding.UTF8;
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
            filterContext.HttpContext.Response.StatusCode = 400;
            filterContext.HttpContext.Response.StatusDescription = (filterContext.Exception as ModelStateException).Message;
        }
    }
}

之后,我只需用我的属性和voila装饰我的控制器动作。我确实在客户端上得到了错误,代码为400,并且更正了我在过滤器中设置的信息。然后将该信息显示给用户(当与模型状态错误相关时,它会显示用户应修改哪些表单字段以使表单有效的信息)。

[HandleModelStateException]
public ActionResult AddComment(MyModel data)
{
    // check if state is valid
    if (!this.ModelState.IsValid)
    {
        throw new ModelStateException(this.ModelState);
    }
    // get data from store
    return PartialView("Comment", /* store data */ );
}

这使我的代码可以在任何模型状态错误下重复使用,并且这些错误将按原样发送给客户端。

一个问题(现已解决)

但是仍然存在与此代码相关的一个问题。
当我设置了错误操作过滤器, StatusDescription并且该字符串包含某些特殊字符(如Č)时,客户端上就会出现垃圾。除非我使用IE(我使用的是版本8)。FF和CH显示为垃圾。这就是为什么我设置编码但是不起作用。如果有人对此有特殊的解决方法,我将非常乐意听。

如果我在内容本身中返回错误消息,一切都很好。编码正确,我可以显示任何内容。



 类似资料:
  • 我正试图在Rails中通过服务器发送事件来实现流媒体直播。我有一个Rake任务,用于监听文件更改,从而将记录添加到数据库中。一旦添加,我想发送一个SSE到前端。 但是,模型不能将事件发送到前端,这是由控制器负责的。如何告诉我的控制器向数据库中添加了新记录? 到目前为止,我的(坏的)解决方案是:在模型中使用EventBus,在保存后回调,宣布更改并要求控制器侦听以下消息: 我认为我的请求在收到事件之

  • 问题内容: 假设我有以下jQuery AJAX调用: 现在,当进行此AJAX调用时,我希望服务器端代码通过一些错误处理检查来运行(例如,用户是否仍在登录,他们是否有权使用此调用,数据是否有效,等等)。如果检测到错误,如何将错误消息冒泡回客户端? 我最初的想法是返回一个带有两个字段的JSON对象:error和errorMessage。然后将在jQuery AJAX调用中检查以下字段: 这对我来说有点

  • 问题内容: 因此,我让我的JavaScript进行了Ajax调用,但是在控制器中,我不知道该怎么做才能将某些内容输出回JavaScript。 我收到错误消息是因为没有视图,但是显然没有视图,所以该怎么办? 问题答案: 为此,假设您要在数组中输出变量,然后使用方法将该数组传递给视图,然后创建一个view 。在该视图文件中,放完后可以使用,它应该输出json。 通用代码… /Controllers/M

  • 问题内容: 我试图通过传递一些参数的AJAX调用MVC控制器动作。 我有时 在此应用程序中执行此操作 ,并且效果很好。 我不知道为什么只有 这一个 无效。 这是我的控制器方法: 提醒一下,我正在做我在其他Ajax调用中所做的事情,但是特别是 只有这一条 不起作用。 有人有什么主意吗? 问题答案: 始终使用或html helper方法来构建操作方法的url。无论您当前的页面/路径如何,它都会正确构建

  • 问题内容: 我正在将数据从javascript应用程序发送到MVC5控制器,但是,当数据提交到Submit controller操作时,它永远不会被调用。我有一些非常简单的映射器,它们创建以下JSON对象: 然后,我使用以下代码发送数据: 我的控制器代码如下: 我有以下问题: 但是,从不会调用Submit,但是,如果我注释掉了控制器参数,那么它将被调用,这是为什么呢? 从上面看来,控制器框架似乎无

  • 问题内容: 目标: 我想让我的用户在我的网页上下载文件。我想打开一个新窗口,并在其中显示或下载文件。 我的实现: 但是,此文件首先必须在服务器端生成,这可能需要一段时间。当用户单击按钮下载文件时,我进行了ajax调用并显示等待动画,直到得到响应为止。处理该调用的控制器操作将生成文件(PDF)并返回FileResult。现在,在javascript中我的ajax调用的成功功能中,我得到了文件数据。