2011-02-16 6 views
10

저는 컨트롤러와 유닛 테스트를 쓰고 있습니다. 두 가지 방법 (똑같이 유효하다고 생각합니다)을 발견했을 때 뭔가를했습니다. 모든 모델에는 IsValid 속성이 있습니다. 모델의 유효성을 검사 할 수 있습니다.ModelState.IsValid 또는 Model.IsValid?

컨트롤러 동작 메서드에 다시 게시 할 때 모델이 유효하면 저장하고 그렇지 않으면 사용자가 오류를 수정하도록 양식을 다시 표시하려고합니다.

초기 생각은 모델이 유효한지 묻는 것입니다. 그러나 ModelState.IsValid를 확인할 수도 있다는 것을 알았습니다.

누군가 다른 사람을보아야하는 특별한 이유가 있습니까?

답변

11

귀하의 모델에 내장 된 맞춤 비즈니스 검증이 좋은 방법이라고 생각합니다. 나는 그것을 처리 할 방법은 ModelState에 사용자 지정 유효성 검사 오류를 추가하는 것입니다 :

if (ModelState.IsValid) 
{ 
    if (!model.IsValid) 
    { 
     ModelState.AddModelError("The model is not valid"); 
    } 
    else 
    { 
     return RedirectToAction("Index"); 
    } 
} 

return View(model); 

보기는 관계없이 사용자 정의 또는 내장 여부의 유효성 검사 오류에 액세스 할 수있는 그런 식으로

6

ModelState. Post-Redirect-Get을 따라 TempData으로 전송할 수 있습니다. 예 :

[HttpPost] 
    [ExportModelStateToTempData] 
    public ActionResult Delete(int id) 
    { 
     if (_service.DeleteTask(id)) 
      return RedirectToAction(ControllerActions.Index); 

     return RedirectToAction(ControllerActions.Edit, new { id }); 
    } 

    [ImportModelStateFromTempData] 
    public ActionResult Edit(int id) 
    { 
     var task = _service.GetTask(id); 
     return View(ControllerActions.Edit, GetEditModel(task)); 
    } 

사용자가/callig/작업으로 작업을 삭제 삭제 작업을하지만, 뭔가 잘못과 오류 메시지가 나타나는 경우, F5를 누르면 다시 삭제를 호출하지 않습니다 수 있습니다. 이후 ModelStateEdit으로 전송하면 모든 오류가 편집 페이지에 표시됩니다.

public abstract class ModelStateTempDataTransferAttribute : ActionFilterAttribute 
{ 
    protected static readonly string Key = typeof(ModelStateTempDataTransferAttribute).FullName; 
} 

public class ExportModelStateToTempDataAttribute : ModelStateTempDataTransferAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     //Only export when ModelState is not valid 
     if (!filterContext.Controller.ViewData.ModelState.IsValid) 
     { 
      //Export if we are redirecting 
      if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult)) 
      { 
       filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState; 
      } 
     } 

     base.OnActionExecuted(filterContext); 
    } 
} 

public class ImportModelStateFromTempDataAttribute : ModelStateTempDataTransferAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary; 

     if (modelState != null) 
     { 
      //Only Import if we are viewing 
      if (filterContext.Result is ViewResult) 
      { 
       filterContext.Controller.ViewData.ModelState.Merge(modelState); 
      } 
      else 
      { 
       //Otherwise remove it. 
       filterContext.Controller.TempData.Remove(Key); 
      } 
     } 

     base.OnActionExecuted(filterContext); 
    } 
} 

매우 문제가 될 것 Model과 같은 일을 :

ModelState 수출 수입 속성/대한 코드입니다.

+0

당신의'ControllerActions' 클래스는 무엇입니까 ? 그것은 저에게 새로운 것입니다. –

+0

@Matt Greer : 그것은 행동의 상수 이름을 가진 클래스 일뿐입니다. 강하게 입력해야합니다. 형형색색의 타이핑 된 이름으로 연주하고 싶다면 T4MVC를 사용하는 것이 좋습니다. – LukLed

+0

그래서 그냥 const 문자열의 모음? Drat, 나는 당신이 마법의 끈을 피할 수있는 영리한 해결책이 있기를 바랬습니다. 매직 문자열은 최근에 가장 큰 애완 동물이되었습니다. NET : –

0

또한 오류 컬렉션을 통해 열거하고 정확한 오류 메시지를 출력에 쓸 수 있습니다.

else if (!ModelState.IsValid) 
{ 
    List<ModelError> modelErrors = new List<ModelError>(); 
    ModelErrorCollection errors = new ModelErrorCollection(); 
           ; 
    // got to the model and look at the Array of Values 
    foreach (var item in ModelState) 
    { 
     if (item.Value.Errors.Count != 0) 
     { 
      // get the error 
      errors = item.Value.Errors; 
      modelErrors.Add(errors.Single()); 
     } 
    } 

    if (modelErrors.Count != 0) 
    { 
     foreach (var error in modelErrors) 
     { 
      Debug.WriteLine(error.ErrorMessage); 
     } 
     } 

...

관련 문제