Adding a view to an ASP.NET Core MVC app (3/10)

 

 

1. 시작 (원글 : Getting started)
2. Controller 추가하기 (원글 : Adding a controller)
3. View 추가하기 (원글 : Adding a view)
4. Model 추가하기 (원글 : Adding a model)
5. Working with SQL Server LocalDB
6. Controller methods and views
7. Adding Search
8. Adding a New Field
9. Adding Validation
10. Examining the Details and Delete methods

 

이 섹션에서 여러분은 client 에 응답할 HTML 을 생성하는 작업을 깔끔하게 캡슐화하는 Razor view template 을 사용하기 위해 HellowWorldController class 를 수정합니다.

여러분은 Razor 를 사용하는 view template file 을 생성합니다.

Razor 기반 View template 은 cshtml 확장자를 갖습니다.

C# 을 사용하여 HTML output 을 생성하는 우아한 방법을 제공합니다.

현재 index method 는 controller class 에서 hard-cord 된 string 의 message 를 반환합니다.

HelloWorldController class 의 index method 를 다음 코드로 변경합니다.

 

 

public IActionResult Index()
{
    return View();
}

 

진행되는 code 는 view object 를 반환합니다.

Browser 에 HTML 응답코드를 생성하기위해 view template 을 사용합니다.

위 index method 같은 Controller method (action method 로 알려진) 는 일반적으로 string과 같은 Primitive 한 형식이 아닌 IActionResult (또는 ActionResult 에서 파생된 class) 를 반환합니다.

Views Folder 를 오른쪽 클릭합니다., 그리고 Add > New folder 를 선택합니다. 그리고 folder 이름을 "HelloWorld" 로 지정합니다.

Views/HelloWorld folder 를 오른쪽 클릭합니다. 그리고 Add > New Item 을 선택합니다.

 

Add New Item - MvcMovie 대화창에서  

오른쪽 상단의 search 입력란에 view 를 입력합니다.

MVC View Page 를 Tap 합니다.

Name 입력란에 필요하다면 이름을 index.cshtml 로 변경합니다.

Add 를 Tap 합니다.

 

Add New Item dialog

 

Views/HelloWorld/index.cshtml Razor View 파일의 내용을 다음의 코드로 변경하십시오.

 

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

 

http://localhost:xxx?HelloWorld 로 이동하십시오.

HelloWorldController 의 index method 는 많은 일을 하지 않습니다. 구문을 실행하고 View(); 를 반환하는 함수를 지정하는데, Browser 에 보낼 응답을 render 하기 위해서 View template 을 사용해야 합니다.

View template file 의 이름을 명확하게 지정하지 않았기 때문에 MVC 는 기본적으로 Views/HelloWorld 폴더내의 index.cshtml view file 을 사용합니다.

아래의 이미지는 View 에 Hard Cording된 "Hello from our View Template!" 이라는 문자열을 보여줍니다.

 

 

Browser window

 

만약 여러분의 browser 창이 작다면( 예를들어, mobile device 처럼 ), Home, About, Contact 링크를 보기위해서 우측상단의 Bootstrap navigation button 을 toggle (tap)할 필요가 있습니다.

 

Browser window highlighting the Bootstrap navigation button

 

View 와 Layout page 변경하기

menu link (MvcMovie, Home, About) 를 Tap 합니다.

각 페이지는 동일한 menu layout 을 보여줍니다.

menu layout 은 Views/Shared/_Layout.cshtml file 에 구현되어 있습니다.

Views/Shared/_Layout.cshtml 파일을 여십시오.

 

Layout template 을 사용하면 여러분 사이트의 HTML container layout 를 한곳에서 지정할 수있으며 여러분 사이트의 여러페이지에 적용됩니다.

@RenderBody() Line 을 찾으십시오.

RenderBody 는 여러분이 만든 모든 view page 가 layout page 상에 보이도록 wrapping 된 Placeholder 입니다.

예를 들어, 만약 여러분이 About link 를 선택한다면, Views/Home/About.cshtml View 가 RenderBody method 내부에 rendering 됩니다.

 

Layout file 에서 Title 과 Menu link 변경

