GUID Maker 를 수정했습니다.

(http://jumptovb.net/search/guidmaker 를 참고하셔요.)

 

 

필요한 사항이 있어서요. ^^

 

 

수정사항은 Hyphen 표시 유무 입니다. ^^

Source 는 링크를 Click 하시면 GitHub 로 이동합니다.

 

 

GUID Maker Source

 

 

 

 

 

GUID Maker 2 Source

 

 

다음 Update 시에는 두개를 합쳐야겠습니다. ^^

 

 

행복한 고수되셔요.













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

'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.27 21:00

tutorialspoint 에서 배포한 MVVM PDF 문서를 우리말로 바꾸어 보려고 합니다.

엉망이니 참고만 하시기 바랍니다.

 

###############################################################################

 

1. MVVM – 소개

 

코드를 잘 정리하고 가장 잘 재사용할 수 있도록 조직화 하는 방법은 'MVVM' pattern 을 사용하는 것입니다.

Model, View, ViewModel (MVVM pattern) 은 여러분이 유지보수 가능하고, 테스트가 가능하며 확장가능한 application 을 작성할 수 있도록 코드를 조직화하고 구조하는 방법으로  안내합니다.

 

Model : data 의 정보를 가지고 있으며 business logic 과는 아무런 작업도 하지 않습니다.

ViewModel : Model 과 ViewModel 사이에서 Link/connection 으로서의 역할을 하며 꽤 멋지게 보이게 합니다.

View : 형식화된 data 를 가지고 있으며 특히나 모든것을 Model 에 위임 (delegate) 합니다.

 

 

분리된(Seperated) Presentation

code-behind 나 XAML 의 application logic 에서 야기된 문제들을 피하기 위해서 분리된 presentation 이라고 알려진 기술을 사용하는 것이 최선입니다.

이런 문제점을 피하기 위해서 User interface object 와 직접 작업하는데 필요한 XAML 과 Code-behind 를 최소한으로 할 것입니다.

 

다음 그림의 왼쪽을 보는 것 처럼 User interface class 들은 복잡한 interaction behaviors, application logic 과 모든 것을 위한 코드를 포함하고 있습니다. 

 

 

 

 

  • 분리된 presentation 기술로 User interface class 는 더욱 단순해집니다.  XAML 을 가지고 있습니다. 하지만 Code-behind 는 실용적으로 적습니다.
  • application logic 이 별도의 class 내에 들어가 있으며 이는 종종 model 로 언급됩니다.

 

  • 하지만 이는 전체 이야기가 아닙니다. 여기서 그만두면 여러분은 data binding 방식을 잃어버리는  매우 흔한 실수를 반복하게 될 것입니다. (However, this is not the whole story. If you stop here, you're likely to repeat a very common mistake that will lead you down the path of data binding insanity)
  • 많은 개발자들이 XAML 에서 data binding 을 사용하여 element 를 직접 model 의 properties 와 연결하기를 시도합니다.

 

  • 때때로 이 방법은 괜찮을수 있습니다. 하지만 그렇지 않을 수 있습니다. Model 은 application 의 동작과 관련이 있지 사용자가 application 과 상호작용하는 방법과는 관련이 없다는 것이 문제입니다.

 

  • Data 를 표현하는 방식은  내부적으로 구조화된 방식과 다소 다릅니다. 게다가 대부분의 user interface 는 application model 이 가지고 있지 않은 몇몇 state 를 가지고 있습니다.

 

  • 예를 들어 만약 user interface 가 drag and drop 을 사용한다면 Drag 되는 항목의 현재 위치는 어디인지,  drop 할 수 있는 target 의 위로 이동했을 때 모양은 어떻게 바뀌는지, target 또한 어떻게 바뀌어야하는지 같은 것들을  추적해야합니다.

 

  • 이런 state 는 놀라울정도록 복잡할 수 있고 철저한 테스트가 필요합니다.

 

  • 실제로 여러분은 User interface 와 Model 사이에 어떤 다른 class 가 있길 원합니다. 여기에는 두가지 중요한 role 이 있습니다.
    • 첫째, 특정 User interface view 를 위한 application model 을 채택합니다.
    • 둘째, 자잘한 interaction logic 이 존재하는 곳이며 그 코드는 여러분이 원하는 방식으로 user interface 가 작동하도록 합니다.

 

######################################################

 

이상입니다. 우리말이 너무 어렵네요. 

머리로는 이해가 가는데 말로 표현하려니...

 

제가 잘 몰라서겠죠...

 

영어도 못하고 우리말도 못하고... ㅡㅡ;

 

 

행복한 고수되셔요.

 

woojja ))*

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













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

