2011-05-03 2 views
1

사내 WCF 기반 REST 서비스를 사용하는 응용 프로그램을 작성 중이며 REST 초보자라는 것을 인정합니다. "서비스 참조 추가"를 사용할 수 없기 때문에 서비스 메소드의 반환 유형을 나타내는 기성 프록시 객체가 없습니다. 지금까지 서비스로 작업 할 수 있었던 유일한 방법은 서비스가 공개하는 데이터 형식을 포함하는 어셈블리를 공유하는 것입니다.공유 어셈블리가 WCF REST 서비스에서 개체를 만들 수있는 유일한 방법입니까

  1. 은 DTO들 (DataContracts)를 구현하고 내 서비스에서 해당 유형을 노출 :

    이 있죠 나의 문제는 내가 두 가능성을 볼 수 있다는 것입니다. 어셈블리를 공유해야하지만이 방법을 사용하면 어셈블리에 포함 된 유형이 서비스 계약 및 DTO로 제한됩니다. DTO를 사용하기 위해 DTO를 사용하는 것을 좋아하지는 않지만, 도메인 객체에서 DTO로 또는 그 반대로 변환 할 추상화 및 처리 시간을 추가하기 때문에 DTO를 사용하는 것을 좋아하지 않습니다. 또한 클라이언트에서 비즈니스 규칙, 유효성 검사 등을 원한다면 어쨌든 도메인 개체를 공유해야하므로 추가 된 복잡성이 필요합니다.

  2. 내 도메인 개체의 직렬화를 지원하고, 해당 유형을 공개하고 해당 어셈블리를 공유하십시오. 이렇게하면 비즈니스 및 유효성 검사 로직을 클라이언트와 공유 할 수 있지만 내 도메인 개체의 일부는 클라이언트에 서비스 응용 프로그램 전용으로 노출됩니다.

아마도 예를 들어 토론을 도움이 될

... 나머지 서비스 (GET 작업)에서 얻어진 문서의 목록이 표시됩니다

  • 내 클라이언트 응용 프로그램입니다. 이 서비스는 DocumentInfo 객체 (문서의 경량 읽기 전용 표현)의 배열을 반환합니다.

  • 사용자가 항목 중 하나를 선택하면 클라이언트는 REST 서비스 (ID로 GET)에서 전체 문서 객체를 검색하고 사용자가 객체를 수정할 수 있도록 데이터 입력 양식을 표시합니다. 풍부한 사용자 경험을위한 검증 규칙이 필요합니다.

  • 변경 사항을 커밋하면 Document 개체가 REST 서비스 (PUT 작업)에 제출되어 백 엔드 데이터 저장소에 저장됩니다.

  • 문서의 상태가 허용되면 사용자는 문서를 "게시"할 수 있습니다. 이 경우, 클라이언트는 Document.ID 값을 사용하여 REST 서비스에 대한 요청을 POST하고 서비스는 서버 측 문서 도메인 객체를 검색하고 Publish 메소드를 호출하여 작업을 수행합니다. Publish 메서드는 클라이언트 응용 프로그램에서 사용할 수 없어야합니다.

내 문서와 DocumentInfo 개체는 공유 어셈블리에 있어야합니다. 이렇게하면 Document.Publish를 클라이언트에서 사용할 수 있습니다. 그것을 숨길 수있는 한 가지 아이디어는 내부 메소드를 만들고 내 서비스 앱이 클라이언트가 아닌 메소드를 호출 할 수있게 해주는 InternalsVisibleTo 속성을 추가하는 것입니다. 그러나 이것은 "냄새 나는 것"처럼 보입니다.

나는 옳은 길에 있거나 완전히 빠져 있습니까?

답변

4

서버에서 사용하는 클래스는 클라이언트에서 사용하는 클래스가 아니어야합니다 (데이터 전송 자체는 제외하고). 가장 좋은 방법은 DTO가 포함 된 패키지 (어셈블리/프로젝트)를 만들고이를 서버와 클라이언트간에 공유하는 것입니다. 당신은을 위해 DTO의 을 생성하고 싶지는 않겠지 만 그것은 최선의 방법입니다. 추가 레이어를 추가하면 성능에 미치는 영향은 미미하며 계층화는 실제로 클라이언트가 서버 코드에 액세스 할 수있는 상황을 피하면서 응용 프로그램을 쉽게 개발하고 유지 관리하는 데 도움이됩니다.

나는 다음과 같은 패키지로 시작하는 것이 좋습니다 :

  1. 서비스 : 서비스를 노출, 전용 서버에 상주하며 서버 응용 프로그램 로직을 포함하고 있습니다.
  2. DTO : 서버와 클라이언트 모두에 상주합니다. 서버와 클라이언트간에 전달되어야하는 데이터를 포함하는 간단한 클래스를 포함합니다. 클래스에는 속성과 별도의 코드가 없습니다. 이들은 데이터를 전송할 수있을만큼 오래 살아남을 수있는 수명이 짧은 개체입니다.
  3. 저장소 : 클라이언트에만 상주합니다. 서버를 호출하고 Model 객체를 DTO로 변환합니다 (그 반대의 경우도 마찬가지입니다).
  4. 모델 : 클라이언트에만 상주합니다. 비즈니스 개체 및 관계를 나타내는 클래스가 들어 있습니다. 모델 객체는 애플리케이션 수명 기간 동안 메모리에 남아 있습니다.