Title 요소의 내용을 변경하십시오.

아래 Highlight 된 코드처럼 Layout template 의 anchor text 를 "Movie App" 으로 변경하십시오. 그리고 Controller 를 Home 에서 Movies 로 변경하십시오.

 

참고 : ASP.NET Core 2.0 version 은 약간 다릅니다.

@inject ApplicationInsights 와 @Html.Raw(JavaScriptSnippet.FullScript) 는 포함되어 있지 않습니다.

 

 

@inject Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet JavaScriptSnippet
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Movie App</title>

    <environment names="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    </environment>
    <environment names="Staging,Production">
        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
        <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
    </environment>
    @Html.Raw(JavaScriptSnippet.FullScript)
</head>
<body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a asp-area="" asp-controller="Movies" asp-action="Index" class="navbar-brand">MvcMovie</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
                    <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
                    <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; 2017 - MvcMovie</p>
        </footer>
    </div>

    <environment names="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
    </environment>
    <environment names="Staging,Production">
        <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
                asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
                asp-fallback-test="window.jQuery"
                crossorigin="anonymous"
                integrity="sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk">
        </script>
        <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
                asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
                asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
                crossorigin="anonymous"
                integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
        </script>
        <script src="~/js/site.min.js" asp-append-version="true"></script>
    </environment>

    @RenderSection("Scripts", required: false)
</body>
</html>

 

 

경고

아직 Movies Controller 를 구현하지 않아서 해당 Link 를 클릭하면 404 (Not Found) 오류가 발생합니다. 

 

변경사항을 저장하고 About Link 를 Tap 하십시오.

browser tab 의 Title 에 About - Mvc Movie 대신에 About - Movie App 을 표시하는 방법에 주의하여 보십시오.

Contact Link 를 Tap 하여 Movie App 이 표시되는 것 또한 주의하여 보십시오.

Layout template 을 한번 변경하면 Site 의 전체 페이지에 새로운 링크와 새로운 title 이 반영하는 것이 가능했습니다.

Views/_ViewStart.cshtml file 을 검사하십시오.

 

@{
    Layout = "_Layout";
}

 

Views/_ViewStart.cshtml file 은 Views/shared/_Layout.cshtml file 을 각 View 에 전달합니다.

Layout property 에 다른 layout view 를 설정하거나  Null 을 설정하여 아무런 layout 을 사용하지 않도록 할 수 있습니다.

Index view 의  title 변경

Views/HelloWorld/Index.cshtml 을 엽니다. 두군데를 수정합니다.

browser 의 title 에 나타나는 text.

secondary header ( <h2> element )

코드의 어느부분을 변경하면 app 의 어느부분이 바뀌는지 약간의 차이점을 알수 있습니다.

 

 

