如何处理在AJAX调用的控制器动作,返回一个PartialView模型状态错误 [英] How to handle model state errors in ajax-invoked controller action that returns a PartialView

查看:289
本文介绍了如何处理在AJAX调用的控制器动作,返回一个PartialView模型状态错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个POST控制器动作,返回的局部视图。一切似乎很容易。但。我加载它使用 $。阿贾克斯(),设置类型为 HTML 。但是,当我的模型验证失败,我想我应该只是把与模型状态错误的错误。但是,我的回答总是返回500服务器错误。

I have a POST controller action that returns a partial view. Everything seems really easy. but. I load it using $.ajax(), setting type as html. But when my model validation fails I thought I should just throw an error with model state errors. But my reply always returns 500 Server error.

我怎么能不返回JSON与任何结果汇报模型的状态误差。我仍想返回局部视图,我可以直接附加到某些HTML元素。

How can I report back model state errors without returning Json with whatever result. I would still like to return partial view that I can directly append to some HTML element.

我也想避免返回错误的局部视图。这看起来就像客户机上的成功。让客户端解析结果,看它是否是一个真正的成功是容易出错。设计人员可以改变局部视图输出仅此一点会破坏功能。所以我想抛出一个异常,而是用正确的错误信息返回给Ajax客户端。

I would also like to avoid returning error partial view. This would look like a success on the client. Having the client parse the result to see whether it's an actual success is prone to errors. Designers may change the partial view output and this alone would break the functionality. So I want to throw an exception, but with the correct error message returned to the ajax client.

推荐答案

我不得不写两个独立的部件,自动地工作了应有

Solution

I had to write two separate parts that automagically work exactly as intended.

因此​​,它应该返回一个局部视图时,控制器操作过程成功,它应该抛出一个错误与失败的一些细节时,事情并不确定,所以在客户端的东西会区分处理总是成功的成功和失败,而不是。

So it should return a partial view when controller action process succeeds and it should throw an error with some failure details when things are not ok so things on the client side would distinguish success as well as failure instead of always handling success.

有,用于实现此两个主要部分:

There are two major parts that are used to achieve this:

  • 自定义异常类出问题的时候,所以我们可以在可能发生的任何时间,任何原因和错误涉及到我们处理(最明显的是无效的模型的状态)一般例外区分时引发
  • 异常行为过滤器映入我们的自定义异常和prepares结果基于该异常;正如你从code看到,我们的自定义异常将持有约模型状态的错误信息,因此这种过滤器将能够返回的自定义HTTP状态code,以及一些文本信息
  • A custom exception class that is thrown when something goes wrong so we can distinguish between general exceptions that can happen any time for whatever reason and errors related to our processing (most notably invalid model state)
  • Exception action filter that catches our custom exception and prepares result based on that exception; As you'll see from the code, our custom exception will hold information about model state errors so this filter will be able to return custom HTTP status code as well some textual information

在细节然后...

外部链接:所有这些信息(详细的说明,以及所有的code),也可在我的博客。最新code的更新总是会发表有

External link: All this information (detailed explanation as well as all the code) is also available on my blog. Latest code updates will always be published there.

这个类提供了两件事情

  1. 请简单区分常规异常模型的状态误差
  2. 提供了一些基本的功能后,我可以使用

本类是后来在我的自定义错误过滤器中使用。

This class is later used in my custom error filter.

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错误codeS方面的错误返回给客户端的时候有任何模型状态错误。

Error filter attribute

This attribute helps returning errors to the client in terms of HTTP error codes when there are any model state errors.

[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;
        }
    }
}

在这之后,我简单的装饰我的控制器行动,我的属性,瞧。我没有得到与code 400和正确的信息在客户端,我在我的过滤器设置上的错误。然后将这些信息显示给用户(当它涉及到模型状态错误,它会显示该表单字段的用户应修改,以使窗体有效信息)。

After that, I simply decorated my controller action with my attribute and voila. I did get errors on the client with code 400 and correct information that I set in my filter. This information is then displayed to the user (when it's related to model state errors it displays information which form fields user should amend to make the form valid).

[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 */ );
}

这让我的code可重复使用的任何模型状态错误,这些将被发送到客户端,因为他们应该。

This makes my code reusable with any model state errors and those will get sent to the client as they should.

<打击>但是还是有一个问题与此相关的code。当我的错误动作过滤器集状态说明和字符串中包含一些特殊的字符,如C,我得到的垃圾在客户端上。除非我用IE浏览器(我使用的是第8版)。 FF和CH显示垃圾。这就是为什么我设置编码,但它不工作。如果任何人有一种解决方法的特殊性,我会多高兴在听。
如果我返回的错误信息内容本身,一切都很好。编码是正确的,我可以显示任何我想要的。

But there's still one issue related to this code. When my error action filter sets StatusDescription and that string contains some special characters like Č, I get rubbish on the client. Unless I use IE (I'm using version 8). FF and CH display rubbish. That's why I set encodings but it doesn't work. If anyone has a workaround for this particularity I'd be more than glad to listen in.
If I return error message in content itself, everything's fine. Encoding is correct and I can display whatever I want.

这篇关于如何处理在AJAX调用的控制器动作,返回一个PartialView模型状态错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