개발팁2016. 7. 29. 10:01

IIS 웹서버로 요청되는 모든 웹페이지/웹서비스 요청에 대해, 퍼포먼스 로그를 남기는 방법이다.

 

퍼포먼스를 체크하는 방법은, 시작시간을 기록하고,

웹페이지나 특정 메서드가 실행되고 나서, 종료시간과의 차이를 계산해서 기록을 하면 된다.

 

DateTime _startTime = DateTime.Now;

 

// 웹페이지 / 메서드 실행.. 코드

 

TimeSpan span = DateTime.Now - _startTime;
string perfLog = span.Milliseconds.ToString() + " ms";


 

간단한 코드지만, 이를 매번 웹페이지마다 삽입하여 사용하는것은 어려우니,

HttpModule 을 이용하여, 자동으로 기록하는 방법이 있다.

 

IHttpModule 이라는 인터페이스를 이용하여, WebServiceAuthenticationModule 을 만들것이다.

이는 원래, 인증 체크를 위한 클래스인데, 이 안에, 퍼포먼스 로그 기능을 추가한 것이다.

 

별도의 프로젝트를 만들고, WebServiceAuthenticationModule  클래스를 만들어서,

Application_BeginRequest 와 Application_EndRequest 이벤트를 구현할 것이다.

이 프로젝트를 빌드해서, 별도의 DLL 을 만들면 된다.

 

ASP.NET 프로젝트에서 해당 DLL 을 참조 추가를 하고, Web.Config 에 아래와 같이 모듈을 추가 하면된다.

 

    <system.webServer>
      <!-- 인증체크 설정 -->
      <modules>
        <add  name="WebServiceAuthenticationModule"
              type="Hungry.Developer.HttpModule.WebServiceAuthenticationModule"/>
      </modules>
      ...

    </system.webServer>


 

이렇게 되면, 해당 ASP.NET  웹서비스의 모든 웹페이지는

항상 페이지 요청시, WebServiceAuthenticationModule 의 Application_BeginRequest 가 먼저 실행이 될것이고,

요청이 완료되면, Application_EndRequest 를 실행하게 될것이다.

 

이를 이용하여, 맨처음 보여줬던, 퍼포먼스 로그를 기록하면 된다.

 

// Copyright 헝그리개발자(https://bemeal2.tistory.com)
// 소스는 자유롭게 사용가능합니다. Copyright 는 삭제하지 마세요.
public sealed class WebServiceAuthenticationModule : IHttpModule
{
        private DateTime _startTime;    // 퍼포먼스 로깅을 위한 시작시간 저장 변수

        public void Init(HttpApplication app)
        {
            app.BeginRequest +=
                (new EventHandler(this.Application_BeginRequest));
            app.EndRequest +=
                (new EventHandler(this.Application_EndRequest));

        }
        private void Application_BeginRequest(object source, EventArgs e)
        {
             // 웹페이지 / 웹서비스 실행 시작시간 기록
            _startTime = DateTime.Now;

             // 인증체크
             ...
        }

        // 요청완료시, 퍼포먼스 로그 기록
        private void Application_EndRequest(object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;

            TimeSpan span = DateTime.Now - _startTime;
            string perfLog = application.Request.Url + " / " + span.Milliseconds.ToString() + " ms";
            LogWriter.PerfLog(perfLog);
        }

}

 

LogWriter 는 string 값을 파일에 추가하는 클래스다.

파일에 저장을 하던, DB에 저장을 하던, 원하는 방식으로 구현하면 된다.

 

아래는 위의 코드를 그대로 이용한, 실제 로그파일의 내용이다. 이중에 Performance 만 보면 된다.

 

