Programming/.NET

1. 인라인 헬퍼 메서드

 

만들고자 하는 헬퍼 메서드를 뷰내부에 특정 이름으로 정의하고 정의된 메서드를 같은 뷰안에서 호출하는 방식으로 사용되는 메서드입니다.

 

@{
    ViewBag.Title = "Index";
}

@helper Sum(int iint j) {
    <span>결과 => @(i  + j)</span>
}

<h2>Index</h2>

계산 : @Sum(10, 20)

 

인라인 헬퍼메서드는 @Helper 를 사용해 만들어지며 일반 헬퍼메서드와 동일한 방법으로 호출하고 사용할 수 있습니다. 다만 @Helper 로 만들어진 메서드는 반환값을 가질 수 없고 내부에서 컨텐츠표현으로 처리되어야 합니다.

 

2. 외부 헬퍼 메서드

 

헬퍼 메서드를 직접 만든다는 면에서 인라인 헬퍼 메서드와 개념은 동일하지만 메서드자체를 별도의 클래스등에 풀어놓는 방식입니다.

 

public static class MyHelper
{
    public static int Sum(this HtmlHelper htmlint iint j)
    {
        return i + j;
    }
}

 

외부 헬퍼메서드는 보시는것처럼 확장메서드로 구현되며 HtmlHelper 개체를 매개변수로 지정해야 합니다.

 

@using WebApplication1.Test

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

계산 : @Html.Sum(10, 20)

 

외부 헬퍼메서드를 사용하려면 @Html. 으로 해당 헬퍼메서드를 호출하면 됩니다.

 

3. 내장 헬퍼 메서드

 

(1) Form

 

@using (Html.BeginForm()) {
    
}

 

Form은 BeginForm 메서드를 통해 구현되며 이것을 using으로 감싸면 처음에는 <form>으로 끝에는 </form>으로 닫히는 Form을 생성합니다.

 

BeginForm 메서드는 아무런 매개변수 없이 단독으로 호출되면 기본적으로 입력된 데이터를 같은 액션메서드의 POST로 전달합니다.

 

public ActionResult Index()
{
    return View(new Member());
}

[HttpPost]
public ActionResult Index(Member m)
{
    return View(m);
}

 

만약 다른 곳으로 POST가 전달되어야 한다면 전달되길 원하는 컨트롤러와 액션메서드를 다음과 같이 지정해야 합니다.

 

@using (Html.BeginForm("MyMember""MyController")) {
    
}

 

또는 특정한 라우트설정을 따라가는 Form을 생성해야 한다면 BeginForm 대신 BeginRouteForm 메서드를 사용할 수도 있습니다.

 

@using (Html.BeginRouteForm("Default"new { id = "newMember" })) {
    
}

 

예제에서는 RouteConfig.cs 파일에 등록된 내용중 이름이 Default 인 라우트설정을 참조하도록 하였으며 동시에 id 세그먼트값을 지정하고 있습니다.

 

(2) HTML요소

 

public class Member
{
    public string ID { getset}
    public string Name { getset}
    public string Email { getset}
    public Role Role { getset}
    public List<SelectListItemFamily {
            get {
                return new List<SelectListItem>  {
                    new SelectListItem { Text = "부",  Value = "F"},

                    new SelectListItem { Text = "모",  Value = "M"},
                    new SelectListItem { Text = "형",  Value = "B"}
                };
            }
        }

}

 

public enum Role
{
    Admin,
    Member,
    Guest
}

 

@using (Html.BeginForm()) {
    <label>아이디</label> @Html.TextBox("ID"Model.ID)<br />
    <label>이름</label> @Html.TextBox("Name"Model.Name)<br />
    <label>이메일</label> @Html.TextBox("Email"Model.Email)<br />
    <input type="submit" value="제출" />
}

 

HTML 요소중 텍스트박스는 TextBox 메서드를 호출함으로서 사용할 수 있습니다. 메서드를 호출할때 첫번째는 id와 name속성을 설정하는 값이며 두번째는 해당 입력요소 자체의 값을 의미합니다. 이밖에도 CheckBox, Hidden, RadioButton, Password, TextArea 등의 메서드를 통해 원하는 Input요소를 생성할 수 있습니다.

 

