Windows Service에서 디비깅을 쉽게 하는 방법


참조 URL
  1. http://devsw.tistory.com/153
  2. https://msdn.microsoft.com/ko-kr/library/cktt23yw.aspx
  3. http://www.codeproject.com/Articles/10153/Debugging-Windows-Services-under-Visual-Studio-NET
  4. http://blog.aliencube.org/ko/2014/04/30/developing-windows-service-with-topshelf/
  5. http://blogs.microsoft.co.il/alon_nativ/2011/02/01/creating-windows-service-using-topshelf/

 


1. 콘솔 프로그램을 사용하여 디버깅

[코드 1] 콘솔에서 디비깅 #1



[코드 2] 콘솔에서 디비깅 #2



위와 같이 별도의 프로젝트 또는 같은 프로젝트에서 위와 같이 구성하여 콘솔 실행으로 개발하고 디버깅을 시작할 수 있다.



2. "Diagnostics.Debugger" 사용하여 디버깅

[코드 3] 윈도우 서비스에서 디버깅



3. "Topshelf"를 사용하여 디버깅


[코드 4] Topshelf










브라우저에서 NTLM으로 로그인 하기


참조 URL
  1. https://github.com/erlandranvinge/ntlm.js
  2. https://github.com/erlandranvinge/ntlm.js/blob/master/ntlm.js

 



NTLM.js 라이브러리의 핵심은 UserName과 Password를 Base64로 인코딩하여 헤더에 추가하여 보내는 로직이다. 

ntlm.js 파일의 "Msg.prototype.toBase64 = function()" 통해서 인코딩하는 로직으로 확인할 수 있으며 "setCredentials"와 "authenticate"를 통해서 사용하면 된다.


Usage

Ntlm.setCredentials('domain', 'username', 'password');
var url = 'http://myserver.com/secret.txt';

if (Ntlm.authenticate(url)) {
    var request = new XMLHttpRequest();
    request.open('GET', url, false);
    request.send(null);
    console.log(request.responseText);
    // => My super secret message stored on server.
}

Setup

On the server side, the following CORS HTTP Response headers are required:

  • Access-Control-Allow-Headers: Authorization
  • Access-Control-Allow-Methods: GET, OPTIONS
  • Access-Control-Allow-Origin: *
  • Access-Control-Expose-Headers: WWW-Authenticate





























NHibernate and ASP.NET MVC - CRUD Operations


참조 URL
  1. http://www.dotnetjalps.com/2013/09/asp-net-mvc-nhibernate-crud-getting-started.html
  2. http://www.dotnetjalps.com/2014/07/fluent-nhibernate-asp-net-mvc-crud.html

 


이 문서에 대하여

이 문서는 원본 문서를 읽고, 따라하고, 변경 또는 수정없이 인용한 부분이 있으며 주석이나 추가 설명에 대해 가감을 하였습니다. 이 문서와는 별개로 별도의 원본이 있음을 알려 드리며 원본에 대한 자세한 사항은 참조 URL에 있음을 알려 드립니다. 오역, 어색한 부분, 매끄럽지 않은 부분이 있을 경우 알려주시면 적극적으로 반영하도록 하겠습니다.





   실습 준비 사항


  • Visual Studio 2013
  • ASP.NET MVC5
  • LocalDB 11 




 NHibernate를 통해 ASP.NET MVC에서 간단한 CRUD를 해보도록 하겠다. 우선 준비 사항으로 데이터 베이스가 필요하여 아래와 같이 Employee테이블을 만들었다. '코드1'에서 관련 Query가 있으니 SQL Server Management Studio에서 실행하여 테이블을 생성할 수 있도록 하였다.



[그림1] Employee Table




