34

저는 사람들이 ViewModel을 구축하는 다양한 방법과 그 방법을 선택하는 이유에 대해 궁금합니다.ViewModels을 채우거나 유효성을 검사하는 방법은 무엇입니까?

여기 몇 가지 방법을 생각해 볼 수 있습니다.

-1. 주입 된 저장소 - 컨트롤러가 모델을로드하고 ViewModel에 매핑합니다. 여기서 ViewModel 생성자는 다양한 콜렉션을 취하여 ex에 대해 내부적으로 설정할 수 있습니다.

 

public CustomerController(ISomeRepository repository) 
{ 
    _repository = repository; 
} 

public ActionResult Create() 
{ 
    CustomerCreateViewModel model = new CustomerCreateViewModel(_repository.GetShipTypes, 
                   _repository.GetStates); 
.. 
.. 
} 
 

-2와 같은 선택 목록에 있습니다. ViewModelBuilder - 주입 된 저장소의 인스턴스로 컨트롤러에 주입되거나 인스턴스화됩니다. ,

var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);

-3

>var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);

또는 같은 것을 통해 호출합니다. 컨트롤러에서 직접 (코드 불필요 - 지저분한)

-4. 컨트롤러가 다음 뷰 모델 매핑 또는 도메인 모델 반환 몇 가지 다른 서비스 (주입 여부) (사람이 직접 지정되지 않은 뷰 모델을 반환하는이 일을가/뷰 모델 빌더 클래스로 언급?)


public JobCreateViewModel BuildJobCreateViewModel(int parentId) 
{ 
    JobCreateViewModel model = new JobCreateViewModel(); 
    model.JobStatus = _unitOfWork.JobRepository.GetJobStatuses(); 
    model.States=_unitOfWork.StateRepository.GetAll(); 
    return model; 
} 

조회 모델의 유효성 확인과 관련하여 이제는 표준 유효성 검사를 위해 기본 ViewModel 클래스를 상속하거나 모든 ViewModel간에 유효성 검사 (예 : 데이터 주석 특성)를 복사하거나 간단히 서버 측 유효성 검사에 의존합니다. 그것은 모두 귀하의 도메인 개체를 다시 확인할 수 있습니까?

다른 사람? 더 나은 점이 있나요? 왜?

편집 아래 링크를 기반으로, ViewModels의 아키텍처에 대한 Jimmy Bogard의 멋진 기사를 찾았습니다. 위의 질문에 직접적으로 대답하지는 않지만 ViewModel 정보를 얻기 위해 여기에 오는 모든 사람들에게 훌륭한 참고 자료입니다. http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/

+0

여기에 downvote가있었습니다 - 단지 궁금한 이유 - 내가 명확히 할 수있는 것? –

+4

내 휴대 전화에서 실수로 별표를 표시하려고 시도했지만 미안합니다. 이제 실행 취소하기에는 너무 늦었습니다. – Jason

+0

아, 걱정할 필요는 없습니다.) –

답변

14

리포지토리가 아닌 컨트롤러에 서비스를 삽입 한 다음 AutoMapper을 사용하여 뷰 모델로 변환하십시오. 이 경우 서비스 계층의 이점은 하나 이상의 리포지토리에서 여러 개의 간단한 작업을 도메인 모델을 노출하는 단일 작업으로 집계 할 수 있다는 것입니다. 예 : 오토 I 컨트롤러 동작 후에 실행되는 기록 할 수있는 사용자 지정 동작 필터이다

private readonly ICustomerService _service; 
public CustomerController(ICustomerService service) 
{ 
    _service = service; 
} 

[AutoMap(typeof(Customer), typeof(CustomerViewModel))] 
public ActionResult Create(int id) 
{ 
    Customer customer = _service.GetCustomer(id); 
    return View(customer); 
} 

이 예에서, 반환 된 객체를 검사하고, 지정된 대상 유형에 맵핑하는 정의 AutoMapper 맵핑을 사용한다. 따라서 뷰는 해당 CustomerViewModel을 모델 유형으로 가져옵니다.

public ActionResult Create(int id) 
{ 
    Customer customer = _service.GetCustomer(id); 
    CustomerViewModel vm = Mapper.Map<Customer, CustomerViewModel>(customer); 
    return View(vm); 
} 

중앙 처리 될 수있는 배관 및 반복 코드가 너무 많습니다

Jimmy Bogard의 putting your controllers on a diet video을 시청하는 것이 좋습니다.

+0

감사합니다. 비슷한 AutoMap 속성을 데모 한 것을 보았습니다. Jimmy가 사용할 수있는 AutoMap 속성이 있습니다. 이 뷰 모델의 클라이언트 유효성 검사 (또는 그렇지 않습니까?)와 그 사이에 유효성 검사 논리를 공유하려면 어떻게합니까? 그런 다음 저장소를 서비스 계층에 주입하고 있습니까? –