@using (Html.BeginForm()) {
    <label>아이디</label> @Html.TextBox("ID")<br />
    <label>이름</label> @Html.TextBox("Name")<br />
    <label>이메일</label> @Html.TextBox("Email")<br />
    <input type="submit" value="제출" />
}

 

HTML 요소를 생성할때 첫번째 매개변수를 통해 특정 값을 전달하면 ViewBag이나 Model에서 일치하는 항목이 있는지를 확인하고 자동으로 해당하는 value값을 설정하게 됩니다.

 

@using (Html.BeginForm()) {
    <label>아이디</label> @Html.TextBoxFor(x => x.ID)<br />
    <label>이름</label> @Html.TextBoxFor(x => x.Name)<br />
    <label>이메일</label> @Html.TextBoxFor(x => x.Email)<br />
    <input type="submit" value="제출" />
}

 

HTML 요소가 특정 Model에 종속되는 경우라면 ~For 메서드를 사용하여 강력한 형식의 요소를 생성할 수도 있습니다. 이렇게 하면 id나 name속성값등을 잘못입력했을경우에 대한 문제를 최소한으로 줄일 수 있습니다.

 

@using (Html.BeginForm()) {
    <label>역활</label>@Html.DropDownList("Role"new SelectList(new[] { "Admin""Member""Guest" }))
    <input type="submit" value="제출" />
}

 

물론 ~For 메서드를 통해 좀더 안전한 강력한 형식의 요소를 생성할 수도 있습니다.

 

@using (Html.BeginForm()) {
    <label>역활</label>@Html.DropDownListFor(x => Model.Rolenew SelectList(Enum.GetNames(typeof(WebApplication1.Infrastructure.Role))))
    <input type="submit" value="제출" />
}

 

참고로 DropDownList나 ListBox는 IEnumerable 형식을 열거하므로 예제에서의 Family 또한 Select 요소로서 적용할 수 있습니다.

 

@using (Html.BeginForm()) {
    <label>역활</label>@Html.ListBoxFor(x => x.FamilyModel.Family)
    <input type="submit" value="제출" />
}

 

ASP.NET MVC 에서는 HTML 요소 생성시 TextBox나 ListBox처럼 요소생성에 필요한 메서드를 직접 호출하는 것 이외에도 Model의 데이터기반하에 자동적으로 요소가 생성될 수 있도록 하는 방법이 제공되고 있습니다.

 

public class Member
{
    public string ID { getset}
    public string Name { getset}
    public string Email { getset}
    public DateTime BirthDay { getset}
    public bool IsDrawal { getset}
}

 

Model을 위와 같이 정의하고

 

@using (Html.BeginForm()) {
    <label>역활</label> @:&#58; @Html.EditorFor(x => x.ID)<br />
    <label>이름</label>  @:&#58; @Html.EditorFor(x => x.Name)<br />
    <label>이메일</label> @:&#58; @Html.Editor("Email")<br />
    <label>생년월일</label> @:&#58; @Html.EditorFor(x => x.BirthDay)<br />
    <label>탈퇴여부</label> @:&#58; @Html.Editor("IsDrawal")<br />
    <input type="submit" value="제출" />
}

 

Editor나 EditorFor메서드를 통해 요소생성을 시도하면 해당 데이터타입에 맞는 요소를 자동적으로 출력할 것입니다. 모델기반 요소생성은 Editor 이외에 Display(읽기전용-태그없이 값만 표시함), Label(라벨태그) 등이 있으며 각 메서드 이름에 For가 붙는 메서드는 강력한 형식으로 요소를 생성하는 메서드입니다.

 

@using (Html.BeginForm()) {
    @Html.EditorForModel()
    <input type="submit" value="제출" />
}

 

위 예제는 HTML 요소에 필요한 모든 요소에 대해 일일이 해당 메서드를 호출하지 않고서도 일괄 생성하는 방법을 보여주고 있습니다. EditorForModel은 Model을 기반으로 편집상태의 요소를 생성하며 LabelForModel은 Label 태그로, DisplayForModel은 속성값으로만 Model을 표현하도록 합니다.

 