@{
    ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

 

 

위 코드의 ViewData["Title"] = "Movie List"; 는 ViewData dictionary 의 Title 속성을 "Movie List" 로 설정합니다.

Title 속성은 Layout page 의 <title> HTML element 에서 사용됩니다.

 

 

<title>@ViewData["Title"] - Movie App</title>

 

변경사항을 저장하고 http://localhost:xxxx/HelloWorld 로 이동하십시오.

browser title, Primary Heading, Secondary Heading 이 변경되었는지 주의해서 살펴보십시오.

(만약 browser 에서 변경사항을 볼 수 없다면 Cache 된 내용일 것입니다. browser 에서 Ctrl+F5 를 눌러 서버의 response 를 강제로 load 하십시오.)

browser title 이 ViewData["Title"]로 생성되어 index.cshtml template 에서 설정되고 추가적으로 " - Movie App" 이 Layout file 에서 추가됩니다.

또, Views/Shared/_Layout.cshtml view template 과 browser 로 보내진 single html response 가 어떻게 병합되어 index.cshtml view template 의 content 가 만들어지는지 주의하여 살펴보십시오.

Layout templates 를 변경하여 적용하면 application 의 모든 페이지 걸쳐 정말 쉽게 변경됩니다.

 

더 자세한 내용은 Layout 을 참조하십시오.

 

Movie List view

 

약간의 data ( 여기서는 "Hello from our View Template" 이라는 message) 는 Hard coding 되어 있습니다.

이 MVC application 에는 "V" (view) 가 있고 "C" (controller) 를 만들었지만 아직 "M" (model) 은 없습니다.

 

Controller 에서 View 로 Data 전달하기

Controller 의 actions 는 들어오는 (incoming) URL request 에 대한 response 에서 호출됩니다.

controller class 는 들어오는 browser request 를 처리하는 코드를 작성하는 곳입니다.

controller 는 data source 로 부터 data 를 retrieve 하고 browser 에 돌려보낼 response 의 type 을 결정합니다.

View template 은 controller 에서 browser 로 보내질 HTML response 를 생성하고 형식을 지정할 수 있습니다.

controller 는 view template 이 response 를 rendering 하기위해 요구되는 data 를 제공해야할 책임이 있습니다.

 

모범 사례 : View template 은 business logic 을 수행하거나 database 와 직접 상호작용을 하면 안됩니다.

대신 view template 은 오직 controller 가 view 만들 위해 제공하는 data 와 작업해야합니다.

이 관심의 분리( "separation of concerns" ) 를 유지하면 여러분의 코드를 깨끗하고, 테스트 가능하고 유지보수가능하도록 하는데 도움이 됩니다.

현재 HelloWorldController class 의 Welcome method 는 name 과 ID 를 매개변수로 취하여 browser 로 값을 직접 출력합니다.

controller 가 response 를 string 으로 rendering 하도록 하기보다. controller 가 view template 을 대신 사용하도록 변경합시다.

 

view template 은 동적 response 를 생성합니다. 이 것은 response 를 생성하기 위해서 적절한 bit 의 data 를 controller 에서 view 로 전달해야할 필요가 있다는 것을 의미합니다.

view template 이 필요한 data 를 controller 에서 dynamic data( parameters) 인  view template 이 접근 가능한 ViewData dictionary 에 담음으로써 이 작업이 가능합니다.

HelloWorldController.cs file 로 돌아가서 ViewData dictionary 에 Message 와 NumTimes 를 추가하도록 Welcome method 를 변경합니다.

ViewData dictionary 는 dynamic object 입니다. 즉 여러분이 원하는 것은 어떤 것도 집어 넣을 수 있습니다.

ViewData object 는 여러분이 그 안에 무언가를 넣기 전까지 정의된 속성이 없습니다.

MVC model binding system 은 address bar 에 적힌 query string 에서  이름있는 매개변수( name 과 numTimes )를 추출하여 여러분이 만든 method 의 parameter 로 자동적으로 mapping 합니다.

완전한 HelloWorldController.cs 파일의 내용은 다음과 같습니다.

 

 

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
    public class HelloWorldController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Welcome(string name, int numTimes = 1)
        {
            ViewData["Message"] = "Hello " + name;
            ViewData["NumTimes"] = numTimes;

            return View();
        }
    }
}

 

ViewData Dictionary 객체는 View 에 전달할 data 를 포함하고 있습니다.

Views/HelloWorld/Welcome.cshtml 라는 이름의 Welcome view template 을 생성하십시오.

Welcome.cshtml view template 내에 "Hello " NumTimes 를 표시할 Loop 를 생성합니다.

아래 코드로 Views/Helloworld/Welcome.cshtml 의 내용을 변경합니다.

 

 

