'WCF'에 해당되는 글 2건

Programming/.NET

WCF는 WCF - 1에서 봤던 단순 데이터 제공이외에 특정 데이터모델과 연계한 데이터 서비스 구축이 가능합니다.

 

데이터 서비스를 위헤 우선 프로젝트에 데이터모델을 만들어야 합니다. 데이터 모델에 대해서는 아래 글에서 edmx생성방법을 참고해 주십시오.

 

2016/06/14 - [Programming/.NET] - [ASP.NET] EntityFramework(엔티티프레임워크)

 

참고로 예제에서는 testdb라는 데이터베이스 생성과 함께 USER_TBL테이블을 만들고

 

USE [testdb]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[USER_TBL](
 [name] [nchar](10) NULL,
 [phone] [nchar](10) NULL,
 [address] [nchar](10) NULL,
 [age] [int] NULL
) ON [PRIMARY]

GO

 

name에 키를 설정한 뒤 아래와 같은 데이터를 삽입하였습니다. 그리고 해당 테이블을 대상으로 데이터모델을 생성하였습니다.

 

Insert Into [dbo].[USER_TBL]
Values('홍길동', '0100000000', '서울시', 30);

Insert Into [dbo].[USER_TBL]
Values('홍길남', '0110000000', '대구시', 35);

Insert Into [dbo].[USER_TBL]
Values('홍길순', '0160000000', '부산시', 28);

 

모델을 생성하고 나면 이제 생성한 모델을 대상으로 WCF 데이터 서비스를 생성할 수 있습니다.

 

 

 

프로젝트에서 마우스 오른쪽 버튼을 눌러 Web부분의 WCF Data Service 항목을 선택합니다.

 

public class WcfDataService : DataService< /* TODO: put your data source class name here */ >
{
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(DataServiceConfiguration config)
    {
        // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
        // Examples:
        // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead);
        // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
    }
}

 

서비스를 생성하고 나면 위와 비슷한 소스가 표시될 것입니다. 이 상태에서 DataService부분에 이전에 생성한 데이터모델클래스를 포함하도록 합니다.

 

public class WcfDataService : DataService<testdbEntities>

 

이제 해당 svc웹서비스 파일을 웹브라우저에서 호출하면 다음과 같은 XML이 출력될 것입니다.

 

만약 svc를 호출하는데 Request Error가 출력(오류 내용중 element type is not an entity type 이라는 내용이 포함된 경우)되면 해당 Entity클래스에서 DataServiceKey("name") 특성을 추가해 주십시오.

 

[DataServiceKey("name")]
public partial class USER_TBL
{
    public string name { get; set; }
    public string phone { get; set; }
    public string address { get; set; }
    public Nullable<int> age { get; set; }
}

 

참고로 에러발생시 에러에 관한 메세지 내용을 보려면 웹서비스 클래스에 ServiceBehavior특성을 추가해야 합니다.

 

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class WcfDataService : DataService<testdbEntities>

 

2016년 6월 현재 서비스를 만들 수 있는 버전은 6.x대와 5.x대가 있습니다. 가급적 5.x대를 생성하는 것이 아직은 정신건강에 좋을 듯 합니다.

 

XML이 정상적으로 출력된다면 해당 XML에 Default만 나와 있음을 알 수 있습니다. 이것은 외부에서 서비스호출시 아무런 데이터도 조회할 수 없음을 의미하는 것으로 웹 서비스의 클래스를 아래와 같이 수정해야 합니다.

 

public static void InitializeService(DataServiceConfiguration config)
{
    // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
    // Examples:
    config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
    // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
    config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}

 

config.SetEntitySetAccessRule- 부분을 주석 제거하고 MyEntityset대신 * 문자를 지정하였습니다. 이것은 외부에서 웹서비스 호출시 서비스가능한 Entity를 지정하는 것입니다. 이때 *문자는 데이터모델에 있는 모든 Entity를 의미하며 EntitySetRights.AllRead 옵션으로 해당 데이터 모델에 대한 읽기가능권한을 부여한 것입니다.

 

 

이제 다시 서비스를 호출하면 위와 같이 표시될 것입니다. 예제에서는 USER_TBL 하나에 대한 모델을 만들었기에 조회 가능한 테이블이 단 하나만 표시되지만 만약 여러개의 테이블을 대상으로 하는 경우 그만큼의 테이블이 표시될 것입니다. 만약 특정 테이블만 제한되어야 한다면 SetEntitySetAccessRule에 * 대신 해당 테이블명을 지정하면 됩니다.

 

USER_TBL테이블에 대한 조회가 가능여부를 확인하였으니 해당 테이블의 모든 데이터를 가져와 보겠습니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL

 

위와 같이 URi에 읽고자 하는 테이블명을 지정합니다.

 

 

데이터 서비스는 이와 같은 방법으로 필요한 데이터를 쿼리합니다. 예를 들어 위 XML내용에서 두번째 '홍길동'에 대한 데이터만 필요하다면 다음과 같이 지정할 수 있습니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL('홍길동')

 

