2010-05-04 3 views
2

MVC 2.현대적인 방법이

그래서 내 질문은 약 MVC에서 데이터 작업에 전념 기사의 많은, 그리고 아무것도 있습니다 적절한 방식이 무엇인지는 POST 쿼리를 처리하고 유효성을 검사합니다.

두 가지 조치가 있다고 가정 해 보겠습니다. 둘 다 동일한 엔티티에서 작동하지만 각 조치에는 자동으로 바인드되어야하는 자체 분리 된 오브젝트 특성 세트가 있습니다. 예를 들어 :

  • 액션 "A"POST 요청에서 가져온 전용 "날짜"개체의 속성을 결합해야 POST 요청
  • 액션 "B"에서 가져온 전용 "이름"개체의 속성을 결합한다

내가 이해하는 한,이 경우에는 Bind 속성을 사용할 수 없습니다.

그래서 MVC2에서 POST 데이터를 처리하고 유효성을 검사하는 가장 좋은 방법은 무엇입니까?

UPD :
작업을 수행 한 후 - 그들은 유효하고 지속 층에 저장할 준비가 될 수 있도록 추가 로직이 개체에 적용됩니다. 조치 "A"의 경우, 현재 날짜로 날짜를 설정합니다.

+0

Employee {string Name {get; 세트; } 날짜 시간? 날짜 {get; 세트; }}, Action A의 Employee 인스턴스에는 무엇이 포함됩니까? 당신은 그것이 오직 이름을 묶어야한다고 말했다. 날짜가 널일까요? 더 나은 그림을 얻으려고. –

+0

@Raje : nope. Employee 객체가 영구 저장소에 저장되기 전에 몇 가지 추가 논리가 적용됩니다 (이 문제를 해결하기 위해 몇 초 안에 질문을 업데이트 중입니다) – zerkms

+0

http://bradwilson.typepad.com/ 이미이 뛰어난 기사를 읽은 적이 있는지 확실하지 않습니다. 블로그/2010/01/input-validation-vs-model-validation-in-aspnet-mvc.html –

답변

3

도메인 모델 클래스를 내보기 모델로 사용하는 것을 개인적으로 싫어합니다. 나는 그것을 확인, 서식, 그리고 일반적으로 잘못 느낀 문제가 발생 찾으십시오. 실제로, 나는 내 뷰 모델에 실제로 DateTime 속성을 사용하지 않을 것입니다. (저는 컨트롤러에서 문자열로 서식을 지정할 것입니다.)

참고 :

내가 기본보기 모델의 속성으로 노출이 개 별도의 뷰 모델, 검증 속성과 각을 사용하는 것이 내가 기본보기 모델로 함께 게시 뷰 모델을 결합 얼마나 떠 났어요 당신을위한 운동이있다, 유효성 검사를 POST 데이터를 처리하고 추가로

public class ActionAViewModel 
{ 
    [Required(ErrorMessage="Please enter your name")] 
    public string Name { get; set; } 
} 

public class ActionBViewModel 
{ 
    [Required(ErrorMessage="Please enter your date")] 
    // You could use a regex or custom attribute to do date validation, 
    // allowing you to have a custom error message for badly formatted 
    // dates 
    public string Date { get; set; } 
} 

public class PageViewModel 
{ 
    public ActionAViewModel ActionA { get; set; } 
    public ActionBViewModel ActionB { get; set; } 
} 

public class PageController 
{ 
    public ActionResult Index() 
    { 
     var viewModel = new PageViewModel 
     { 
      ActionA = new ActionAViewModel { Name = "Test" } 
      ActionB = new ActionBViewModel { Date = DateTime.Today.ToString(); } 
     }; 

     return View(viewModel); 
    } 

    // The [Bind] prefix is there for when you use 
    // <%= Html.TextBoxFor(x => x.ActionA.Name) %> 
    public ActionResult ActionA(
     [Bind(Prefix="ActionA")] ActionAViewModel viewModel) 
    { 
     if (ModelState.IsValid) 
     { 
      // Load model, update the Name, and commit the change 
     } 
     else 
     { 
      // Display Index with viewModel 
      // and default ActionBViewModel 
     } 
    } 

    public ActionResult ActionB(
     [Bind(Prefix="ActionB")] ActionBViewModel viewModel) 
    { 
     if (ModelState.IsValid) 
     { 
      // Load model, update the Date, and commit the change 
     } 
     else 
     { 
      // Display Index with viewModel 
      // and default ActionAViewModel 
     } 
    } 
} 
+0

이 코드의 기능을 이해하려면 시간이 필요합니다. 답변 주셔서 감사합니다 ;-) – zerkms

+0

- 실생활의 뷰 모델에서 여전히 속성으로 지정된 유효성 검사를 사용하고 있습니까? 비즈니스 논리를 분리하기 위해 유효성 검사 논리를 서비스 응용 프로그램 수준으로 이동하고 싶습니다. 이 경우에는 (...) elseif (...) 등 (유효성 검사 클래스에서 캡슐화되지 않음) – zerkms

