解
我必须编写两个独立的部分,这些部分自动按照意图进行工作。
因此,当控制器操作过程成功时,它应该返回部分视图,并且当事情不正确时,它会抛出一些错误,因为客户端上的某些事情会区分成功以及失败,而不是总是处理成功。
有两个主要部分用于实现这一点:
>一个自定义异常类,当出现错误时抛出异常,所以我们可以区分出现任何时候出现的任何原因和与处理有关的错误的异常(最引人注目的是无效的模型状态)
>异常行为过滤器捕获我们的自定义异常并根据该异常准备结果;从代码中可以看出,我们的自定义异常将保存有关模型状态错误的信息,因此此过滤器将能够返回自定义HTTP状态代码以及一些文本信息
关于细节,那么…
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 07000.
自定义异常类
这个班提供两件事
>使模型状态错误与常规异常区分开来很简单
>提供一些我以后可以使用的基本功能
此类以后在我的自定义错误过滤器中使用。
public class ModelStateException : Exception
{
public Dictionary 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();
}
public ModelStateException(ModelStateDictionary modelState) : this()
{
this.ModelState = modelState;
if (!modelState.IsValid)
{
foreach (KeyValuePair 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;
}
}
}
之后,我简单地用我的属性来装饰我的控制器动作。我在客户端上收到错误代码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显示垃圾。这就是为什么我设置编码,但它不工作。如果有人有这个特殊性的解决方法,我会很乐意听。如果我在内容本身返回错误信息,一切都很好。编码是正确的,我可以显示任何我想要的。