您的位置:首页 > 其它

MVC 实现计算页面执行时间

2014-06-04 16:23 218 查看
使用 ActionFilterAttribute 来实现:

public class PerformanceActionAttribute:ActionFilterAttribute
{
public string Message { get; set; }

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//在Action执行前执行

GetTimer(filterContext, "action").Start();

base.OnActionExecuting(filterContext);
}

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//在Action执行之后执行
var actionTimer = GetTimer(filterContext, "action");
//GetTimer(filterContext, "action").Stop();
actionTimer.Stop();
base.OnActionExecuted(filterContext);
string extime = "页面执行耗时" + actionTimer.ElapsedMilliseconds+"毫秒";
filterContext.HttpContext.Response.Headers.Add("extime",extime);
//在这里显示给用户的时间只是action的执行时间,如果在view中有执行调用代码的部分,则时间不会
//记录在内,所以这里的时间不是很准,但是这个时间可以很自由的被view中的代码调用显示,使得界面可以按照
//自己的意愿进行显示
}

public override void OnResultExecuting(ResultExecutingContext filterContext)
{
GetTimer(filterContext, "render").Start();

base.OnResultExecuting(filterContext);
}

public override void OnResultExecuted(ResultExecutedContext filterContext)
{
//在Result执行之后
//这里使用response.write输出只能是输出到documnet的最后部分,不能按照想法显示到指定的随意位置
//所以这里隐藏显示了。
//这这部分使用response.Headers是无效的,因为当执行这部分内容的时候,view已经渲染完了,在这添加到Header
//中的值,无法在页面获得
var renderTimer = GetTimer(filterContext, "render");
renderTimer.Stop();

var actionTimer = GetTimer(filterContext, "action");
var response = filterContext.HttpContext.Response;

if (response.ContentType == "text/html")
{
response.Write(
String.Format(
"<p id='pidtimeelapse' style='display:none;'>Action '{0} :: {1}', Execute: {2}ms, Render: {3}ms.</p>",
filterContext.RouteData.Values["controller"],
filterContext.RouteData.Values["action"],
actionTimer.ElapsedMilliseconds,
renderTimer.ElapsedMilliseconds
)
);

}

base.OnResultExecuted(filterContext);
}

private Stopwatch GetTimer(ControllerContext context, string name)
{
string key = "__timer__" + name;
if (context.HttpContext.Items.Contains(key))
{
return (Stopwatch)context.HttpContext.Items[key];
}

var result = new Stopwatch();
context.HttpContext.Items[key] = result;
return result;
}
}


在action 处使用 见第一行

[PerformanceAction]
public ActionResult Index(string type="默认",int pageIndex=1)
{
string orderType = type;
int pageSize = pageSizeCom;
int total = 1;
List<vArticleMain> list = artBLL.GetArticleByPage(pageIndex, pageSize, orderType, out total);
ViewBag.list = list;

//分页信息

ViewBag.pageIndex = pageIndex;
ViewBag.pageCount = total;
ViewBag.type = type;

return View();
}


在view 中显示 可以在指定位置引用

<div class="row col-md-12">
@Response.Headers.Get("extime")
</div>


还有一种是使用 httpmodule的方法,使用该方法不用在每个action上加特性了

地址:http://haacked.com/archive/2008/07/02/httpmodule-for-timing-requests.aspx/

但是在使用该方法调试的时候,出现一个进程中有多个线程的情况,该方法多次执行。而时间编程是单线程的,没有定义多线程,不知道为什么会出现多线程情况。

所以没有使用该方法。(该方法得到的时间比filter的方法得到的时间要更准确)

filter方法参考链接:http://bradwilson.typepad.com/blog/2010/07/aspnet-mvc-filters-and-statefulness.html
http://www.sharejs.com/codes/csharp/6235 http://blog.csdn.net/keepitshortandsimple/article/details/7357954
第二天想到新的解决办法,思路就是:OnResultExecuted 中最后输出的代码虽然不在服务器端的view中用response取得,只能输出到页面的最后部分,

但是当信息传输到浏览器上的时候,可以用jquery 来取得输出的内容,然后显示到指定的位置。OnResultExecuted 方法只是在view页面在服务器端渲染完之后执行,

不是在浏览器上显示完之后执行,所以可以在浏览器上取得在OnResultExecuted 阶段输出的内容。

attribute的代码 :在 OnActionExecuted 阶段不再输出内容

public class PerformanceActionAttribute:ActionFilterAttribute
{
public string Message { get; set; }

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//在Action执行前执行

GetTimer(filterContext, "action").Start();

base.OnActionExecuting(filterContext);
}

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//在Action执行之后执行
//var actionTimer = GetTimer(filterContext, "action");
GetTimer(filterContext, "action").Stop();
//actionTimer.Stop();
base.OnActionExecuted(filterContext);
//string extime = "页面执行耗时" + actionTimer.ElapsedMilliseconds+"毫秒";
//filterContext.HttpContext.Response.Headers.Add("extime",extime);

//在这里显示给用户的时间只是action的执行时间,如果在view中有执行调用代码的部分,则时间不会
//记录在内,所以这里的时间不是很准,但是这个时间可以很自由的被view中的代码调用显示,使得界面可以按照
//自己的意愿进行显示

//想出新的办法了,所以这里注释掉,用下边的总时间
}

public override void OnResultExecuting(ResultExecutingContext filterContext)
{
GetTimer(filterContext, "render").Start();

base.OnResultExecuting(filterContext);
}

public override void OnResultExecuted(ResultExecutedContext filterContext)
{
//在Result执行之后
//这里使用response.write输出只能是输出到documnet的最后部分,不能按照想法显示到指定的随意位置
//所以这里隐藏显示了。
//这这部分使用response.Headers是无效的,因为当执行这部分内容的时候,view已经渲染完了,在这添加到Header
//中的值,无法在页面获得

//第二天想出新的方法来解决
//如下所以,输出到页面的内容放到固定标签中,有ID,然后再页面上用js来取得对应的内容,然后相加,显示到指定的位置
var renderTimer = GetTimer(filterContext, "render");
renderTimer.Stop();

var actionTimer = GetTimer(filterContext, "action");
var response = filterContext.HttpContext.Response;

if (response.ContentType == "text/html")
{
response.Write(
String.Format(
"<p id='disAction' style='display:block;'>Action '{0} :: {1}' <span id='disexecute'>{2}</span><span id='disrender'>{3}</span></p>",
filterContext.RouteData.Values["controller"],
filterContext.RouteData.Values["action"],
actionTimer.ElapsedMilliseconds,
renderTimer.ElapsedMilliseconds
)
);

}

base.OnResultExecuted(filterContext);
}

private Stopwatch GetTimer(ControllerContext context, string name)
{
string key = "__timer__" + name;
if (context.HttpContext.Items.Contains(key))
{
return (Stopwatch)context.HttpContext.Items[key];
}

var result = new Stopwatch();
context.HttpContext.Items[key] = result;
return result;
}
}


在controller中的内容不变,

在view中的内容:

<div id="pagetime" class="row col-md-12">

</div>


jquery

$(function () {
var disexecute = $("#disexecute").html();
var disrender = $("#disrender").html();
var ht = "页面执行耗时" + (parseInt(disexecute) + parseInt(disrender)) + "毫秒";
$("#pagetime").html(ht);
});


这样就比较完美了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: