最近监控线上日志,网站是ASP.NET MVC 开发的,发现不少错误日志都记录同样的内容:

The view 'Error' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Search/Error.aspx
~/Views/Search/Error.ascx
~/Views/Shared/Error.aspx
~/Views/Shared/Error.ascx
~/Views/Search/Error.cshtml
~/Views/Search/Error.vbhtml
~/Views/Shared/Error.cshtml
~/Views/Shared/Error.vbhtml
System.Web.Mvc
   at System.Web.Mvc.ViewResult.FindView(ControllerContext context)

本地调试下不会发现,通过排查发现本地和线上配置的差异在于 customErrors mode="On",将本地改后单点调试发现确实是将这样的错误记录,而本身我在action里面 throw 出来的异常已经抓取不到了。也就是说真的异常并未抓取到,而记录的是一个无关紧要莫名其妙的日志,因为我并没有任何代码去返回”Error“这个view。

先说下目前我抓取异常的方式:在Global.asax文件中增加

        protected void Application_Error(object sender, EventArgs e)
        {
            Exception ex = Server.GetLastError();
            //Write Log
        }

假如在Controller里面去override OnException方法进行写日志则不会出现这样的问题,但是在Controller里记日志可能会使在View里面出错的日志记录不到。

烦了很久,最后不经意发现MVC里面会默认注册一个Filter,代码如下

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

注册掉可以解决上述问题,但是我不太服气,于是在codeplex翻了mvc的源代码,HandleErrorAttribute的代码如下:

using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Web.Mvc.Properties;

namespace System.Web.Mvc
{
    [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "This attribute is AllowMultiple = true and users might want to override behavior.")]
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class HandleErrorAttribute : FilterAttribute, IExceptionFilter
    {
        private const string DefaultView = "Error";

        private readonly object _typeId = new object();

        private Type _exceptionType = typeof(Exception);
        private string _master;
        private string _view;

        public Type ExceptionType
        {
            get { return _exceptionType; }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }
                if (!typeof(Exception).IsAssignableFrom(value))
                {
                    throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
                                                              MvcResources.ExceptionViewAttribute_NonExceptionType, value.FullName));
                }

                _exceptionType = value;
            }
        }

        public string Master
        {
            get { return _master ?? String.Empty; }
            set { _master = value; }
        }

        public override object TypeId
        {
            get { return _typeId; }
        }

        public string View
        {
            get { return (!String.IsNullOrEmpty(_view)) ? _view : DefaultView; }
            set { _view = value; }
        }

        public virtual void OnException(ExceptionContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            if (filterContext.IsChildAction)
            {
                return;
            }

            // If custom errors are disabled, we need to let the normal ASP.NET exception handler
            // execute so that the user can see useful debugging information.
            if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
            {
                return;
            }

            Exception exception = filterContext.Exception;

            // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
            // ignore it.
            if (new HttpException(null, exception).GetHttpCode() != 500)
            {
                return;
            }

            if (!ExceptionType.IsInstanceOfType(exception))
            {
                return;
            }

            string controllerName = (string)filterContext.RouteData.Values["controller"];
            string actionName = (string)filterContext.RouteData.Values["action"];
            HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
            filterContext.Result = new ViewResult
            {
                ViewName = View,
                MasterName = Master,
                ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
                TempData = filterContext.Controller.TempData
            };
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Clear();
            filterContext.HttpContext.Response.StatusCode = 500;

            // Certain versions of IIS will sometimes use their own error page when
            // they detect a server error. Setting this property indicates that we
            // want it to try to render ASP.NET MVC's error page instead.
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
        }
    }
}
HandleErrorAttribute

坑爹,他mvc里面会默认返回error视图,看来以后新开发时还是创建空项目好了。

至于为啥设置了customErrors mode="On"后才会出现这种垃圾日志,则要归咎于HandleErrorAttribute类的OnException方法里面了

        // If custom errors are disabled, we need to let the normal ASP.NET exception handler
            // execute so that the user can see useful debugging information.
            if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
            {
                return;
            }

 

解决方案是删掉默认注册的这个filter或者新增类去override相应的方法。