+0

사용자 지정을 제외하고 유효성 검사를 수행 할 가능성이 전혀 없습니다. 유효성 검사 시스템이 완전히 플러그 가능합니다. 따라서 속성을 사용할 필요가 없습니다. 가장 중요한 것은 뷰 바인딩 모델을 분리하여 모델 바인딩을 최대한 활용하는 것입니다. –

2

한 가지 가능한 방법으로 접근하는 몇 가지 방법을의 사용자 정의 모델 바인더 때문이다.

public class Customer 
{ 
    public string Name { get; set; } 
    public DateTime Date { get; set; } 
} 


public class PageController : Controller 
{ 
    [HttpPost] 
    public ActionResult ActionA(Customer customer) 
    { 
     if(ModelState.IsValid) { 
     //do something with the customer 
     } 
    } 

    [HttpPost] 
    public ActionResult ActionB(Customer customer) 
    { 
     if(ModelState.IsValid) { 
     //do something with the customer 
     } 
    } 
} 

CustomerModelBinder는 그런 일이 될 것입니다 :

public class CustomerModelBinder : DefaultModelBinder 
{ 
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor) 
    { 
     if (propertyDescriptor.Name == "Name") //or date or whatever else you want 
     { 


      //Access your Name property with valueprovider and do some magic before you bind it to the model. 
      //To add validation errors do (simple stuff) 
      if(string.IsNullOrEmpty(bindingContext.ValueProvider.GetValue("Name").AttemptedValue)) 
       bindingContext.ModelState.AddModelError("Name", "Please enter a valid name"); 

      //Any complex validation 
     } 
     else 
     { 
      //call the usual binder otherwise. I noticed that in this way you can use DataAnnotations as well. 
      base.BindProperty(controllerContext, bindingContext, propertyDescriptor); 
     } 
    } 

을하고 Global.asax에 넣어에서 여기 내가 POST-폼 데이터에 사용자 지정 유효성 검사를 추가하기 위해 최근에 사용 무엇의 작은 샘플입니다

ModelBinders.Binders.Add(typeof(Customer), new CustomerModelBinder()); 

당신이 이름 속성 (단지 일) 당신이 ActionB를 호출 할 때, 다음 하나 이상의 사용자 정의 모델 바인더와의 명령문 "만일", 넣어 다시 할 수 있도록 바인딩하지하려면 널 (null) 또는 이미 존재하는 값이나 원하는 값을 설정하십시오. 그런 다음 컨트롤러 넣어에서 :

[HttpPost] 
public ActionResult([ModelBinder(typeof(CustomerAModelBinder))] Customer customer) 

[HttpPost] 
public ActionResult([ModelBinder(typeof(CustomerBModelBinder))] Customer customer) 

customerAmodelbinder에만 이름을 바인딩하고 customerBmodelbinder는 날짜를 결합 할 경우.

이것은 모델 바인딩의 유효성을 검사하는 가장 쉬운 방법이며 복잡한보기 모델을 사용하여 매우 멋진 결과를 얻었습니다. 내가 놓친 뭔가가있을 것이고 아마도 전문가가 대답 할 수있을 것입니다. 희망 사항을 바로 잡았습니다. :)

+0

옳은 질문이지만 유효성 검사를 두 부분으로 분리 : 입력 유효성 검사 (ViewModel, 고객을 샘플로 작성할 때) 및 비즈니스 논리 유효성 검사 (데이터가 응용 프로그램 필수 항목을 충족하는지 확인하는 경우)가 이상하게 보입니다. 그렇지? – zerkms

+0

솔루션에 더 많은 것을 추가했습니다. 글쎄 그것은 이상하다. 이상하게 생각하는 가장 좋은 방법은 DataAnnotations를 시도했지만 DB, 파일 등을 저장하기 전에 한 지점에서 유효성을 검사하는 것이 었습니다. 잘못된 날짜를 입력하면 사용자 정의 유효성 검사 메시지를 추가 할 수 없습니다. 그래서 나는 검증 로직을 두 부분으로 구분해야했습니다. 나는 이것이 aps.net MVC 2의 방식이라고 생각한다. – goldenelf2

+0

도메인 객체는 영속되기 전에 항상 검증되어야한다. 도메인 객체의 유효성을 검사하는 것은 UI의 책임이 아니며, 도메인의 책임이다 . 도메인에 새 UI를 추가하려면 어떻게됩니까? 사용자의 UI는 사용자 경험에 대한 책임이 있으므로 도메인 확인이 도메인 메시지 및/또는 예외와 함께 시작되기 전에 사용자에게 멋진 메시지가 포함 된 입력 유효성 검사가 포함될 수 있습니다 –

관련 문제