('홍길동')은 테이블의 id값이 '홍길동'인 데이터를 가져오도록 하는 것입니다. 이것은 USER_TBL의 키가 name이기 때문에 가능합니다.

 

이 밖에 전체 테이블의 내용이 아닌 특정컬럼에 대한 데이터만을 가져오려면 다음과 같이 지정합니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL('홍길동')/name

 

만약 USER_TBL이 ORDER_TBL(존재한다고 가정)처럼 다른 테이블과 관계를 맺고 있는 상태에서 ORDER_TBL의 전체 데이터를 찾아보려면 name대신 해당 관계테이블을 명시하면 됩니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL('홍길동')/ORDER_TBL

 

이 URI는 관계한 ORDER_TBL의 내용만을 출력하는데 USER_TBL의 내용까지도 포함하여 출력하려면 $expand 키워드를 사용해야 합니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL('홍길동')?$expand=ORDER_TBL

 

관계한 테이블이 2개 이상이라면 테이블을 ,로 구분할 수 있습니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL('홍길동')?$expand=ORDER_TBL, ETC_TBL

 

위에서 $expand 키워드를 사용했는데 $orderby키워드를 통해서는 정렬을 수행할 수 있습니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL?$orderby=name

 

오름차순과 내림차순에 대한 명시는 다음과 같이 지정합니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL?$orderby=name desc

 

$top 키워드를 사용하면 상위집계가 가능합니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL?$top=10

 

$skip은 무시할 리스트를 지정합니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL?$skip=1

 

지금까지는 아주 간단한 쿼리스트링의 예를 알아보았는데 쿼리구문중 가장강력한 $filter 키워드를 사용하면 다소 복잡한 형태로 데이터를 필터링 할 수 있습니다.

 

http://test.cliel.com/WcfDataService.svc/USER_TBL?$filter=age eq 35

 

USER_TBL에서 age값이 35인 데이터를 가져옵니다. 여기서 eq는 '같다'는 의미이며 아래와 같은 논리연산자를 추가적으로 적용할 수 있습니다.

 

 eq

 같다

 ne

 다르다

 gt

 크다

 ge

 크거나 같다

 lt

 작다

 le

 작거나 같다

 and

 논리 and

 or

 논리 or

 not

 논리 not

 

뿐만 아니라 $filter에는 다음과 같은 수학연산자와

 

 add

 더하기

 sub

 빼기

 mul

 곱하기

 div

 나누기

 mod

 나머지

 

각종 함수또한 사용이 가능합니다.

 

 substringof

 문자열포함

 endswith

 마지막 문자열 일치

 startswith

 시작 문자열 일치

 length

 문자열 길이

 indexof

 시작 문자열 포함

 replace

 문자열 교체

 substring

 특정 index에서의 문자열 포함

 tolower

 소문자 변환

 toupper

 대문자 변환

 trim

 공백제거

 concat

 문자열 결합

 day

 날짜비교

 hour

 시간비교

 minute

 분비교

 month

 월비교

 second

 초비교

 year

 년도비교

 round

 소수점 처리

 floor

 반올림

 ceiling

 반내림

 

http://test.cliel.com/WcfDataService.svc/USER_TBL?$filter=startswith(phone, '010')

 

아래는 위와 같이 만들어진 WCF 데이터 서비스를 프로그램에서 어떻게 호출하여 사용할 수 있을지를 보여주고 있습니다.

 

ServiceReference.testdbEntities tn = new ServiceReference.testdbEntities(new Uri("http://test.cliel.com/WcfDataService.svc"));

var query = from n in tn.USER_TBL
            where n.phone.Contains("010")
            select n;