~ForModel 메서드를 통해 HTML요소를 생성하는 방식은 순전히 Model의 데이터타입을 통해 적절하다고 판단되는 HTML요소를 추정하여 생성할 뿐입니다. 가장 간단하게 요소를 생성하지만 일부는 의도하지 않은 형태의 요소를 생성할 수도 있는데 이러한 문제는 Model에 직접적인 세부사항을 지정함으로서 해결될 수 있습니다.

 

public class Member
{
    [HiddenInput]
    public string ID { getset}
    public string Name { getset}
    public string Email { getset}
    public DateTime BirthDay { getset}
    public bool IsDrawal { getset}
}

 

HiddenInput은 편집이 불가능하도록 해당 필드의 값만을 표시합니다.

 

[HiddenInput(DisplayValue =false)]

 

하지만 HiddenInput 에서 DisplayValue 속성을 False로 지정하면 아예 값조차도 표시하지 않도록 할 수 있습니다.

 

[ScaffoldColumn(false)]

 

ScaffoldColumn(false)는 [HiddenInput(DisplayValue =false)] 보다 더 강력한 형식으로 아예 해당필드에 대한 요소표현을 생략하도록 합니다. 눈에 보이지 않는 것에서 끝내는 것이 아니라 어떠한 형태의 요소로도 해당 필드의 데이터를 표시하지 않습니다.

 

[Display(Name ="이름")]
public string Name { getset}

 

특정 필드에 대해 Label 태그로 제목(이름)을 표현할때는 필드명이 기본적으로 적용됩니다. 하지만 이를 바꾸고자 한다면 Display의 Name속성을 통해 변경하고자 하는 명칭을 지정할 수 있습니다.

 

[DataType(DataType.EmailAddress)]
public string Email { getset}

 

DataType은 특정 필드에 대해 데이터의 포멧형식을 지정합니다.

 

[UIHint("Date")]
public DateTime BirthDay { getset}

 

UIHint는 HTML요소 생성시 HTML에 해당 데이터타입에 맞는 속성을 추가하도록 합니다. 이렇게 되면 예를 들어 날짜타입인 경우 날짜입력에 편리한 달력등을 표시할 수도 있을 것입니다. (오페라와 같은 브라우저는 이 설정의 적용을 바로 확인할 수 있으나 다른 브라우저의 경우 현재까지 HTML5의 기능이 완벽히 구현되지 않은 상태이므로 변화가 아예 없거나 제한적인 부분만을 표시할 수 있습니다.)

 

위 예제에서 Member 클래스는 임의로 제작한 Model 클래스에 해당합니다. 이런 모델클래스의 경우에는 별 문제가 없으나 만약 특정 모델클래스가 EntityFramework 등을 이용해 자동으로 생성된 모델 클래스라면 속성값을 지정하기 어려울 수 있습니다. 대부분 자동생성되는 모델 클래스의 경우 클래스에 어떠한 변경사항이 발생하면 해당 클래스의 변경사항이 감지되어 자동으로 클래스를 재 작성하거나 오류를 발생시키기 때문입니다. 때문에 지정한 속성값들이 제거되거나 사용이 불가능해 질 수 있습니다.

 

public partial class Member
{
    public string ID { getset}
    public string Name { getset}
    public string Email { getset}
    public DateTime BirthDay { getset}
    public bool IsDrawal { getset}
}

public partial class MemberMetaData
{
    public string ID { getset}
    public string Name { getset}
    public string Email { getset}
    public DateTime BirthDay { getset}
    public bool IsDrawal { getset}
}

 

이러한 문제를 해결하기 위해서는 원본 클래스를 partial 클래스로 만들고 각 필드가 동일한 별도의 클래스를 partial로 생성한뒤 해당 클래스에 필요한 속성값을 부여해야 합니다.

 

[MetadataType(typeof(MemberMetaData))]
public partial class Member
{
    public string ID { getset}
    public string Name { getset}
    public string Email { getset}
    public DateTime BirthDay { getset}
    public bool IsDrawal { getset}
}

public partial class MemberMetaData
{
    public string ID { getset}
    public string Name { getset}
    public string Email { getset}

    [DataType(DataType.Date)]
    public DateTime BirthDay { getset}
    public bool IsDrawal { getset}
}

 