posted @ 2015-07-10 13:54 dong.net 阅读(2263) 评论(1) 推荐(1) 编辑
摘要: 之前由于上线验证需要各种修改配置,需要运维同事处理,太麻烦,今天用程序处理了修改配置文件,一劳永逸,小记下: [HttpPost] public ActionResult SaveSetting(string key, string value) { ... 阅读全文
posted @ 2015-04-20 15:52 dong.net 阅读(1053) 评论(0) 推荐(0) 编辑
摘要: 问题一:Nullable可赋值为null先看两行C#代码 int? i1 = null; int? i2 = new int?(); int? 即Nullable,就像int之于Int32;Nullable是非常特殊结构类型,它可赋值为nul... 阅读全文
posted @ 2015-02-11 17:53 dong.net 阅读(816) 评论(0) 推荐(2) 编辑
摘要: 一、【前言】(1)本文将用到IOC框架Unity,可参照《Unity V3 初步使用 —— 为我的.NET项目从简单三层架构转到IOC做准备》(2)本文的解决方案是基于前述《使用IdleTest进行TDD单元测试驱动开发演练(1)》、《使用IdleTest进行TDD单元测试驱动开发演练(2)》继续编 写的,但是已经将解决方案、项目名称等等改名为了“IdleTest.EFAndMVCDemo”。(3)本文将不再一步一步的记录,只写出重要的步骤并贴出一些关键代码,完整代码请参照 IdleTest中的IdleTest.EFAndMVCDemo.MvcUI项目和IdleTest.EFAndMVCDem 阅读全文
posted @ 2013-12-29 16:45 dong.net 阅读(1579) 评论(0) 推荐(2) 编辑
摘要: 【前言】1. 有关上篇请参见《使用IdleTest进行TDD单元测试驱动开发演练(1)》,有关本篇用到Entity Framework Code First请参见《使用NuGet助您玩转代码生成数据————Entity Framework 之 Code First》,而用的个人类库参照IdleTest。2. 本文只用了简单的Entity Framework演练单元测试,着重于Testing,而不是实现,并不会涉及事务、效率等问题。3. 回顾上一篇里面讲到的是针对业务层的测试,正如敏捷中厉行的多与用户沟通,在书《C# 测试驱动开发(Professional Test Driven Develop 阅读全文
posted @ 2013-11-09 19:37 dong.net 阅读(1541) 评论(0) 推荐(1) 编辑
摘要: 如果说磨刀不误砍柴工,同样用好Visual Studio,会大大增加咱.NET程序猿效率。本文说的就是Visual Studio中的生成事件,在解决方案下右击某个项目然后选择 “属性” 打开窗口后即可看到 “生成事件” 选项,这个东西其实并不常用,甚至写几年代码都不会碰它一次,但是我今天需要她了... 阅读全文
posted @ 2013-11-05 22:07 dong.net 阅读(15982) 评论(5) 推荐(5) 编辑
摘要: 【前言】开发工具:Visual Studio 2012测试库:Visual Studio 2012自带的MSTestDI框架:Unity数据持久层:Entity Framework前端UI:ASP.NET MVC 4.0需求:我这里假设只满足两个功能,一个用户注册,另一个则是登陆的功能,借助于一些DDD思想,我将从领域层(或者常说的BLL)开始开发,当然每一层都是采用TDD,按我喜欢的做法就是“接口先行,测试驱动”,不废话,直奔主题吧。有关VS2012的单元测试请参见《VS2012 Unit Test 个人学习汇总(含目录)》有关测试中使用的IdleTest库请参见http://idletes 阅读全文
posted @ 2013-11-01 00:24 dong.net 阅读(2384) 评论(4) 推荐(3) 编辑
摘要: 首先,给出MSDN相关地址:http://msdn.microsoft.com/en-us/library/Microsoft.VisualStudio.TestTools.UnitTesting.aspx (类库) Verifying Code by Using Unit Tests(介绍)我的IdleTest源码地址:http://idletest.codeplex.com/VS2012单元测试的主要类:Assert、StringAssert、CollectionAssert,具体可参照上述链接的MSDN介绍。单元测试一直都想接触,但是碍于没有那样的工作环境,故只能由自己在业余时间去... 阅读全文
posted @ 2013-10-22 18:55 dong.net 阅读(14162) 评论(9) 推荐(3) 编辑
摘要: 【1】我的IdleTest源码地址:http://idletest.codeplex.com/【2】IdleTest改动说明:2013年10月份在保持原有功能的情况下对其动了较大的手术,首先将基本的断言方法分离成为接口,以便于扩展,例如现在可以支持切换测试框架(实现IAssertInstance接口,并修改AssertCommon_Editable.cs中的DEFAULT_INSTANCE为新的对象),然后就是增加对xml一些操作的支持。尽管如此,但并不是完全遵循OCP,可以说对扩展开放,对修改适当关闭。体现在AssertCommon_Editable.cs文件,该文件提供了AssertCom 阅读全文
posted @ 2013-10-20 21:44 dong.net 阅读(1765) 评论(2) 推荐(0) 编辑
摘要: 如题,本文主要作为在VS2012使用Fakes的入门示例,开发工具必须是VS2012或更高版本。关于Fakes的MSDN地址:http://msdn.microsoft.com/en-us/library/hh549175.aspx关于VS2012单元测试的前期文章:1.《在Visual Studio 2012使用单元测试》、2.《VS2012 单元测试之泛型类(Generics Unit Test)》、3.《VS2012 Unit Test —— 我对接口进行单元测试使用的技巧》4.《VS2012 Unit Test(Void, Action, Func) —— 对无返回值、使用Action 阅读全文
posted @ 2013-10-06 16:41 dong.net 阅读(17523) 评论(12) 推荐(1) 编辑
点击右上角即可分享
微信分享提示