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






+ Recent posts