+0

@AdamTuliper, 서버 측 유효성 검사 및 간단한 클라이언트 측 유효성 검사 시나리오 (필수,보다 큼 ...)로 FluentValidation.NET을 사용합니다. 좀 더 복잡한 클라이언트 측 유효성 검사 시나리오 (종속 속성 ...)에서는 클라이언트에서 처리해야하는지 여부를 결정하고 이러한 시나리오에 대한 클라이언트 측 유효성 검사를 수행해야하는 경우 사용자 정의 jquery 유효성 검사 appenders를 작성합니다. 서비스 계층에 대한 저장소와 관련하여 예, 서비스 계층은 모든 저장소가 도메인 모델에서 간단한 CRUD 작업을 수행 할 수 있도록하기 위해 ctor injection을 사용합니다. –

+0

감사합니다. Darin, 또 다른 훌륭한 대답 :) –

0

우리의 방법은 저장소에 컨트롤러를 삽입하고 Automapper http://automapper.org/을 사용하여 ViewModel에 매핑하는 것입니다. ViewModel에는 데이터 주석 속성이있어 클라이언트에서 유효성 검사를 수행 할 수 있습니다.

도메인 개체 (Entity Framework)를 반환하는 저장소의 메서드를 호출합니다. 도메인 객체는 ViewModel에 매핑됩니다. 편집 및 추가시에는 동일한 ViewModel을 사용하는 경향이 있으므로 데이터 주석은 한 번만 필요합니다. 가장 간단한 형태로 다음 코드와 같습니다 :

public ActionResult List(int custId, int projId) 
    { 
     var users = _userRepository.GetByCustomerId(custId); 
     var userList = Mapper.Map<IEnumerable<CMUser>, IEnumerable<UserListViewModel>>(users); 
     return View(userList); 
    } 
+0

저장소는 뷰 모델에 매핑되지 않습니다. 도메인 객체 또는 뷰 모델을 반환하려면 저장소에서 일부 메소드를 호출해야합니다. 또한 각 모델이나 공유 위치 등에 별도의 주석을 사용하는 경우에는 적용되지 않습니다. –

+0

편집/추가에 대해 동일한 ViewModel을 사용하는 경우 기본적으로 데이터 주석이 필요한 정수 ID 필드에 대한 작업 ? 양식에서 누락 된 경우 유효하지 않습니다. 삽입은 기본적으로 필요하므로 "작성"시나리오의 경우 0으로 초기화해야합니까? 감사합니다. –

1

# 4에서 변형 된 프로젝트를 완료했습니다. 우리는 컨트롤러에 서비스 클래스를 주입했습니다. 서비스 클래스는 저장소와 모델 빌더 클래스 (모델 팩토리라고 함)에 대한 종속성을 유지합니다.

컨트롤러가 비즈니스 유효성 검사 논리를 처리 한 서비스 클래스를 호출 한 다음 해당 팩토리에서 뷰 모델을 가져 왔습니다. 모델 자체는 입력 검증을 위해 데이터 주석에 의존했습니다.

우리 팀에게는 정말 효과가있었습니다. 개발자들이 서로 영향을 미치지 않고 업무를 수행 할 수 있도록하는 데 충분한 관심이 있었지만 진행 상황을 이해하기에 충분했습니다.

우리가 처음 시도했을 때 우리는 그걸 고수 할 것입니다. 나는 다른 사람들이 어떻게 반응하는지보고 싶다.

+0

. 따라서 서비스 클래스에 저장소가 주입되었습니다. 예를 들어 당신의 방법 설정은 어떻습니까? 서비스 클래스에서? 여러 뷰 모델에서 클라이언트 측 유효성 검사를 어떻게 처리 했습니까? (예 : 편집 대 작성) –

+0

아래의 Darin의 예와 매우 유사하므로 우리는 오픈 소스 소프트웨어를 사용할 수 없다는 미친 요구 사항을 가지고있어서 Automapper를 사용할 수 없었습니다. 다음 번에는 뷰 모델 팩토리를 오토마 퍼로 교체 할 것입니다. 디스플레이 및 편집기 템플릿을 사용하여 동일한 모델의 다양한 뷰를 제공했으며 데이터 주석은 필요한 모든 유효성 검사를 제공했습니다. – Jason

+0

그리고 모델 빌더 클래스는 생성자 매개 변수 (서비스가 저장소 객체를 처리 함)에서 저장소 객체를 받거나 모델 빌더가 저장소 자체를 직접 사용합니까? 아주 간단한 예제를 제공해 주시겠습니까? – Muflix

0

서비스 메소드에서 ViewModels를 반환하는 컨트롤러에서 도메인 모델을 숨기는 서비스 레이어를 사용합니다. 이를 통해 클라이언트에 영향을주지 않고 도메인 모델을 변경할 수 있습니다.

관련 문제