CREATE TABLE [dbo].[Employee](
	[Id] [intIDENTITY(1,1NOT NULL,
	[FirstName] [nvarchar](50NULL,
	[LastName] [nvarchar](50NULL,
	[Designation] [nvarchar](50NULLON [PRIMARY]

[코드1] Create query Employee table 





 이제 준비가 되었으면 아래와 같이 웹 프로젝트를 만들어 보자.



[그림2] ASP.NET MVC template




[그림3] ASP.NET MVC Web API 선택



NHibernate 관련 DLL을 참조 하여야 한다. 참조 방법은 PM( Tools -> NuGet Package Manager -> Package Manager Console )에서 "Install-Package NHibernate"를 입력하면 참조가 된다.
( "그림4"에서는 이미 참조가 되어 있는 관계로 처음 참조하는 화면과는 다르며 예시를 하기 위함입니다. )




[그림4] Package Manager Console




NHibernate에서 사용하는 Config 파일을 Models폴더에 추가 하자. 추가할 파일명은 "Hibernate.cfg.xml"로 한다.


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">
      NHibernate.Connection.DriverConnectionProvider
    </property>
    <property name="connection.driver_class">
      NHibernate.Driver.SqlClientDriver
    </property>
    <property name="connection.connection_string">
      Server=(LocalDB)\v11.0;Integrated Security=true;AttachDbFileName=C:\Users\천호\NHibernateTest.mdf
    </property>
    <property name="dialect">
      NHibernate.Dialect.MsSql2012Dialect
    </property>
  </session-factory>
</hibernate-configuration>

[코드2] NHibernate.cfg.xml



이제 Employee 관련 모델 클래스를 만든다.


public class Employee
{
    public virtual int Id { getset; }
    public virtual string FirstName { getset; }
    public virtual string LastName { getset; }
    public virtual string Designation { getset; }
}

[코드3] Employee model class



이제 모델 클래스와 DB의 Table과 매칭시켜 주는 파일을 Models 폴더에 추가해야 한다. 파일명은 "Employee.hbm.xml"로 한다.


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="NHibernateTest" namespace="NHibernateTest.Models">
  <class name="Employee" table="Employee" dynamic-update="true" >
    <cache usage="read-write"/>
    <id name="Id" column="Id" type="int">
      <generator class="native" />
    </id>
    <property name="FirstName" />
    <property name="LastName" />
    <property name="Designation" />
  </class>
</hibernate-mapping>

[코드4] Employee.hbm.xml




NHibernate을 접근하기 위한 Helper 클래스를 만든다.


public static ISession OpenSession()
{
    var configuration = new Configuration();
    // Configue 파일에 대한 정보
    var configurationPath = HttpContext.Current.Server.MapPath(@"~\Models\hibernate.cfg.xml");
    configuration.Configure(configurationPath);
 
    // 매칭 정보에 관한 파일
    var employeeConfigurationFile = HttpContext.Current.Server.MapPath(@"~\Models\Employee.hbm.xml");
            
    configuration.AddFile(employeeConfigurationFile);
    ISessionFactory sessionFactory = configuration.BuildSessionFactory();
    return sessionFactory.OpenSession();
}

[코드5] NHibernateSession Helper 클래스


 위 코드에서 MapPath를 통해 설정 정보와 매칭 정보가 있는 파일 정보를 세션 객체를 초기화 하는 작업이다. 이제 기본적인 준비 작업은 마무리가 되었으며 Controller에서 CRUD를 해보도록 하겠다.



public ActionResult Index()
{
	using (ISession session = NHibertnateSession.OpenSession())
	{
		var employees = session.Query<Employee>().ToList();
		return View(employees);
	}
}
 
public ActionResult Create()
{
	return View();
}
 
 
[HttpPost]
public ActionResult Create(Employee emplolyee)
{
	try
	{
		using (ISession session = NHibertnateSession.OpenSession())
		{
			using (ITransaction transaction = session.BeginTransaction())
			{
				session.Save(emplolyee);
				transaction.Commit();
			}
		}
 
		return RedirectToAction("Index");
	}
	catch (Exception exception)
	{
		return View();
	}
}
 
public ActionResult Edit(int id)
{
	using (ISession session = NHibertnateSession.OpenSession())
	{
		var employee = session.Get<Employee>(id);
		return View(employee);
	}
 
}
 
 
[HttpPost]
public ActionResult Edit(int idEmployee employee)
{
	try
	{
		using (ISession session = NHibertnateSession.OpenSession())
		{
			var employeetoUpdate = session.Get<Employee>(id);
 
			employeetoUpdate.Designation = employee.Designation;
			employeetoUpdate.FirstName = employee.FirstName;
			employeetoUpdate.LastName = employee.LastName;
 
			using (ITransaction transaction = session.BeginTransaction())
			{
				session.Save(employeetoUpdate);
				transaction.Commit();
			}
		}
		return RedirectToAction("Index");
	}
	catch
	{
		return View();
	}
}
 
public ActionResult Details(int id)
{
	using (ISession session = NHibertnateSession.OpenSession())
	{
		var employee = session.Get<Employee>(id);
		return View(employee);
	}
}
 
public ActionResult Delete(int id)
{
	using (ISession session = NHibertnateSession.OpenSession())
	{
		var employee = session.Get<Employee>(id);
		return View(employee);
	}
}
 
 
[HttpPost]
public ActionResult Delete(int idEmployee employee)
{
	try
	{
		using (ISession session = NHibertnateSession.OpenSession())
		{
			using (ITransaction transaction = session.BeginTransaction())
			{
				session.Delete(employee);
				transaction.Commit();
			}
		}
		return RedirectToAction("Index");
	}
	catch (Exception exception)
	{
		return View();
	}
}

[코드6] EmployeeController




이제 View 페이지를 만든다.


@model NHibernateTest.Models.Employee
 
@{
    ViewBag.Title = "Create";
}
 
<h2>Create</h2>
 
 
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>Employee</h4>
        <hr />
        @Html.ValidationSummary(true)
 
        <div class="form-group">
            @Html.LabelFor(model => model.FirstNamenew { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.FirstName)
                @Html.ValidationMessageFor(model => model.FirstName)
            </div>
        </div>
 
        <div class="form-group">
            @Html.LabelFor(model => model.LastNamenew { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.LastName)
                @Html.ValidationMessageFor(model => model.LastName)
            </div>
        </div>
 
        <div class="form-group">
            @Html.LabelFor(model => model.Designationnew { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Designation)
                @Html.ValidationMessageFor(model => model.Designation)
            </div>
        </div>
 
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}
 
<div>
    @Html.ActionLink("Back to List""Index")
</div>
 
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

[코드7] Create




@model IEnumerable<NHibernateTest.Models.Employee>
 
@{
    ViewBag.Title = "Index";
}
 
<h2>Index</h2>
 
<p>
    @Html.ActionLink("Create New""Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.FirstName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.LastName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Designation)
        </th>
        <th></th>
    </tr>
 
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.FirstName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.LastName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Designation)
        </td>
        <td>
            @Html.ActionLink("Edit""Edit"new { id=item.Id }) |
            @Html.ActionLink("Details""Details"new { id=item.Id }) |
            @Html.ActionLink("Delete""Delete"new { id=item.Id })
        </td>
    </tr>
}
 
</table>

[코드8] Index




@model NHibernateTest.Models.Employee
 
@{
    ViewBag.Title = "Edit";
}
 
<h2>Edit</h2>
 
 
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>Employee</h4>
        <hr />
        @Html.ValidationSummary(true)
        @Html.HiddenFor(model => model.Id)
 
        <div class="form-group">
            @Html.LabelFor(model => model.FirstNamenew { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.FirstName)
                @Html.ValidationMessageFor(model => model.FirstName)
            </div>
        </div>
 
        <div class="form-group">
            @Html.LabelFor(model => model.LastNamenew { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.LastName)
                @Html.ValidationMessageFor(model => model.LastName)
            </div>
        </div>
 
        <div class="form-group">
            @Html.LabelFor(model => model.Designationnew { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Designation)
                @Html.ValidationMessageFor(model => model.Designation)
            </div>
        </div>
 
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}
 
<div>
    @Html.ActionLink("Back to List""Index")
</div>
 
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

[코드9] Edit




@model NHibernateTest.Models.Employee
 
@{
    ViewBag.Title = "Details";
}
 
<h2>Details</h2>
 
<div>
    <h4>Employee</h4>
	<hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.FirstName)
        </dt>
 
        <dd>
            @Html.DisplayFor(model => model.FirstName)
        </dd>
 
        <dt>
            @Html.DisplayNameFor(model => model.LastName)
        </dt>
 
        <dd>
            @Html.DisplayFor(model => model.LastName)
        </dd>
 
        <dt>
            @Html.DisplayNameFor(model => model.Designation)
        </dt>
 
        <dd>
            @Html.DisplayFor(model => model.Designation)
        </dd>
 
    </dl>
</div>
<p>
    @Html.ActionLink("Edit""Edit"new { id = Model.Id }) |
    @Html.ActionLink("Back to List""Index")
</p>

[코드10] Details




@model NHibernateTest.Models.Employee
 
@{
    ViewBag.Title = "Delete";
}
 
<h2>Delete</h2>
 
<h3>Are you sure you want to delete this?</h3>
<div>
    <h4>Employee</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.FirstName)
        </dt>
 
        <dd>
            @Html.DisplayFor(model => model.FirstName)
        </dd>
 
        <dt>
            @Html.DisplayNameFor(model => model.LastName)
        </dt>
 
        <dd>
            @Html.DisplayFor(model => model.LastName)
        </dd>
 
        <dt>
            @Html.DisplayNameFor(model => model.Designation)
        </dt>
 
        <dd>
            @Html.DisplayFor(model => model.Designation)
        </dd>
 
    </dl>
 
    @using (Html.BeginForm()) {
        @Html.AntiForgeryToken()
 
        <div class="form-actions no-color">
            <input type="submit" value="Delete" class="btn btn-default" /> |
            @Html.ActionLink("Back to List""Index")
        </div>
    }
</div>

[코드11] Delete




이제 모든 준비가 되었으니 확인해 보도록 한다.



이 프로젝테에서 사용하는 DB는 LocalDB V11 을 사용하였다. Hibernate.cfg.xml 파일에서  "AttachDbFileName" 부분을 자신의 환경에 맞게 수정해야 한다.




[그림2] List





[그림3] Edit





Source Download

NHibernateTest.zip





Model Binding using IModelBinder and DefaultModelBinder in ASP.NET MVC


참조 URL
  1. http://www.codeproject.com/Tips/806415/Model-Binding-using-IModelBinder-and-DefaultModelB

 


이 문서에 대하여

이 문서는 원본 문서를 읽고, 따라하고, 변경 또는 수정없이 인용한 부분이 있으며 주석이나 추가 설명에 대해 가감을 하였습니다. 이 문서와는 별개로 별도의 원본이 있음을 알려 드리며 원본에 대한 자세한 사항은 참조 URL에 있음을 알려 드립니다. 오역, 어색한 부분, 매끄럽지 않은 부분이 있을 경우 알려주시면 적극적으로 반영하도록 하겠습니다.



ASP.NET MVC에서 기본으로 제공되는 모델 바인더가 있어서 컨트롤러에서 클래스로 변환되어 사용할 수 있도록 해주고 있다. 일반적인 케이스에서는 잘 동작하고 있지만 모델과 HTML의 Name이 일치하지 않을경우 커스텀 모델 바인더를 통해 해결 할 수 있는 방법을 제공해 주고 있다. 'IModelBinder' 인터페이스를 상속받아 구현된 클래스를 통해 이와같은 기능을 대체할 수 있도록 한다. 


public interface IModelBinder
{
    object BindModel(ControllerContext controllerContextModelBindingContext bindingContext);
}

[코드1] IModelBinder interface



 IModelBinder 인터페이스는 object를 반환하는 BindModel이 선언되어 있어서 이 메소드만 구현하면 원하는 방법으로 바인딩을 할 수 있다. 우선 모델 클래스를 선언하는 것부터 시작하자!


public class Person
{
    [Required]
    [MaxLength(50ErrorMessage = "Full name should be within 50 character")]
    public string full_name { getset; }
 
    [Range(1880)]
    [Required(ErrorMessage = "Please provide age")]
    public Int32 Age { getset; }
}

[모드2] Person Model class



 위와 같이 모델 클래스를 선언하고 IModelBinder을 상속받아 아래와 같이 Form객체에서 값을 가져와 Person객체를 반환하는 코드를 작성하자.



public class PersonModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContextModelBindingContext bindingContext)
    {
        var request = controllerContext.HttpContext.Request;
 
        string first_name = request.Form.Get("first_name");
        string middle_name = request.Form.Get("middle_name");
        string last_name = request.Form.Get("last_name");
        int Age = Convert.ToInt32(request.Form.Get("age"));
        return new Person { full_name = first_name + middle_name + last_nameAge = Age };
    }
}

[코드3] PersonModelBinder class




 이제 웹페이지에서 확인할 수 있도록 UI 관련 코드를 작성하자. 아래와 같이 CustomodelbinderController 클래스를 작성하고 PostData View 페이지를 추가하자.



public class CustomodelbinderController : Controller
{
    //
    // GET: /Customodelbinder/
    public ActionResult Index()
    {
        return View();
    }
 
    public ActionResult PostData()
    {
        return View();
    }
 
    [HttpPost]
    public void PostData([ModelBinder(typeof(PersonModelBinder))] Person person)
    {

    }

[코드4] CustomodelbinderController class


 위 코드에서 주의할 부분이 PostData의 입력 인자에서 Parameter Attribute를 선언하여 명시적으로 PersonModelBinder를 사용하도록 선언을 해야 한다.



@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        @{Html.BeginForm("PostData""Customodelbinder");
        <table>
            <tr>
                <td>First Name : </td>
                <td>@Html.TextBox("first_name")</td>
            </tr>
            <tr>
                <td>Middle Name : </td>
                <td>@Html.TextBox("middle_name")</td>
            </tr>
            <tr>
                <td>Surname :</td>
                <td> @Html.TextBox("last_name")</td>
            </tr>
            <tr>
                <td>Age:</td>
                <td> @Html.TextBox("age"</td>
            </tr>
            <tr>
                <td></td>
                <td>
                    <input type="submit" name="Save" value="Save" />
                </td>
            </tr>
        </table>
        }
    </div>
</body>
</html>

[코드5] CustomodelbinderController 의 PostData View 페이지



이제 완료가 되었으니 "http://localhost:????/Customodelbinder/PostData"와 같은 주소로 지금까지의 코드를 확인해 보도록 하자.



[그림1] 입력 화면







[그림2] PersonModelBinder 값 확인




[그림3] Controller에서 값 확인



 위와 같이 ModelBinder 단과 Controller단에서 기대하는 값을 확인 할 수 있다.





사용자가 수정한 커스텀 바인더를 ASP.NET MVC에서 인식하여 사용할 수 있는 방법이 아래오 같이 두가지가 있다.


  1. Parameter Attribute

  2. Global.asax에서 ModelBinders에 등록


첫번째는 위 "코드4"에서 언급이 되었듯 

public void PostData([ModelBinder(typeof(PersonModelBinder))] Person person)

이 사용할 수 있고 아래와 같이 추가하여 사용할 수 있다.

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
 
        ModelBinders.Binders.Add(typeof(Person), new PersonModelBinder()); // <- 추가 코드
    }
}

[코드6] Global.asax









여담으로 IModelBinder 인터페이스 대신에 DefaultModelBinder 클래스를 상속받아 같은 기능을 실현 할 수 있다.

public class PersonDefaultModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContextModelBindingContext bindingContext)
    {
        var request = controllerContext.HttpContext.Request;
 
        string first_name = request.Form.Get("first_name");
        string middle_name = request.Form.Get("middle_name");
        string last_name = request.Form.Get("last_name");
        int Age = Convert.ToInt32(request.Form.Get("age"));
        return new Person { full_name = first_name + middle_name + last_nameAge = Age };
    }
}





Source Download


IModelBinderWebApplication.zip







새로운 버전의 ASP.NET MVC 5.2, Web API 2.2 and Web Pages 3.2가 발표가 되었다


참조 URL
  1. http://blogs.msdn.com/b/webdev/archive/2014/07/02/announcing-the-release-of-asp-net-mvc-5-2-web-api-2-2-and-web-pages-3-2.aspx

 



이 문서에 대하여

이 문서는 원본 문서를 읽고, 따라하고, 변경 또는 수정없이 인용한 부분이 있으며 주석이나 추가 설명에 대해 가감을 하였습니다. 이 문서와는 별개로 별도의 원본이 있음을 알려 드리며 원본에 대한 자세한 사항은 참조 URL에 있음을 알려 드립니다. 오역, 어색한 부분, 매끄럽지 않은 부분이 있을 경우 알려주시면 적극적으로 반영하도록 하겠습니다.





 2014.07.02에 "ASP.NET MVC 5.2, Web API 2.2 and Web Pages 3.2"에 새로운 버전이 발표가 되면서 자잘한 기능들에서 개선 사항들이 반영이 되었으며 Web Pages 3.2.1에서는 성능 적인 면에서 기존보다 개선되어 있는 것을 확인할 수 있다. ( http://www.asp.net/web-pages/overview/releases/whats-new-in-aspnet-web-pages-321 )



  • ASP.NET MVC 5.2

    • 개선된 Attribute 라우팅

    • 기능 업데이트

    • 버그 수정

  • ASP.NET Web API 2.2

    • OData V4 지원

    • 개선된 Attribute 라우팅

    • Windows Phone 8.1용 클라이언트 지원

    • 기능 업데이트

    • 버그 수정

  • ASP.NET Web Pages 3.2

    • 기능 업데이트

    • 버그 수정




이 버전을 프로젝트에 반영하기 위해서는 아래와 같이 PM에서 실행해 주면 된다.


  • Install-Package Microsoft.AspNet.Mvc -Version 5.2.0
  • Install-Package Microsoft.AspNet.WebApi -Version 5.2.0
  • Install-Package Microsoft.AspNet.WebPages -Version 3.2.0













Visual Studio "14" CTP Now Available


참조 URL
  1. http://blogs.msdn.com/b/csharpfaq/archive/2014/06/03/visual-studio-14-ctp-now-available.aspx
  2. http://www.visualstudio.com/en-us/downloads/visual-studio-14-ctp-vs
  3. http://go.microsoft.com/fwlink/?LinkId=399010
  4. http://msdn.microsoft.com/en-us/library/zzszcehe.aspx

 



 Visual studio 2013의 차기 버전이 '14' CTP가 나왔다.  추가된 대표 기능으로 는 아래와 같다.

  • C# and VB with the .NET Compiler Platform ("Roslyn")
    (open-source compiler as a service)

  • ASP.NET vNext

  • C++ 11/14

이 밖에도 자잘하게 C#을 위한 리팩토링 기능이 향상 되었으며, 웹 탬플릿(vNext) 추가등 여러가지 자잘한 기능 향상이 되었다.



 

 

 

 

 그리고 마지막으로 쉽게 피드백을 보낼 수 있는 방법으로 Send a smile로 쉽게 보낼 수 있는 기능이 있다.

 

 

 








 

Entity Framework사용 시 편리한 테스트 방법


참조 URL
  1. http://msdn.microsoft.com/en-US/data/dn314429
  2. https://github.com/rowanmiller/EntityFramework.Testing/wiki
  3. 페이스 북의 "Gyuwon Yi"님이 소개를 해줘서 알게된 프레임워크

 


 Entity Framework를 통해 DB 컨트롤을 하는 객체를 만들었을 때 Mock을 통해 쉽게 테스트를 할 수 있는 프레임웍을 소개 하고자 한다. rowanmiller가 GitHub에 올려둔 "EntityFramework.Testing"를 살펴 보면 간단한 사용 방법을 보여주고 있다. 아래 코드는 테스트 부분만 따로 떼어내서 간단한 부연 설명을 주석으로 추가 하였다.


var data = new List<Blog>
{
    new Blog{ Name = "BBB" },
    new Blog{ Name = "CCC" },
    new Blog{ Name = "AAA" }
};

[코드1] 데이터 원본


'코드1'에서와 같은 데이터에서 Mock을 통해 DBContext를 만들기 위해서는 '코드2' 에서와 같이 해줘야 했으나 "EntityFramework.Testing"를 사용하면 "코드3"와 같은 코드로 대체할 수 있다.


var mockSet = new Mock<DbSet<Blog>>(); mockSet.As<IQueryable<Blog>>().Setup(m =>m.Provider).Returns(data.Provider); mockSet.As<IQueryable<Blog>>().Setup(m =>m.Expression).Returns(data.Expression); mockSet.As<IQueryable<Blog>>().Setup(m =>m.ElementType).Returns(data.ElementType); mockSet.As<IQueryable<Blog>>().Setup(m =>m.GetEnumerator()).Returns(data.GetEnumerator()); var mockContext = new Mock<BloggingContext>(); mockContext.Setup(c => c.Blogs).Returns(mockSet.Object); 

[코드2] 기존 초기화 코드


var set = new MockDbSet<Blog>()
    .SetupSeedData(data)
    .SetupLinq();

[코드3] 변경된 초기화 코드




 테스트 및 직접 확인할 수 있는 코드를 '코드4~6'를 통해 직접 확인해 보기를 바란다.




public class BloggingContext : DbContext
{
    public virtual DbSet<Blog> Blogs { getset; }
    public virtual DbSet<Post> Posts { getset; }
}
 
public class Blog
{
    public int BlogId { getset; }
    public string Name { getset; }
    public string Url { getset; }
 
    public virtual List<Post> Posts { getset; }
}
 
public class Post
{
    public int PostId { getset; }
    public string Title { getset; }
    public string Content { getset; }
 
    public int BlogId { getset; }
    public virtual Blog Blog { getset; }
}

[코드4] 기본 Entity 클래스 선언



public class BlogsController : Controller
{
    private readonly BloggingContext db;
 
    public BlogsController(BloggingContext context)
    {
        db = context;
    }
 
    public async Task<ViewResult> Index()
    {
        var query = db.Blogs.OrderBy(b => b.Name);
 
        return View(await query.ToListAsync());
    }
}

[코드5] 테스트할 클래스 생성


// https://github.com/rowanmiller/EntityFramework.Testing/wiki [TestClass] public class EntityFrameworkTest {     [TestMethod]     public async Task Index_returns_blogs_ordered_by_name()     {         // 테스트 데이터 생성 - Arrange         var data = new List<Blog>         {             new Blog{ Name = "BBB" },             new Blog{ Name = "CCC" },             new Blog{ Name = "AAA" }         };         // Mock를 통해 Context 세팅 -- Act         // Mock객체가 반환할 객체 단위를 List<Blog>에서 가져오도록 세팅한 것이다.         var mockSet = new MockDbSet<Blog>()             .SetupSeedData(data)            .SetupLinq();

// 기존 초기화 세팅 //var mockSet = new Mock<DbSet<Blog>>(); //mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider); //mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression); //mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType); //mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

        var context = new Mock<BloggingContext>();         context.Setup(c => c.Blogs).Returns(mockSet.Object);         // BlogsController 의  Index를 실행         var controller = new BlogsController(context.Object);         var result = await controller.Index();         // 결과값 확인 - Assert         var blogs = (List<Blog>)result.Model;         Assert.AreEqual(3, blogs.Count());         Assert.AreEqual("AAA", blogs[0].Name);         Assert.AreEqual("BBB", blogs[1].Name);         Assert.AreEqual("CCC", blogs[2].Name);     } }

[코드6] 테스트 코드








A C# 6.0 Language Preview


참조 URL
  1. http://msdn.microsoft.com/en-us/magazine/dn683793.aspx

 


example





MS 요즘 빠른 행보와 C# 6.0 버전이 출시를 할거 같습니다.
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

 

A C# 6.0 Language Preview

http://msdn.microsoft.com/en-us/magazine/dn683793.aspx

 

중에 프로퍼티의 선언과 초기화가 좀더 단순화 있도록 개선이 되네요

 

지금까지는 private public 변수를 각각 선언해서 초기화를 시켰는데 아래와 같이 초기화를 한줄로 있을 합니다.

 

 

 

Auto-Properties with Initializers

Initializing a class today can be cumbersome at times. Consider, for example, the trivial case of a custom collection type (such as Queue<T>) that internally maintains a private System.Collections.Generic.List<T> property for a list of items. When instantiating the collection, you have to initialize the queue with the list of items it is to contain. However, the reasonable options for doing so with a property require a backing field along with an initializer or an else constructor, the combination of which virtually doubles the amount of required code.


With C# 6.0, there’s a syntax shortcut: auto-property initializers. You can now assign to auto-properties directly, as shown here:


1.      class Queue<T>

2.      {

3.        private List<T> InternalCollection { get; } = 

4.          new List<T>; 

5.        // Queue Implementation

6.        // ...

7.      }

 

 

 

그리고 JSON Data 쉽게 다룰 있는 JObject라는 타입이 새로 나왔습니다.

 

 

 

Figure 3 Leveraging the Indexed Method with JSON Data

1.      using Microsoft.VisualStudio.TestTools.UnitTesting;

2.      using Newtonsoft.Json.Linq;

3.      // ...

4.      [TestMethod]

5.      public void JsonWithDollarOperatorStringIndexers()

6.      {

7.        // Additional data types eliminated for elucidation

8.        string jsonText = @"

9.          {

10.        'Byte':  {

11.          'Keyword':  'byte',

12.          'DotNetClassName':  'Byte',

13.          'Description':  'Unsigned integer',

14.          'Width':  '8',

15.          'Range':  '0 to 255'

16.                  },

17.        'Boolean':  {

18.          'Keyword':  'bool',

19.          'DotNetClassName':  'Boolean',

20.          'Description':  'Logical Boolean type',

21.          'Width':  '8',

22.          'Range':  'True or false.'

23.                    },

24.      }";

25.    JObject jObject = JObject.Parse(jsonText);

26.    Assert.AreEqual("bool", jObject.$Boolean.$Keyword);

27.  }

 



총 10가지 정도가 프리뷰에서 보여졌는데요. 그 중에 크게 변한 2가지 부분을 우선 소개하고 좀더 자세한 사항은 링크를 타고 들어가서 확인하시면 될거 같습니다.





 








손 코딩 뇌 컴파일 눈 디버깅


참조 URL
  1. 손코딩뇌컴파일눈디버깅
  2. http://www.slideshare.net/kwangswei/ss-30510586
  3. http://community.topcoder.com/
  4. http://kwangswei.tistory.com/421

 


 논리적인 사고와 문제 해결능력을 배양 시키는 방법을 소개하고 있다. 손으로 코딩하고 뇌로 컴파일하고 눈으로 디버깅을 하는 연습으로 자신의 능력을 배양 할 수 있을것이다.














C#에서 Enum 타입을 다중값으로 활용 - Flags


참조 URL
  1. http://msdn.microsoft.com/ko-kr/library/cc138362.aspx
  2. http://msdn.microsoft.com/en-us/library/system.enum.hasflag(v=vs.110).aspx
  3. http://stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c

 


 C#에서 Enum 타입으로 선언해서 프로그래밍을 할 때 하나의 값 대신 복수의 상태를 표시해야 할 때 사용할 수 있는 방법입니다. Enum을 선언시 아래와 같이 Attribute를 달아주면 복수의 상태를 사용할 수 있는 상태가 됩니다.



[코드1] Enum 선언과 사용 방법 ( OR 연산으로 값 추가 )



 위와 같이 선언하고 사용할 수 있으며 선언된 값을 판단하여 사용하는 방법은 아래와 같습니다.


[코드2] & 연산으로 값 비교




[코드3] XOR 연산으로 값 해제




example

[코드4] 다른 방식으로 선언 방법



[코드] 또 다른 선언 방법










 








+ Recent posts