'MVVM' 카테고리의 다른 글

[MVVM] 1. 소개  (0) 2017.10.27
Posted by woojja

 

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

 수많은 의존관계에 있는 JS 파일을 웹에 배포하는 것이 그리 쉬운일이 아닐겁니다.


이때 사용하는 것이 WebPack Module Bundler 입니다.


설치는 


npm install -g webpack


사용은 


webpack "WoojjaCustomer.js" "Bundle.js" --output-library='WoojjaLibrary'



webpack 에게 시작 JS 파일을 알려주면 참조관계에 맞추어 Bundle JS 파일을 생성해주며, WoojjaLibrary 라는 이름의 component 를 생성해줍니다.



HTML 에서의 사용은 


<script src="Bundle.js"></script>

<script>

var x = new WoojjaLibrary.Customer();

x.Add();

</script>


접근하는데도 편리하겠죠? 


행복한 고수되셔요~ ^^


woojja ))*

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














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

'Web > JavaScript' 카테고리의 다른 글

[JavaScript] WebPack  (0) 2017.10.09
[JavaScript] SystemJS  (0) 2017.10.08
[JavaScript] Interval, Timeout  (0) 2017.02.11
[JavaScript] Markup Insertion  (0) 2017.02.10
[JavaScript] Pop Up 차단 확인  (0) 2017.01.26
[JavaScript] Browser 탐지 스크립트  (0) 2017.01.26
Posted by woojja
TAG webpack


JavaScript 사용시 JavaScript 파일의 참조와는 상관없이 SystemJS 에게 시작 JS 파일을 알려주면 알아서 참조되는 JavaScript 파일을 Loading 해줍니다.


설치는 

npm install systemjs



사용법은 


<script src="system.js"></script>

<script>

SystemJS.import('./Customer.js')

.then(function(module){

var cust = new module.Customer();

cust.Add();

}).catch(function (err)

{ console.error(err); });;

</script>


SystemJS.import 에서 시작 JS 파일을 알려주고 있습니다.


행복한 고수되셔요. ^^


woojja ))*

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













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

'Web > JavaScript' 카테고리의 다른 글

[JavaScript] WebPack  (0) 2017.10.09
[JavaScript] SystemJS  (0) 2017.10.08
[JavaScript] Interval, Timeout  (0) 2017.02.11
[JavaScript] Markup Insertion  (0) 2017.02.10
[JavaScript] Pop Up 차단 확인  (0) 2017.01.26
[JavaScript] Browser 탐지 스크립트  (0) 2017.01.26
Posted by woojja
TAG SystemJS


tsc -v 을 통해서 TypeScript 의 Version 을 확인합니다.

헌데 Version 이 1.0.3 으로 낮아서 update 를 하려해보지만 

Update 는 오류메세지 없이 진행되지만 tsc -v 로 확인해보면 

Version 이 낮은 상태로 변경이 되지 않는 경우가 있습니다.


이런 경우  "C:\Program Files (x86)\Microsoft SDKs\TypeScript\" 폴더로 들어가 

"C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.0" 폴더를 삭제해 줍니다.


저는 그냥 "1.0_" 로 폴더 명을 변경해 주었습니다.


그리고 tsc -v 로 확인하면 Version 이 올라간것을 확인 하실수 있을 겁니다.



행복한 고수되셔요~ ^^


woojja ))*

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













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

'Web > TypeScript' 카테고리의 다른 글

[TypeScript] TypeScript 의 version 이 변경되지 않을때...  (0) 2017.10.08
Posted by woojja
이전버튼 1 이전버튼

티스토리 툴바