2016-07-29 09:27:37.036 (Performance) From< HttpModule > :http://삐~/WebService/삐~Service.asmx / ReadBy / 100 ms
2016-07-29 09:27:37.359 (Debug) From< HttpModule > :인증체크 : 0 / cachekey(cUwze7r0rMTQCVHW9eXE/A==) / authkey(khMBxeLsajUjv7zdBcnrdG33JUQahNjqCqNzmH5G6nk=) / menuid(149) / permission(1)
2016-07-29 09:27:37.361 (Debug) From< HttpModule > :권한체크 : 0 / menuid(149) / permission(1) / requestURL(http://삐~/WebService/삐~Service.asmx) / webMethodName(ReadBy) / userIP(127.0.0.1)
2016-07-29 09:27:37.430 (Debug) From< HttpModule > :인증체크 : 0 / cachekey(cUwze7r0rMTQCVHW9eXE/A==) / authkey(khMBxeLsajUjv7zdBcnrdG33JUQahNjqCqNzmH5G6nk=) / menuid(149) / permission(1)
2016-07-29 09:27:37.433 (Debug) From< HttpModule > :권한체크 : 0 / menuid(149) / permission(1) / requestURL(http://삐~/WebService/삐~Service.asmx) / webMethodName(ReadBy) / userIP(127.0.0.1)
2016-07-29 09:27:37.470 (Performance) From< HttpModule > :http://삐~/WebService/삐~Service.asmx / ReadBy / 113 ms
2016-07-29 09:27:37.514 (Performance) From< HttpModule > :http://삐~/WebService/삐~Service.asmx / ReadBy / 87 ms
2016-07-29 09:27:46.580 (Debug) From< HttpModule > :인증체크 : 0 / cachekey(cUwze7r0rMTQCVHW9eXE/A==) / authkey(khMBxeLsajUjv7zdBcnrdG33JUQahNjqCqNzmH5G6nk=) / menuid(139) / permission(1)
2016-07-29 09:27:46.589 (Debug) From< HttpModule > :권한체크 : 0 / menuid(139) / permission(1) / requestURL(http://삐~/WebService/삐~Service.asmx) / webMethodName(삐~) / userIP(127.0.0.1)
2016-07-29 09:27:46.893 (Performance) From< HttpModule > :http://삐~/WebService/삐~Service.asmx / SponsorSearch / 315 ms 

 

Posted by 헝개
개발팁2016. 7. 20. 09:41

ASP.NET 의 View 를 ViewEngine 으로 렌더링해서 나온 HTML 을 엑셀로 내려받는 방법이다.

 

아래와 같이 2개의 정적 메서드를 정적 클래스 (static class) 안에 정의한다.

 

// Copyright 헝그리개발자​(http://bemeal2.tistory.com)
// 소스는 자유롭게 사용가능합니다. Copyright 는 삭제하지 마세요.

// HTML 을 엑셀파일로 웹 다운로드
public static void ToExcelDownload(this string strHTML, string filename)
{
    filename = filename.Replace(" ", "_");



    HttpContext.Current.Response.AppendHeader("content-disposition", "attachment;filename=" + HttpUtility.UrlEncode(filename));
    HttpContext.Current.Response.Charset = "";
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
    HttpContext.Current.Response.Write(strHTML);
    HttpContext.Current.Response.End();
}



// View 를 HTML 문자열로 변환
public static string ViewToString(this ControllerContext controller, string viewName, ViewDataDictionary ViewData, TempDataDictionary TempData, object model)
{
    ViewData.Model = model;
    using (var sw = new StringWriter())
    {
         var viewResult = ViewEngines.Engines.FindPartialView(controller, viewName);
         var viewContext = new ViewContext(controller, viewResult.View, ViewData, TempData, sw);
         viewResult.View.Render(viewContext, sw);
         viewResult.ViewEngine.ReleaseView(controller, viewResult.View);


         return sw.GetStringBuilder().ToString();
    }
}

 

ToExcelDownload 메서드는 문자열(html)을 엑셀타입으로 내려받도록 해준다.

실제 내용은 table 테그로 구성된 html 이지만, 엑셀 형식으로 다운로드하도록 해주는 것이다.

 

ViewToString 메서드는 ViewContext 로, View 를 렌더링해서 String 으로 만들어준다.

 

 

엑셀 다운로드 버튼에 대한 Controller 를 아래와 같이 정의할 수 있다.

Model 을 구성하여, ViewToString 으로 View 이름과 Model 객체를 전달하여 준다.

예제에서는 Controller 이름과 동일한 이름의 View 이름을 사용하였다.

 

이 말은, 현재 Controller 의 View 를 호출하여 렌더링 한다는 뜻이다.

물론, 다른 Controller 의 View 이름을 넣어주어도 상관이 없다. 해당 View 에 맞는 Model 만 생성해서 전달해주면 된다.

 

 // 엑셀 다운로드에 대한 컨트롤러
public ActionResult Sample_ExcelDownload(int key_id)
{
    MySampleDataContainer model = new MySampleDataContainer();



    BizSample biz = new BizSample();
    model.header = biz.SampleDataInfo(key_id);
    model.list = biz.SampleDataList(key_id);



    string strHTML = this.ControllerContext.ViewToString("Sample_ExcelDownload", this.ViewData, this.TempData, model);
    string filename = "excel_download_sample.xls";
    strHTML.ToExcelDownload(filename);

    return View();
}

 

 

View 내용인데, 일반적으로 사용하는 View 와 동일하다.

다만 Excel 파일로 열어줘야 하기 때문에 엑셀에서 인식하도록 몇가지 태그가 추가되었을 뿐이다.

 

 // 엑셀 내용에 대한 뷰 - Sample_ExcelDownload
@model HD.DataFactory.MySampleDataContainer
@{
    ViewBag.Title = "Excel";
    Layout = "~/Views/Shared/_ContentLayout.cshtml";
}

<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">
<head>
    <meta content="text/html; charset=utf-8" http-equiv="content-type" />
    <!--[if gte mso 9]>
<xml>
<x:ExcelWorkbook>
<x:ExcelWorksheets>
<x:ExcelWorksheet>
<x:Name>sheet name</x:Name>
<x:WorksheetOptions>
<x:DisplayGridlines/>
</x:WorksheetOptions>
</x:ExcelWorksheet>
</x:ExcelWorksheets>
</x:ExcelWorkbook>
</xml>
<![endif]-->
</head>
<body>

<table class="doc_data_list" border="1">
...
</table>

</body>
</html>

 

 

Posted by 헝개