@{
    ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
    @for (int i = 0; i < (int)ViewData["NumTimes"]; i++)
    {
        <li>@ViewData["Message"]</li>
    }
</ul> 

 

변경사항을 저장하고 다음 URL 로 이동하십시오.
http://localhost:xxxx/HelloWorld/Welcome?name=Rick&numtimes=4

Data 를 URL 에서 가져와서  MVC model binder 를 이용하여 controller 에 전달합니다.

controller 는 data 를 ViewData dictionary 에 packages 하고 View 에 그  Object 를 전달합니다.

그 다음 view 는 HTML data 를 browser 에 render 합니다.

 

 

About view showing a Welcome label and the phrase Hello Rick shown four times

 

위 sample 에서 controller 로 부터 view 로 data 를 전달하기위해서 ViewData Dictionary 를 사용했습니다.

다음 tutorial 에서는 controller 에서 view 로 data 를 전달하기위해서 view model 을 사용합니다.

data 를 전달하는 view model 접근 (approach) 은 일반적으로 ViewData dictionary 접근 보다 훨씬 더 좋습니다.

자세한 사항은 ViewModel vs ViewData vs ViewBag vs TempData vs Session in MVC 를 참조하십시오.

그럼, 여기서 M 은 model 을 말하는 것이지 database 를 의미하지 않습니다.

배운 것을 바탕으로 Movie database 를 생성해 봅시다.

 

 

 

이상입니다.

번역?이 이상하고 맘에 들지 않지만 참고로 보시기 바랍니다.

 

 

 

행복한 고수되셔요.

 

 

woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\













저작자 표시 비영리 변경 금지
신고

'Web > ASP.NET Core' 카테고리의 다른 글

[ASP.NET Core] Adding a view to an ASP.NET Core MVC app (3/10)  (0) 2017.10.27
[ASP.NET Core] MiddleWare  (0) 2017.07.10
[ASP.NET Core] Application Startup  (0) 2017.06.11
Posted by woojja
2017.10.24 20:30


Log4Net 을 사용하다가 다소 불편한 감이 있어서

File 에 Log 를 작성하는 Class 를 간단하게 작성했습니다.

그냥 동적으로 로그 파일을 만들어서 확확 적어버리고 싶었거든요. 




내용은 이렇습니다.


    public enum LogLevel

    {

        NONE,

        TRACE,

        INFO,

        DEBUG,

        WARNING,

        ERROR,

        FATAL,

        MANNUAL

    }


    public class Logger

    {        

        public Logger()

        {

        }

        

        /// <summary>

        /// Format a log message based on log level

        /// </summary>

        /// <param name="level">Log level</param>

        /// <param name="text">Log message</param>

        public static int WriteLog(string filePath, string fileName, string text, LogLevel level = LogLevel.INFO, bool withLevel = true, bool append = true)

        {

            string DatetimeFormat = "yyyy-MM-dd HH:mm:ss.fff";

            string pretext = DateTime.Now.ToString(DatetimeFormat);

            string strLevel = " : ";


            if (withLevel)

            {

                switch (level)

                {

                    case LogLevel.TRACE:

                        strLevel = " [TRACE]   : ";

                        break;

                    case LogLevel.INFO:

                        strLevel = " [INFO]    : ";

                        break;

                    case LogLevel.DEBUG:

                        strLevel = " [DEBUG]   : ";

                        break;

                    case LogLevel.WARNING:

                        strLevel = " [WARNING] : ";

                        break;

                    case LogLevel.ERROR:

                        strLevel = " [ERROR]   : ";

                        break;

                    case LogLevel.FATAL:

                        strLevel = " [FATAL]   : ";

                        break;

                    default: break;

                }

            }


            return WriteLine(filePath, fileName, pretext + strLevel + text);

        }


        /// <summary>

        /// Format a log message based on log level

        /// </summary>

        /// <param name="level">Log level</param>

        /// <param name="text">Log message</param>

        public static async Task<int> WriteLogAsync(string filePath, string fileName, string text, LogLevel level = LogLevel.INFO, bool withLevel = true, bool append = true)

        {

            string DatetimeFormat = "yyyy-MM-dd HH:mm:ss.fff";

            string pretext = DateTime.Now.ToString(DatetimeFormat);

            string strLevel = " : ";


            if (withLevel)

            {

                switch (level)

                {

                    case LogLevel.TRACE:

                        strLevel = " [TRACE]   : ";

                        break;

                    case LogLevel.INFO:

                        strLevel = " [INFO]    : ";

                        break;

                    case LogLevel.DEBUG:

                        strLevel = " [DEBUG]   : ";

                        break;

                    case LogLevel.WARNING:

                        strLevel = " [WARNING] : ";

                        break;

                    case LogLevel.ERROR:

                        strLevel = " [ERROR]   : ";

                        break;

                    case LogLevel.FATAL:

                        strLevel = " [FATAL]   : ";

                        break;

                    case LogLevel.MANNUAL:

                        strLevel = " [MANNUAL] : ";

                        break;

                    default: break;

                }

            }


            return await WriteLineAsync(filePath, fileName, pretext + strLevel + text);

        }

        

        /// <summary>

        /// Write a line of formatted log message into a log file

        /// </summary>

        /// <param name="text">Formatted log message</param>

        /// <param name="append">True to append, False to overwrite the file</param>

        /// <exception cref="System.IO.IOException"></exception>

        private static int WriteLine(string filePath, string fileName, string text, bool append = true)

        {

            int intReturn = 0;


            if (string.IsNullOrEmpty(filePath))

                throw new ArgumentNullException("filePath");


            if (string.IsNullOrEmpty(fileName))

                throw new ArgumentNullException("fileName");


            if (string.IsNullOrEmpty(text))

                throw new ArgumentNullException("text");


            if (!Directory.Exists(filePath))

            {

                Directory.CreateDirectory(filePath);

                Thread.Sleep(100);

            }

            

            fileName = fileName + "_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";

            filePath = Path.Combine(filePath, fileName);


            text += "\r\n";

            //byte[] buffer = Encoding.Unicode.GetBytes(text);

            byte[] buffer = Encoding.UTF8.GetBytes(text);

            Int32 offset = 0;

            Int32 sizeOfBuffer = 4096;

            //FileStream fileStream = null;


            FileMode fileMode = FileMode.Append;

            if (!append)

                fileMode = FileMode.OpenOrCreate;


            try

            {

                using (FileStream fileStream = new FileStream(filePath, fileMode, FileAccess.Write,

                FileShare.None, bufferSize: sizeOfBuffer, useAsync: true))

                {

                    fileStream.Write(buffer, offset, buffer.Length);

                }


                intReturn = 1;

            }

            catch (Exception ex)

            {

                //Write code here to handle exceptions.

                string strMessage = ex.Message;

            }

            finally

            {

                //if (fileStream != null)

                //    fileStream.Dispose();

            }

            return intReturn;

        }


        static async Task<int> WriteLineAsync(string filePath, string fileName, string text, bool append = true)

        {

            int intReturn = 0;


            if (string.IsNullOrEmpty(filePath))

                throw new ArgumentNullException("filePath");


            if (string.IsNullOrEmpty(fileName))

                throw new ArgumentNullException("fileName");


            if (string.IsNullOrEmpty(text))

                throw new ArgumentNullException("text");


            if (!Directory.Exists(filePath))

            {

                Directory.CreateDirectory(filePath);

                Thread.Sleep(100);

            }


            fileName = fileName + "_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";

            filePath = Path.Combine(filePath, fileName);


            text += "\r\n";

            //byte[] buffer = Encoding.Unicode.GetBytes(text);

            byte[] buffer = Encoding.UTF8.GetBytes(text);

            Int32 offset = 0;

            Int32 sizeOfBuffer = 4096;

            //FileStream fileStream = null;


            FileMode fileMode = FileMode.Append;

            if (!append)

                fileMode = FileMode.OpenOrCreate;


            try

            {

                using (FileStream fileStream = new FileStream(filePath, fileMode, FileAccess.Write,

                FileShare.None, bufferSize: sizeOfBuffer, useAsync: true)){

                    await fileStream.WriteAsync(buffer, offset, buffer.Length);

                }


                //fileStream = new FileStream(filePath, fileMode, FileAccess.Write,

                //FileShare.None, bufferSize: sizeOfBuffer, useAsync: true);

                //await fileStream.WriteAsync(buffer, offset, buffer.Length);

                intReturn = 1;

            }

            catch(Exception ex)

            {

                //Write code here to handle exceptions.

                string strMessage = ex.Message;

            }

            finally

            {

                //if (fileStream != null)

                //    fileStream.Dispose();

            }

            return intReturn;

        }


    }


사용은 ...


        private async void WriteLog(string anyLocation, string logMessage, LogLevel level = LogLevel.INFO)

        {

            string strRootPath = Application.StartupPath;

            string strPath = Path.Combine(strRootPath, anyLocation+ "_Logs");


            await SystemLogger.WriteLogAsync(strPath, strFileName, logMessage, level);

        }


이렇게 별도의 함수를 만들어 호출하여 사용하면 되겠습니다.

매번 async 를 붙이기도 귀찮더라고요. ^^;


            WriteLog(anyLocation, "Write some Log.");


이제부터는 개떡같이 쓰여졌더라도 찰떡같이 알아 보시는 쎈스를 동원하시면 되겠습니다. 


다른 방법이 있다면 알려주셔요~ ^^



행복한 고수되셔요. ^^


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\













저작자 표시 비영리 변경 금지
신고

'.NET > C#' 카테고리의 다른 글

[C#] CreateDirectory  (0) 2017.11.15
[C#] Logging on File  (0) 2017.10.24
[C#] How do you check if a file is in use?  (0) 2017.07.27
[C#] 단일 Process 실행  (2) 2010.11.08
[C#] C# 은 VB.NET 따라쟁이...  (3) 2009.05.07
[C#] C# 컴파일러 오류  (0) 2009.03.06
Posted by woojja
2017.10.12 20:00

들어는 보셨을 Log4Net 을 소개해 드립니다.


Web 에서 간단하게 Log 를 쌓을 때 사용하던 녀석입니다.


이번 프로젝트는 WinForm 인데 Log 기능을 넣어달라고 하여 이 녀석을 추가해주려고 합니다.


일단은 파일로만 생성해 주렵니다.

공식웹사이트는 http://logging.apache.org/log4net 이며


GitHub Site 는 https://github.com/apache/logging-log4net/ 입니다.



Project 를 여시고요.

NuGet Manager Console 에서 


Install-Package log4net


이렇게 입력하시면 설치가 간단히 끝납니다.


그 다음은 app.config 또는 Web.config 파일에 Log4Net 을 사용하겠다고 알려주고요.


Log 에 대한 설정 사항을 입력해 주면 됩니다.


별도의 Log4Net.config 파일에 정의해 주어도 되겠습니다.


Log4Net.config 에서 설정을 관리하겠다면 첨부되어 있는 Logger.cs 파일의 initialize() 함수에서 처럼 로그를 관리하는 class 에 아래 구문을 추가해주시고요.


XmlConfigurator.ConfigureAndWatch(new FileInfo(logFilePath));


app.config 나 web.config 을 사용하시겠다면 

assemblyinfo.cs 이나 program.cs 파일에 아래 구문을 입력해 주셔요. ^^


[assembly: log4net.Config.XmlConfigurator(Watch = true)]



다음 설정은 App.Config 에 적어준 사항을 블로그에 맞게 약간 수정해서 기록합니다.


다른 사항들도 빼곡하게 적어 놓았는데 그 사항들을 여러분들이 사용하실때 주석을 풀어 사용하시면 되리라 생각하고 일단은 파일에 Log 를 쌓는 부분만 사용할 수 있게 주석을 풀어 놓았습니다.



<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <startup> 

    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>

  </startup>

  <runtime>

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

      <probing privatePath="DLL" />

    </assemblyBinding>

  </runtime>


  <configSections>

    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>

  </configSections>


  <log4net>


    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">


      <file type="log4net.Util.PatternString" value="Logs/%date{yyyy-MM-dd}_log4net.log"/>

      <datePattern value="yyyy-MM-dd"/>

      <appendToFile value="true" />

      <rollingStyle value="Date" />

      <staticLogFileName value="true" />

      <maxSizeRollBackups value="60" />

      <maximumFileSize value="15MB"/>

      <layout type="log4net.Layout.PatternLayout">

        <conversionPattern value="%d [%t] %-5p %c - %m%n" />

      </layout>


    </appender>

    

    <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">

      <bufferSize value="1" />

      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

      <connectionString value="Data Source=DataSourceName;Initial Catalog=DatabaseName;integrated security=True" />

      <commandText value="INSERT INTO SADT_Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />

      <parameter>

        <parameterName value="@log_date" />

        <dbType value="DateTime" />

        <layout type="log4net.Layout.RawTimeStampLayout" />

      </parameter>

      <parameter>

        <parameterName value="@thread" />

        <dbType value="String" />

        <size value="255" />

        <layout type="log4net.Layout.PatternLayout">

          <conversionPattern value="%thread" />

        </layout>

      </parameter>

      <parameter>

        <parameterName value="@log_level" />

        <dbType value="String" />

        <size value="50" />

        <layout type="log4net.Layout.PatternLayout">

          <conversionPattern value="%level" />

        </layout>

      </parameter>

      <parameter>

        <parameterName value="@logger" />

        <dbType value="String" />

        <size value="255" />

        <layout type="log4net.Layout.PatternLayout">

          <conversionPattern value="%logger" />

        </layout>

      </parameter>

      <parameter>

        <parameterName value="@message" />

        <dbType value="String" />

        <size value="4000" />

        <layout type="log4net.Layout.PatternLayout">

          <conversionPattern value="%message" />

        </layout>

      </parameter>

      <parameter>

        <parameterName value="@exception" />

        <dbType value="String" />

        <size value="2000" />

        <layout type="log4net.Layout.ExceptionLayout" />

      </parameter>

    </appender>

    

    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">

      <layout type="log4net.Layout.PatternLayout">

        <conversionPattern value="%d [%t] %-5p %c - %m%n" />

      </layout>

    </appender>

    <appender name="OutputDebugStringAppender" type="log4net.Appender.OutputDebugStringAppender">

      <layout type="log4net.Layout.PatternLayout">

        <conversionPattern value="%-5p %m - %c -%n" />

      </layout>

    </appender>

    <appender name="TraceAppender" type="log4net.Appender.TraceAppender">

      <layout type="log4net.Layout.PatternLayout">

        <conversionPattern value="%d [%t] %-5p %c - %m%n" />

      </layout>

    </appender>

    <appender name="AspNetTraceAppender" type="log4net.Appender.AspNetTraceAppender">

      <layout type="log4net.Layout.PatternLayout">

        <conversionPattern value="%d [%t] %-5p %c - %m%n" />

      </layout>

    </appender>


    <root>

      <level value="DEBUG" />


      <appender-ref ref="RollingFileAppender" />


      <!--

      <appender-ref ref="AdoNetAppender" />

      <appender-ref ref="ConsoleAppender" />

      <appender-ref ref="OutputDebugStringAppender" />

      <appender-ref ref="TraceAppender" />

      <appender-ref ref="AspNetTraceAppender" />

      -->

    </root>


  </log4net>

  

</configuration>




내용은 설명을 달아 놓아야 할까 싶을 정도로 간단합니다.

제가 굵게 표시한 글자들만 보셔도 아하~~ 하실거라 생각합니다.


설명을 안할까 생각중인데... 헤헤헤 

에헤~~ 한번 찬찬히 봐 보셔요. ^^

설명 필요없을거예요. 






행복한 고수되셔요. ^^


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
















저작자 표시 비영리 변경 금지
신고

'Tools' 카테고리의 다른 글

[Tools] GUID Maker Updated.  (0) 2017.10.31
[Tools] Log4Net  (0) 2017.10.12
[Tools] DotNetZip  (0) 2017.10.10
[Tools] 3 Ways to Change Bitrate on MP3 Files  (0) 2017.09.08
[Tools] NShape  (0) 2017.06.28
[Tools] GUID Maker  (0) 2017.06.21
Posted by woojja
2017.10.12 10:50


File Header 정보를 확인해 볼 수 있는 페이지 입니다.


참고삼아 올려봅니다.



http://www.garykessler.net/library/file_sigs.html



행복한 고수되셔요 ^^


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\













저작자 표시 비영리 변경 금지
신고
Posted by woojja
2017.10.10 20:00

.NET Framework 에서 사용할 Zip library 로 DotNetZip 을 사용했습니다.


사용도 편하여 사용 code snippet ? 을 적어봅니다.


공식 Source Page 는 사용이 정지된 Codeplex 의 https://dotnetzip.codeplex.com/ 입니다.

해당 페이지에 사용법도 간단하게? 설명해 놓았습니다.


NuGet Package Manager 에서도 DotNetZip 이라는 Keyword 로 찾으시면 되겠습니다.

제가 사용한 Version 은 1.10.1 입니다.



참조 추가는 해주시고요.


using Ionic.Zip; 으로 사용을 시작하겠습니다.


using Ionic.Zip;


. . . 


string strFileName = string.Format("NewZip_{0}.zip", DateTime.Now.ToString("yyyyMMddHHmm"));

bool isOk = false;


saveFileDialog.CreatePrompt = false;

saveFileDialog.CheckFileExists = false;

saveFileDialog.CheckPathExists = true;

saveFileDialog.Filter = FileFilterZip;

saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

saveFileDialog.FileName = strFileName;


if (saveFileDialog.ShowDialog() == DialogResult.OK)

{

    strFileName = saveFileDialog.FileName;


    . . .


    using (ZipFile zip = new ZipFile { CompressionLevel = CompressionLevel.BestCompression })

    {

        . . . 

        strPath = Path.Combine(strFileFolderPath, "FileName.ext");


        if (File.Exists(strPath))

{

    // Zip 파일내에 FolderName 이라는 Folder 를 만들어 그 폴더 내에 저장합니다.

            zip.AddFile(fi.FullName, "FolderName"); 


            // Zip 파일의 Root 에 저장됩니다.

            // zip.AddFile(strPath, ""); 


            // 이렇게 하시면 System 의 Folder 구조대로 Zip 파일에 포함됩니다. 

            // 경로의 앞부분은 잘립니다.

    // 어느 Depth 에서 잘리는지 확인하지 못했네요. 직접 확인해보시길... ^^;

            // zip.AddFile(strPath); 

}


        if (Directory.Exists(strFolderPath))

{

    // Directory 를 Zip 파일에 포함하고자 할 때 사용하는 구문이겠죠?

            zip.AddDirectory(strFolderPath, strFolderName);


    // 이렇게 하시면 System 의 Folder 구조대로 Zip 파일에 포함됩니다. 

    // 이 경우도 마찬가지로 경로의 앞부분은 잘립니다. ^^;

            // zip.AddDirectory(strFolderPath); 

        }


string strRootPath = dirRoot.FullName;

        foreach (var d in dirRoot.GetDirectories())

        {

            // 이렇게도 사용할 수 있습니다.

    // 이렇게하면 Zip 파일내에 New_Folder 라는

    // Directory 를 생성하고 그 아래에 d Directory를 포함시킵니다.

    zip.AddDirectory(d.FullName, "New_Folder" 

+ d.FullName.Replace(strRootPath, string.Empty));

        } 

        . . .


        zip.Save(strFileName);

        isOk = true;

    }


    if (isOk)

    {

        DialogResult result = MessageBox.Show("Completed Export Work.\n\t Do you want to open result file's location?", "Network Designer", MessageBoxButtons.OKCancel);

        //압축에 성공했으니 압축결과물을 봐야겠죠? ^^


        if (result == DialogResult.OK)

        {

            if (File.Exists(strFileName))

            {

                Process.Start(new ProcessStartInfo("explorer.exe", " /select, " + strFileName));

            }

        }

    }

}


사이트에 설명이 되어 있는 내용도 있고 제가 요리조리 잔머리 굴리며 작성한 내용입니다.

Folder 이름이나 파일명을 바꾸느라 코드에 오류가 있을 수도 있습니다. ^^;

오류가 있더라도 큰 줄기만 잘 살펴보시고...

도움이 되었으면 합니다.



행복한 고수되셔요.


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\













저작자 표시 비영리 변경 금지
신고

'Tools' 카테고리의 다른 글

[Tools] GUID Maker Updated.  (0) 2017.10.31
[Tools] Log4Net  (0) 2017.10.12
[Tools] DotNetZip  (0) 2017.10.10
[Tools] 3 Ways to Change Bitrate on MP3 Files  (0) 2017.09.08
[Tools] NShape  (0) 2017.06.28
[Tools] GUID Maker  (0) 2017.06.21
Posted by woojja
TAG DotNetZip

티스토리 툴바