클라이언트 응용 프로그램 코드에서 Model 객체를 가져 오기 위해 Repository를 호출해야합니다 (MVVM을 사용하는 방법을 잘 모르는 경우이를 고려해야합니다).

서비스 코드가 복잡하여 모델 클래스에 액세스해야하는 경우 별도의 모델 패키지를 만들어야합니다. 분명히 다른 이름을 지정해야합니다. 서버와 클라이언트에 모두 존재해야하는 클래스는 DTO 클래스입니다.

+0

REST에서 DTO를 사용하는 것이 가장 좋은 시점은 언제입니까? REST는 객체가 아닌 와이어를 통해 미디어 유형을 전송합니다. –

+0

당연히이 게시물의 모든 활동에 잠시 시간이 걸렸지 만, 한 가지 질문이 나에게 잔소리가되었습니다. "미디어 유형"은 무엇을 의미합니까? – SonOfPirate

0

도메인 개체를 serialize하고 클라이언트에서 다른 유형으로 역 직렬화 할 수 있습니다. 두 유형 모두 동일한 데이터 계약을 구현해야합니다. 모든 직렬화 가능 유형에는 최소한 모든 공용 읽기/쓰기 특성 및 필드를 포함하는 기본 데이터 계약이 있습니다.

2

내가 경로를 안내하는 데 도움을 준 Greg와 Jake에게 신용을 제공하면서 내가 취한 접근 방식을 게시 할 것이라고 생각했습니다.

Jake는 동일한 데이터 계약을 구현하는 한 모든 유형의 클라이언트에서 데이터를 deserialize하는 것이 맞지만 WSDL없이 이것을 적용하는 것은 약간 까다로울 수 있습니다. 저는 다른 개발자가 내 솔루션을 사용하여 기존 서비스를 지원하고 유지 관리하고 내 서비스를 사용하는 새로운 고객을 생성하는 환경에 있습니다. 그들은 "서비스 참조 추가"및 진행에 사용됩니다.

클라이언트와 서버에서 서로 다른 개체를 사용한다는 Greg의 주장이 가장 도움이되었습니다. 클라이언트와 서버 사이에서 도메인 계층을 공유하여 중복을 최소화하려고했는데 이것이 내 혼란의 근원이었습니다. 이들을 두 개의 별개의 응용 프로그램으로 분리하고 별도로 보았을 때, 각각은 자신의 유스 케이스를 사용하여 그림이 더 명확 해졌습니다.

결과적으로 클라이언트가 클라이언트 측에서 WCF를 사용하여 서버에 대한 채널을 쉽게 만들 수 있도록 고객 서비스 계약을 포함하는 계약 어셈블리를 공유하고 클라이언트간에 전달 된 DTO를 나타내는 데이터 계약을 공유합니다. 및 서비스.

클라이언트에는 UI의 Model 개체 (데이터 계약)를 래핑하고 서비스 에이전트 클래스를 사용하여 공유 어셈블리의 서비스 계약을 사용하여 서비스와 통신하는 ViewModel 개체가 있습니다. 따라서 사용자가 UI에서 "게시"버튼을 클릭하면 컨트롤러 (또는 WPF/SL의 명령)가 게시 할 문서의 ID를 전달하는 서비스 에이전트의 Publish 메서드를 호출합니다. 서비스 에이전트는 요청을 REST API (공개 작업)에 중계합니다.

서버에서 REST API는 동일한 서비스 계약을 사용하여 구현됩니다. 이 경우 서비스는 내 도메인 서비스, 저장소 및 도메인 개체와 함께 작업을 수행합니다. 따라서 서비스 게시 작업이 호출되면 서비스는 DocumentRepository에서 Document 도메인 객체를 가져 와서 개체의 내부 상태를 업데이트하는 개체의 Publish 메서드를 호출 한 다음 업데이트 된 개체를 저장소의 Update 메서드에 전달합니다 변경 사항을 유지합니다.

나는 이것이 내게보다 견고하고 확장 가능한 아키텍처를 제공한다고 믿기 때문에 결과에 만족한다. 필요에 따라 ViewModels을 변경하여 서비스 폴링에 대해 걱정할 필요없이 UI를 지원할 수 있으며 마찬가지로 클라이언트 애플리케이션에 영향을 미치지 않고 서비스 작업 (도메인 계층)의 내부 구현을 변경할 수 있습니다. 둘을 묶는 것은 모두 그들이 나누는 계약입니다. 꽤 깨끗해.

관련 문제