원본 모델클래스에는 MetaDataType을 사용하여 필요한 타입이 있는 클래스를 지정함으로서 이전처럼 모델클래스에 직접적으로 속성을 설정한 것과 동일한 효과를 얻을 수 있습니다.

 

public partial class Member
{
    public string ID { getset}
    public string Name { getset}
    public string Email { getset}
    public DateTime BirthDay { getset}
    public bool IsDrawal { getset}
    public MemberType MT { getset}
}

public enum MemberType
{
    Admin,
    Member,
    Guest
}

 

위와 같은 구조의 모델클래스의 경우 MemberType인 경우에는 특별히 DropDownList로 표현하고 싶지만 기존의 템블릿만으로는 이를 명시할 방법이 없습니다. 이런 상황에서는 대략 2가지 정도의 해결방법이 존재하는데 우선 첫번째 방법으로 아래와 같이 EditorForModel에서 요소생성이 제외되도록 하고 해당 필드에 대해 별도의 요소생성을 지시하는 것입니다.

 

[HiddenInput(DisplayValue =false)]
public MemberType MT { getset}

 

@using (Html.BeginForm()) {
    @Html.EditorForModel()<br />
    @Html.DropDownListFor(x => x.MTnew SelectList(Enum.GetNames(typeof(WebApplication1.Infrastructure.MemberType))))
    <input type="submit" value="제출" />
}

 

두번째는 아예 MemberType인 경우 무조건 DropDownList 형태로 표현되도록 템블릿을 직접 지정하는 방법입니다. 이 방법을 위해서는 우선 /Views/Shared 폴더 하위에 EditorTemplates 라는 폴더를 새로 추가하고 해당 폴더안에 MemberType.cshtml 파일을 생성해야 합니다. 주의할점은 EditorTemplates이라는 폴더 이름은 약속된 이름이므로 다른 이름으로 폴더를 생성해서는 안되며 내부에 생성하는 cshtml 파일이름또한 템블릿을 지정하려는 클래스 혹은 타입명과 일치해야 한다는 것입니다. 다만 편집이 아닌 읽기전용으로의 템블릿 생성의 경우에는 DisplayTemplates 으로 폴더를 생성해야 합니다.

 

@model WebApplication1.Infrastructure.MemberType

@Html.DropDownListFor(x => xnew SelectList(Enum.GetNames(typeof(WebApplication1.Infrastructure.MemberType))))

 

MemberType.cshtml 파일에서는 위와 같이 생성하려는 타입과 요소를 지정하면 MVC 프레임워크는 자동으로 해당 템블릿을 적용할 것입니다. 따라서 기존의 EditorForModel 메서드만으로 원하는 요소를 생성할 수 있게 됩니다.

 

이러한 방법은 UIHint 에서 데이터타입을 지정하는 것만으로도 원하는 요소를 생성할 수 있게 합니다. 예를 들어 DateTime 형식을 년월일로 표현하려면 /Views/Shared/EditorTemplates 하위에 DateTime.cshtml 파일을 생성하고

 

@model DateTime

@Html.TextBoxFor(x => xModel.ToString("yyyy년 MM월 dd일"))

 

위와 같이 원하는 데이터타입에 템플릿을 만들어 두면

 

[UIHint("DateTime")]
public DateTime BirthDay { getset}

 

UIHint 속성에 해당 데이터타입을 지정하는 것만으로 필요한 요소를 생성할 수 있습니다. 재미있는건 템블릿을 생성할때 파일안에 포함된 모든 내용을 렌더하게 되므로 추가적으로 필요한 다른 요소까지도 부수적으로 포함시켜 요소생성시 필요한 모든 요소를 렌더할 수 있다는 것입니다.

 

@model DateTime

<span style="color:red">시간 : </span>
@Html.TextBoxFor(x => xModel.ToString("yyyy년 MM월 dd일"))

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

[ASP.NET MVC] 뷰 (View)  (0) 2018.08.14
[C#] using static  (0) 2018.07.27
[ASP.NET MVC] 헬퍼메서드(Helper Method)  (0) 2018.07.18
[C#] extern  (0) 2018.07.03
[C#] BinaryFormatter / XmlSerializer / DataContractJsonSerializer  (0) 2018.06.26
[C#] Encoding / BitConverter  (0) 2018.06.19
0 0