解
我必须编写两个独立的部分,它们 可以完全按预期 自动运行。
因此,当控制器动作过程成功时,它应该返回部分视图;当事情不正常时,它应该引发带有一些失败细节的错误,以便客户端的事情可以区分成功和失败,而不是总是处理成功。
有两个主要部分可用于实现此目的:
- *当出现问题时引发的 *自定义异常类 ,因此我们可以区分由于任何原因随时可能发生的一般异常以及与处理相关的错误(最明显的无效模型状态)
- 异常操作过滤器 ,它捕获我们的自定义异常并根据该异常准备结果;从代码中可以看到,我们的自定义异常将保存有关模型状态错误的信息,因此此过滤器将能够返回自定义HTTP状态代码以及一些文本信息
然后到细节…
外部链接
:所有这些信息(详细说明以及所有代码)也都可以在我的博客上找到。最新的代码更新将始终在那里发布。
自定义异常类
本课提供两件事
- 轻松区分模型状态错误和常规异常
- 提供一些我以后可以使用的基本功能
此类稍后在我的自定义错误过滤器中使用。
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", );}这使我的代码可以在任何模型状态错误下重复使用,并且这些错误将按原样发送给客户端。
一个问题(现已解决)
但是仍然存在与此代码相关的一个问题。
当我设置了错误操作过滤器,StatusDescription
并且该字符串包含某些特殊字符(如Č)时,客户端上就会出现垃圾。除非我使用IE(我使用的是版本8)。FF和CH显示为垃圾。这就是为什么我设置编码但是不起作用。如果有人对此有特殊的解决方法,我将非常乐意听。
如果我在内容本身中返回错误消息,一切都很好。编码正确,我可以显示任何内容。