string s = query.ToList()[0].name;

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] URL 매핑 (URL 라우팅)  (0) 2016.09.21
[ASP.NET] TreeView  (0) 2016.09.13
[ASP.NET] WCF - 2  (0) 2016.09.07
[ASP.NET] WCF - 1  (0) 2016.08.31
[C#] Stream  (0) 2016.08.24
[ASP.NET] 개인화(Personalization)  (0) 2016.08.16
WCF
0 0
Programming/.NET

WCF는 분산 응용프로그램을 만드는 하나의 수단으로써 사용될 수 있습니다. 분산 응용프로그램이라는 용어자체에 신경쓸 필요는 없습니다.

 

간단히 말해 A프로그램에서 B라는 프로그램으로 데이터를 던지면 B라는 프로그램은 받은 데이터로 특정 처리를 수행하고 그 결과를 다시 A에 반환합니다. 그러면 A프로그램은 B가 던져준 결과를 받아 사용자에게 표시합니다. 이런식으로 동작하는 구조가 분산응용프로그램의 개념이 될 수 있습니다.

 

ASP.NET에서도 WCF 웹서비스를 만들고 다른 프로그램에서 이를 활용할 수 있는데, 그 과정을 간단히 살펴볼까 합니다.

 

프로젝트에서 Add -> New Item 을 선택해 WCF Service를 선택합니다.

 

 

프로젝트에는 해당 이름으로 만들어진 cs파일이 하나 생성될 것입니다. 이 파일을 열어보면 아마도 다음과 같거나 비슷할 것입니다.

 

// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name

"IService" in both code and config file together.
[ServiceContract]
public interface IService
{
    [OperationContract]
    void DoWork();
}

 

우선 제일 먼저 인터페이스를 구성해야 합니다. 인터페이스는 외부에서 WCF서비스에 접근할때 호출할 수 있는 메소드를 구성하는 곳입니다.

 

public interface IService
{
    [OperationContract]
    int plus(int i, int j);
}

 

기존 DoWork 인터페이스를 무시하고 새로운 plus라는 인터페이스를 생성하였습니다. 또한 위와 같이 외부에 노출하고자 하는 인터페이스는 반드시 OperationContract 특성을 포함해야 합니다.

 

위에서 처럼 인터페이스를 만들고 나면 실제 이 인터페이스의 동작을 구현할 클래스를 다음과 같이 생성해야 합니다.

 

public class plusService : IService
{
    public int plus(int i, int j)
    {
        return i + j;
    }
}

 

이 클래스는 WCF 서비스파일인 svc파일에 구현되어야 하며 이전에 만들어진 인터페이스를 상속받아 야 합니다. 예제에서는 두개의 인자값을 받아 이들 값을 더하여 반환하도록 하였습니다.

 

이것으로 WCF서비스가 완성되었습니다. 해당 서비스가 제대로 동작하는지 확인하려면 웹브라우저에서 프로젝트의 서비스명.svc 파일에 대한 URL을 입력해 해당 서비스페이지를 호출해 보면 됩니다.

 

 

만약 위와 같은 화면이 나오지 않고 404관련 오류가 난다면 서버에서 WCF에 관한 필수항목이 설치되어 있는지 확인해 보시기 바랍니다.(HTTP Activation, TCP Port Sharing)

 

 

이제 해당 서비스의 plus메소드를 호출하여 실제 데이터처리를 수행해 보겠습니다.

 

우선 간단한 응용프로그램 프로젝트를 신규로 생성해 위에서 만든 WCF서비스를 참조해야 합니다. 이를 위해 프로젝트에서 마우스오른쪽을 클릭해 Add -> Service Refernce 항목을 클릭하십시오.

 

 

Add Service Reference 대화상자에서 위에서 만든 WCF서비스의 URL을 입력하고 Go 버튼을 눌러 서비스내역을 확인한 뒤 OK버튼을 눌러줍니다.

 

이로써 서비스참조가 완료되었습니다. 이제 참조한 서비스의 개체를 통해 두 숫자의 합을 구해보도록 하겠습니다.

 

ServiceReference.ServiceClient sc = new ServiceReference.ServiceClient();
int sum = sc.plus(100, 200);

 

XML웹서비스와 매우 비슷한 과정을 통해 WCF서비스를 사용할 수 있음을 알 수 있습니다.

 

만약 위에서 처럼 int나 string형식의 단순타입이 아닌 커스텀화된 복잡한 데이터타입을 전달해야 하는 경우 서비스를 계약(Contract)화 할 수 있습니다.

 

[DataContract]
public class Wellcome
{
    [DataMember]
    public string name;

    [DataMember]
    public string place;
}

 

필요한 데이터형은 [DataContract] 특성을 붙여서 작성하고 내부 클래스에 노출되어야할 필드에는 [DataMember]특성을 붙여야 합니다.

 

[ServiceContract]
public interface IService
{
    [OperationContract]
    string hi(Wellcome w);
}

 

인터페이스에는 위와같이 데이터용으로 전달될 Wellcome형식을 지정하고 반환형식도 적절하게 수정하도록 합니다.

 

public class Service : IService
{
    public string hi(Wellcome w)
    {

        return w.name + "님 " + w.place + "에 오신걸 환영합니다.";
    }
}

 

svc역시 수정된 인터페이스에 맞에 처리로직을 변경해줘야 합니다.

 

ServiceReference.Wellcome w = new ServiceReference.Wellcome();
w.name = "홍길동";
w.place = "서울";

ServiceReference.ServiceClient sc = new ServiceReference.ServiceClient();
string message = sc.hi(w);

 

서비스를 호출하는 클라이언트에서는 서비스에서 정의한 Wellcome형식의 개체를 생성해 필요한 값을 정의하고 해당 개체를 인자로 전달하여 WCF서비스를 호출하면 됩니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] TreeView  (0) 2016.09.13
[ASP.NET] WCF - 2  (0) 2016.09.07
[ASP.NET] WCF - 1  (0) 2016.08.31
[C#] Stream  (0) 2016.08.24
[ASP.NET] 개인화(Personalization)  (0) 2016.08.16
[ASP.NET] 서버 컨트롤 - 2 (렌더링)  (0) 2016.08.09
WCF
0 0
1
블로그 이미지

클리엘