수안이의 컴퓨터 연구실

  • Mainpage
  • About Me
  • Tags
  • Metapage
  • Notice
  • Location
  • Keywords
  • Guestbook
  • Admin
  • Write an Article
  • Total | 1693861
  • Today | 212
  • Yesterday | 588

3 Articles, Search for 'Architecture'

  1. 2007/07/23 WCF(Windows Communication Foundation) 아키텍처 개요
  2. 2007/06/21 Silverlight Architecture Overview
  3. 2007/04/29 High-Performance .NET Application Development & Architecture
Programming/WCF/WPF2007/07/23 09:34

WCF(Windows Communication Foundation) 아키텍처 개요

Microsoft Corporation

업데이트한 날짜: 2006년 3월

요약: WCF(Windows Communication Foundation) 아키텍처와 주요 개념에 대한 고급 정보를 얻을 수 있습니다. 코드 예에서는 WCF 계약, 끝점 및 동작에 대해 설명합니다(17페이지/인쇄 페이지 기준).

목차

소개
WCF의 기본
코드 예
요약

소개

이 문서에서는 WCF(Windows Communication Foundation) 아키텍처를 심도 깊게 살펴보고 WCF의 주요 개념과 이러한 주요 개념이 어떻게 함께 상호 작용하는지를 확인할 것입니다. 개념을 자세히 설명하기 위해 몇 가지 코드 예가 수록되어 있지만 코드가 이 문서의 중심은 아닙니다.

이 문서의 나머지 부분은 다음의 두 주요 섹션으로 구성됩니다.

  • WCF의 기본: WCF의 주요 개념, 용어 및 아키텍처 구성 요소에 대해 설명합니다.
  • 코드 예: WCF의 기본 부분에서 설명된 개념을 설명하고 이를 구체화하는 몇 가지 짧은 코드 예를 제공합니다.

이 기사에서는 Windows 워크플로 파운데이션을 간단히 소개하고 단계별 예를 통해 작동 방식을 설명합니다.

WCF의 기본

WCF 서비스는 끝점 컬렉션을 제공하는 프로그램이며 각 끝점은 세계와 통신하는 포털 역할을 합니다.

클라이언트는 하나 이상의 끝점과 메시지를 교환하는 프로그램이며 이중 메시지 교환 패턴으로 서비스로부터 메시지를 수신하도록 끝점을 제공하기도 합니다.

다음 섹션에서는 이러한 기본적인 내용을 좀 더 자세히 설명합니다.

끝점

서비스 끝점은 주소, 바인딩 및 계약으로 구성됩니다.

끝점의 주소는 끝점이 있는 위치의 네트워크 주소입니다. EndpointAddress 클래스는 WCF 끝점 주소를 나타냅니다.

끝점의 바인딩은 끝점에서 전송 프로토콜(예: TCP, HTTP), 인코딩(예: 텍스트, 이진) 및 보안 요구 사항(예: SSL, SOAP 메시지 보안)과 같은 항목을 포함하여 세계와 통신하는 방식을 지정합니다. Binding 클래스는 WCF 바인딩을 나타냅니다.

끝점의 계약은 끝점에서 통신하는 대상을 지정하며 기본적으로 단방향, 이중 및 요청/응답과 같은 기본 MEP(Message Exchange Pattern)가 있는 작업으로 구성되는 메시지 컬렉션입니다. ContractDescription 클래스는 WCF 계약을 나타냅니다.

ServiceEndpoint 클래스는 끝점을 나타내며 각각 끝점의 주소, 바인딩 및 계약에 해당하는 EndpointAddress, Binding 및 ContractDescription을 포함합니다(그림 1 참조).

그림 1. 각 서비스의 끝점에는 EndpointAddress, Binding, 그리고 ContractDescription이라는 계약이 포함되어 있습니다.

EndpointAddress

EndpointAddress는 기본적으로 그림 2에 표시된 것처럼 URI, ID 및 헤더(선택 사항)의 컬렉션입니다.

끝점의 보안 ID는 일반적으로 URI이지만 고급 시나리오에서는 Identity 주소 속성을 사용하여 URI에 관계없이 ID를 명시적으로 설정할 수 있습니다.

선택적 헤더는 끝점의 URI 이외의 추가 주소 정보를 제공하는 데 사용됩니다. 예를 들어 같은 주소 URI를 공유하는 여러 끝점을 구별하는 데 주소 헤더를 유용하게 사용할 수 있습니다.

그림 2. EndpointAddress에는 URI가 포함되고 AddressProperties에는 Identity와 AddressHeader 컬렉션이 포함됩니다.

바인딩

바인딩은 이름, 네임스페이스 및 구성 가능한 바인딩 요소의 컬렉션으로 구성됩니다(그림 3). 바인딩의 이름과 네임스페이스를 통해 서비스의 메타데이터에서 바인딩을 고유하게 식별할 수 있습니다. 각 바인딩 요소는 끝점이 세계와 통신하는 방법적 측면을 정의합니다.

그림 3. Binding 클래스와 해당 멤버

예를 들어 그림 4에서는 세 개의 바인딩 요소를 포함하는 바인딩 요소 컬렉션을 보여 줍니다. 각각의 바인딩 요소는 끝점과의 통신 방식에 대한 일부 측면을 정의합니다. TcpTransportBindingElement는 끝점에서 TCP를 전송 프로토콜로 사용하여 세계와 통신함을 나타냅니다. ReliableSessionBindingElement는 끝점에서 신뢰할 수 있는 메시징을 통해 메시지 배달 보증을 제공함을 나타냅니다. SecurityBindingElement는 끝점에서 SOAP 메시지 보안을 사용함을 나타냅니다. 각 바인딩 요소에는 대부분 끝점과의 통신 방식에 대한 고유 정보를 보다 자세히 정의하는 속성이 있습니다. 예를 들어 ReliableSessionBindingElement에는 필요한 메시지 배달 보증(예: 없음, 한 번 이상, 최대 한 번 또는 한 번만)을 지정하는 Assurances 속성이 있습니다.

그림 4. 세 가지 바인딩 요소가 있는 바인딩의 예

바인딩에서 바인딩 요소의 순서와 유형은 중요합니다. 바인딩 요소 컬렉션을 사용하여 통신 스택을 구축할 때, 통신 스택은 바인딩 요소 컬렉션에 있는 바인딩 요소의 순서에 따라 정렬됩니다. 컬렉션에 추가된 마지막 바인딩 요소는 통신 스택의 최하위 구성 요소에 해당하며 첫 번째 바인딩 요소는 최상위 구성 요소에 해당합니다. 받는 메시지는 아래에서 위로 이동하며 보내는 메시지는 위에서 아래로 이동합니다. 그러므로 컬렉션 내 바인딩 요소의 순서는 통신 스택 구성 요소에서 메시지를 처리하는 순서에 직접적인 영향을 줍니다. WCF에서는 대부분의 시나리오에서 사용자 지정 바인딩을 정의하지 않고 사용할 수 있는 미리 정의된 바인딩 집합을 제공합니다.

계약

WCF 계약은 끝점에서 외부 세계와 통신하는 대상을 지정하는 작업의 컬렉션입니다. 각 작업은 단방향 또는 요청/응답 메시지 교환과 같은 간단한 메시지의 교환입니다.

ContractDescription 클래스는 WCF 계약과 해당 작업을 정의하는 데 사용됩니다. ContractDescription 내에서 각 계약 작업에는 작업이 단방향 작업인지 또는 요청/응답 작업인지와 같은 작업의 측면을 정의하는 OperationDescription이 포함됩니다. 각 OperationDescription은 또한 MessageDescriptions의 컬렉션을 사용하여 작업을 구성하는 메시지를 정의합니다.

일반적으로 ContractDescription은 WCF 프로그래밍 모델을 사용하여 계약을 정의하는 인터페이스나 클래스에서 생성합니다. 이 형식에는 ServiceContractAttribute를 연결하고 끝점 작업에 해당하는 메서드에는 OperationContractAttribute를 연결해야 합니다. 특성을 연결한 CLR 형식으로 시작하지 않고 직접 ContractDescription을 작성할 수도 있습니다.

이중 계약은 클라이언트가 호출하도록 서비스에서 제공하는 집합과 서비스가 호출하도록 클라이언트에서 제공하는 집합 등, 논리적인 작업 집합 두 가지를 정의합니다. 이중 계약을 정의하기 위한 프로그래밍 모델에서는 각 집합을 별도의 형식으로 분할하고(각 형식은 클래스 또는 인터페이스여야 함) 서비스 작업을 나타내는 계약에 ServiceContractAttribute를 연결하여 클라이언트(또는 콜백) 작업을 정의하는 계약을 참조합니다. 또한 ContractDescription에는 각 형식에 대한 참조가 포함되어 있으므로 이를 하나의 이중 계약으로 그룹화할 수 있습니다.

바인딩과 마찬가지로 각 계약에는 서비스의 메타데이터에서 계약을 고유하게 식별하는 이름과 네임스페이스가 있습니다.

각 계약에는 계약의 동작을 수정하거나 확장하는 모듈인 ContractBehaviors 컬렉션도 포함됩니다. 다음 섹션에서는 이러한 동작에 대해 보다 자세히 설명합니다.

그림 5. WCF 계약을 정의하는 ContractDescription 클래스

동작

동작은 서비스 또는 클라이언트 기능을 수정하거나 확장하는 형식입니다. 예를 들어 ServiceMetadataBehavior에서 구현한 메타데이터 동작은 서비스에서 메타데이터를 게시할지 여부를 제어합니다. 마찬가지로 보안 동작은 가장 및 권한 부여를 제어하고 트랜잭션 동작은 트랜잭션 참여 및 자동 완료를 제어합니다.

동작은 채널 구축 프로세스에도 참여할 수 있으며 사용자가 지정한 설정 및/또는 서비스나 채널의 기타 측면에 따라 해당 채널을 수정할 수 있습니다.

서비스 동작은 IServiceBehavior를 구현하고 서비스에 적용되는 형식입니다. 마찬가지로 채널 동작도 IChannelBehavior를 구현하고 클라이언트 채널에 적용되는 형식입니다.

서비스 및 채널 설명

ServiceDescription 클래스는 서비스에서 제공하는 끝점, 서비스에 적용된 동작, 그리고 서비스를 구현하는 형식(클래스)을 비롯한 WCF 서비스를 정의하는 메모리 내 구조입니다(그림 6 참조). ServiceDescription은 메타데이터, 코드/구성 및 채널을 생성하는 데 사용됩니다.

이 ServiceDescription 개체를 직접 작성할 수 있습니다. 특정 WCF 특성을 연결한 형식에서 개체를 만들 수도 있으며 이 방법이 좀 더 일반적인 시나리오입니다. 이 형식을 위한 코드는 직접 작성하거나 svcutil.exe라는 WCF 도구를 사용하여 WSDL 문서로부터 생성할 수 있습니다.

ServiceDescription 개체를 명시적으로 만들고 채울 수 있지만 서비스 실행 과정의 일부로 백그라운드에서 만들어지는 경우가 많습니다.

그림 6. ServiceDescription 개체 모델

마찬가지로 클라이언트 쪽에서는 ChannelDescription이 특정 끝점에 대한 WCF 클라이언트의 채널을 정의합니다(그림 7). ChannelDescription 클래스에는 채널에 적용되는 동작인 IchannelBehaviors 컬렉션과 채널이 통신하는 끝점을 정의하는 ServiceEndpoint가 포함됩니다.

ServiceDescription과 달리 ChannelDescription에는 채널이 통신하는 대상 끝점을 나타내는 ServiceEndpoint가 한 개만 포함됩니다.

그림 7. ChannelDescription 개체 모델

WCF 런타임

WCF 런타임은 메시지 송수신을 담당하는 개체 집합입니다. 예를 들어 메시지 서식 지정, 보안 적용, 다양한 전송 프로토콜을 사용한 메시지 송수신 작업뿐 아니라 수신된 메시지를 해당 작업으로 전송하는 작업이 모두 WCF 런타임 내에서 이루어집니다. 다음 섹션에서는 WCF 런타임의 주요 개념에 대해 설명하겠습니다.

메시지

WCF 메시지는 클라이언트와 끝점 간의 데이터 교환 단위입니다. 메시지는 기본적으로 SOAP 메시지 InfoSet의 메모리 내 표현입니다. 메시지는 텍스트 XML에 제한되지 않으며 사용된 인코딩 메커니즘에 따라 WCF 이진 형식, 텍스트 XML 또는 다른 사용자 지정 형식을 사용하여 메시지를 serialize할 수 있습니다.

채널

채널은 끝점으로 메시지를 전송하고 끝점에서 메시지를 수신하는 핵심 추상입니다. 크게 보면 채널의 범주는 두 가지로 나뉩니다. 이 중 하나인 전송 채널은 TCP, UDP 또는 MSMQ와 같은 전송 프로토콜을 사용하여 불투명 8진수 스트림의 송수신을 처리하는 반면, 프로토콜 채널은 메시지를 처리하고 필요한 경우 수정하는 방식으로 SOAP 기반 프로토콜을 구현합니다. 예를 들어 보안 채널은 SOAP 메시지 헤더를 추가 및 처리할 수 있으며 메시지 본문을 암호화하여 수정할 수 있습니다. 채널을 다른 채널 위에 배치하고 이 채널을 다시 세 번째 채널 위에 배치하는 방식으로 채널을 구성하는 것이 가능합니다.

EndpointListener

EndpointListener는 런타임에서 ServiceEndpoint와 동일한 역할을 합니다. ServiceEndpoint의 EndpointAddress, 계약 및 바인딩(각각 통신 위치, 대상 및 방식을 나타냄)은 각각 EndpointListener의 수신 주소, 메시지 필터링 및 전송, 그리고 채널 스택에 해당합니다. EndpointListener에는 메시지 송수신을 담당하는 채널 스택이 포함됩니다.

ServiceHost 및 ChannelFactory

WCF 서비스 런타임은 대개 ServiceHost.Open을 호출함으로써 백그라운드에서 생성됩니다. ServiceHost(그 림 6)는 서비스 형식에 따라 ServiceDescription 생성을 주도하며 ServiceDescription의 ServiceEndpoint 컬렉션을 구성 또는 코드(또는 둘 다)에 정의된 끝점으로 채웁니다. 그런 다음 ServiceHost는 ServiceDescription을 사용하여 ServiceDescription 내의 각 ServiceEndpoint에 대한 EndpointListener 개체 형태로 채널 스택을 만듭니다.

그림 8. ServiceHost 개체 모델

마찬가지로 클라이언트 쪽에서는 클라이언트 쪽 ServiceHost에 해당하는 ChannelFactory에 의해 클라이언트 런타임이 생성됩니다.

ChannelFactory는 계약 형식, 바인딩 및 EndpointAddress에 따라 ChannelDescription 생성을 주도합니다. 그런 다음 이 ChannelDescription을 사용하여 클라이언트의 채널 스택을 만듭니다.

서비스 런타임과는 달리 클라이언트 런타임은 EndpointListener를 포함하지 않습니다. 클라이언트에서 항상 서비스에 대한 연결을 시작하므로 클라이언트는 받는 연결을 위해 "수신 대기"할 필요가 없기 때문입니다.

코드 예

다음 섹션에서는 서비스와 클라이언트를 어떻게 작성하는지 보여 주는 코드 예를 제시하겠습니다. 이러한 예는 위에서 소개한 개념을 구체적으로 설명하기 위한 것이며 WCF 프로그래밍을 가르치기 위한 것은 아닙니다.

계약 정의 및 구현

위에서 설명했듯이 계약을 정의하는 가장 쉬운 방법은 인터페이스나 클래스를 만들고 ServiceContractAttribute를 연결하는 것입니다. 이렇게 하면 계약으로부터 ContractDescription을 손쉽게 만들 수 있습니다.

인터페이스나 클래스를 사용하여 계약을 정의할 때 계약의 멤버인 각 인터페이스 또는 클래스 메서드에는 OperationContractAttribute를 연결해야 합니다. 예를 들면 다음과 같습니다.

using System.ServiceModel;

//인터페이스를 사용하여 정의된 WCF 계약
[ServiceContract]
public interface IMath
{
[OperationContract]
int Add(int x, int y);
}(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)

이 경우에 계약을 구현하려면 IMath를 구현하는 클래스를 만들면 됩니다. 이 클래스는 WCF 서비스 클래스가 됩니다. 예를 들면 다음과 같습니다.

//인터페이스를 구현하는 서비스 클래스
public class MathService : IMath
{
public int Add(int x, int y)
{ return x + y; }
}
끝점 정의 및 서비스 시작

코드나 구성에 끝점을 정의할 수 있습니다. 아래 예에서 DefineEndpointImperatively 메서드는 코드에서 끝점을 정의하고 서비스를 시작하는 가장 쉬운 방법을 보여 줍니다.

DefineEndpointInConfig 메서드는 구성(구성 예는 아래 코드 다음에 제시됨)에 정의된 동일한 끝점을 보여 줍니다.

public class WCFServiceApp
{
public void DefineEndpointImperatively()
{
//MathService를 위한 서비스 호스트를 만듭니다.
ServiceHost sh = new ServiceHost(typeof(MathService));

//AddEndpoint 도우미 메서드를 사용하여
//ServiceEndpoint를 만들고
//이를 ServiceDescription에 추가합니다.
sh.AddServiceEndpoint(
typeof(IMath), //계약 형식
new WSHttpBinding(), //기본 제공 바인딩 중 하나
"http://localhost/MathService/Ep1"); //끝점의 주소

//서비스 런타임을 만들고 엽니다.
sh.Open();

}

public void DefineEndpointInConfig()
{
//MathService를 위한 서비스 호스트를 만듭니다.
ServiceHost sh = new ServiceHost (typeof(MathService));

//서비스 런타임을 만들고 엽니다.
sh.Open();

}
}
<!-- 위의 코드에서 사용하는 구성 파일 -->
<configuration
xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.serviceModel>
<services>
<!-- 서비스 형식에서 참조하는 서비스 요소 -->
<service type="MathService">
<!-- ABC의 끝점을 정의하는 끝점 요소 -->
<endpoint
address="http://localhost/MathService/Ep1"
binding="wsHttpBinding"
contract="IMath"/>
</service>
</services>
</system.serviceModel>
</configuration>
끝점으로 메시지 전송

아래 코드는 IMath 끝점으로 메시지를 전송하는 두 가지 방법을 보여 줍니다. SendMessageToEndpoint는 채널 생성을 숨깁니다. SendMessageToEndpointUsingChannel 예에서는 이 과정이 명시적으로 수행되지만 여기에서는 백그라운드에서 수행됩니다.

SendMessageToEndpoint의 첫 번째 예에서는 svcutil.exe라는 도구와 서비스의 메타데이터를 사용하여 계약(이 예에서는 IMath), 계약을 구현하는 프록시 클래스(이 예에서는 MathProxy) 및 관련 구성(여기에는 나와 있지 않음)을 생성합니다. 다시 설명하지만 IMath에 의해 정의된 계약은 대상(즉, 수행할 작업)을 지정하며 생성된 구성에는 바인딩(방식)과 주소(위치)가 포함됩니다.

이 프록시 클래스를 사용하려면 인스턴스화한 다음 Add 메서드를 호출하면 됩니다. 프록시 클래스는 백그라운드에서 채널을 만들고 이 채널을 사용하여 끝점과 통신합니다.

아래에 있는 SendMessageToEndpointsUsingChannel의 두 번째 예는 ChannelFactory를 직접 사용하여 끝점과 통신하는 경우를 보여 줍니다. 이 예에서는 프록시 클래스와 구성을 사용하지 않고 직접 ChannelFactory<IMath>.CreateChannel을 사용하여 채널을 만들었습니다. 또한 끝점의 주소와 바인딩을 정의하는 데 구성을 사용하지 않고 ChannelFactory<IMath> 생성자가 이 두 가지 정보를 매개 변수로 받았습니다. 끝점 정의에 필요한 세 번째 정보인 계약은 T 형식으로 전달됩니다.

using System.ServiceModel;
//이 계약은 svcutil.exe에 의해
//서비스의 메타데이터로부터 생성됩니다.
public interface IMath
{
[OperationContract]
public int Add(int x, int y)
{ return x + y; }
}


//이 클래스는 svcutil.exe에 의해
//서비스의 메타데이터로부터 생성됩니다.
//생성된 구성은 여기에서 제시되지 않습니다.
public class MathProxy : IMath
{
...
}

public class WCFClientApp
{
public void SendMessageToEndpoint()
{
//여기에서는 svcutil.exe에 의해 서비스의 메타데이터로부터 생성된
//프록시 클래스를 사용합니다.
MathProxy proxy = new MathProxy();

int result = proxy.Add(35, 7);
}
public void SendMessageToEndpointUsingChannel()
{
//여기에서는 채널을 만들기 위해 ChannelFactory를 사용합니다.
//주소, 바인딩 및 계약 형식(IMath)을
//지정해야 합니다.
ChannelFactory<IMath> factory=new ChannelFactory<IMath>(
new WSHttpBinding(),
new EndpointAddress("http://localhost/MathService/Ep1"));
IMath channel=factory.CreateChannel();
int result=channel.Add(35,7);
factory.Close();

}
}
사용자 지정 동작 정의

사용자 지정 동작을 정의하려면 IServiceBehavior를 구현해야 합니다(클라이언트 쪽 동작의 경우에는 IChannelBehavior). 아래 코드에서는 IServiceBehavior를 구현하는 동작의 예를 보여 줍니다. 이 코드는 IServiceBehavior.ApplyBehavior에서 ServiceDescription을 검사하며 ServiceDescription 내의 각 동작의 이름은 물론 각 ServiceEndpoint의 주소, 바인딩 및 계약을 작성합니다.

이 특정 동작은 System.Attribute에서 상속한 특성이기도 하므로 아래와 같이 선언적으로 적용할 수 있습니다. 그러나 동작이 특성이어야 하는 것은 아닙니다.

[AttributeUsageAttribute(
AttributeTargets.Class,
AllowMultiple=false,
Inherited=false)]
public class InspectorBehavior : System.Attribute,
System.ServiceModel.IServiceBehavior
{
public void ApplyBehavior(
ServiceDescription description,
Collection<DispatchBehavior> behaviors)
{
Console.WriteLine("-------- Endpoints ---------");
foreach (ServiceEndpoint endpoint in description.Endpoints)
{
Console.WriteLine("--> Endpoint");
Console.WriteLine("Endpoint Address: {0}",
endpoint.Address);
Console.WriteLine("Endpoint Binding: {0}",
endpoint.Binding.GetType().Name);
Console.WriteLine("Endpoint Contract: {0}",
endpoint.Contract.ContractType.Name);
Console.WriteLine();
}
Console.WriteLine("-------- Service Behaviors --------");
foreach (IServiceBehavior behavior in description.Behaviors)
{
Console.WriteLine("--> Behavior");
Console.WriteLine("Behavior: {0}", behavior.GetType().Name);
Console.WriteLine();
}
}
}
사용자 지정 동작 적용

모든 동작은 ServiceDescription(클라이언트 쪽에서는 ChannelDescription)에 동작의 인스턴스를 추가하여 강제로 적용할 수 있습니다. 예를 들어 InspectorBehavior를 강제로 적용하려면 다음과 같이 코드를 작성합니다.

ServiceHost sh = new ServiceHost(typeof(MathService));
sh.AddServiceEndpoint(
typeof(IMath),
new WSHttpBinding(),
"http://localhost/MathService/Ep1");
//강제로 동작을 추가합니다.
InspectorBehavior behavior = new InspectorBehavior();
sh.Description.Behaviors.Add(behavior);
sh.Open();

또한 System.Attribute에서 상속한 동작을 서비스에 선언적으로 적용할 수 있습니다. 예를 들어 InspectorBehavior는 System.Attribute에서 상속되었으므로 다음과 같이 선언적으로 적용할 수 있습니다.

[InspectorBehavior]
public class MathService : IMath
{
public int Add(int x, int y)
{ return x + y; }
}
요약

WCF 서비스에서는 각 끝점이 세계와 통신하는 포털이 되는 끝점 컬렉션을 제공합니다. 각 끝점에는 주소, 바인딩 및 계약(ABC)이 포함됩니다. 주소는 끝점이 있는 위치이며 바인딩은 끝점의 통신 방식이고 계약은 끝점의 통신 대상입니다.

서비스에서는 ServiceDescription에 서비스에서 제공하는 끝점을 각각 정의하는 ServiceEndpoint 컬렉션이 포함됩니다. ServiceHost에서는 이 정의로부터 ServiceDescription 내의 각 ServiceEndpoint에 대한 EndpointListener를 포함하는 런타임을 만듭니다. 끝점의 주소, 바인딩 및 계약(통신 위치, 대상 및 방식을 나타냄)은 각각 EndpointListener의 수신 주소, 메시지 필터링 및 전송, 그리고 채널 스택에 해당합니다.

마찬가지로 클라이언트에서 ChannelDescription에는 클라이언트가 통신하는 ServiceEndpoint가 하나 포함됩니다. ChannelFactory에서는 이 ChannelDescription으로부터 서비스의 끝점과 통신할 수 있는 채널 스택을 만듭니다.

"WCF/WPF" 카테고리의 다른 글
  • Windows Presentation Foundation으로 최상의 사용... (0)2007/07/23
  • Windows Presentation Foundation 소개 (0)2007/07/23
  • Windows Communication Foundation과의 관계로 보... (0)2007/07/23
  • WCF(Windows Communication Foundation) 아키텍처... (0)2007/07/23
2007/07/23 09:34 2007/07/23 09:34
Posted by webdizen
Tags Architecture, WCF, Windows Communication Foundation
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/3084

Leave your greetings.

[로그인][오픈아이디란?]

Web/Silverlight2007/06/21 22:44

Silverlight Architecture Overview

출처 : http://msdn2.microsoft.com/en-us/library/bb428859.aspx

Barak Cohen

Microsoft Corporation

April 2007

Applies to:
  Silverlight Community Technology Preview (CTP) Feb 2007

Summary: This white paper provides a high-level overview of the Silverlight (formerly known as code name "WPF/E") architecture and how it fits into the Microsoft offering for building next-generation Web applications. Also, this white paper provides an architectural review of the Silverlight technology. (6 printed pages)

Contents

Introduction
Silverlight as Part of a User-Experience Continuum
Silverlight Architecture
Deployment and Packaging
Scenarios for Using Silverlight
Conclusion

Introduction

Microsoft Silverlight is a cross-browser, cross-platform plug-in for delivering the next generation of .NET based media experiences and rich interactive applications (RIAs) for the Web. Silverlight offers a flexible and consistent programming model that supports AJAX, Python, Ruby, and .NET languages such as VB and C#, and integrates with existing Web applications. Silverlight media capabilities include fast, cost-effective delivery of high-quality audio and video to all major browsers including Firefox, Safari and Internet Explorer running on the Mac or on Windows. By using Expression Studio and Visual Studio, designers and developers can collaborate more effectively using the skills they have today to create Silverlight web experience.

Silverlight as Part of a User-Experience Continuum

Now, more than ever, customers are demanding applications and online experiences that not only meet their individual needs in terms of effectiveness and efficiency, but also address the perception of satisfaction the user has with a company's products or services. In most cases, the level of satisfaction will have a network and an emotional effect, shaping perceptions of the company as a whole, and, as an extension, the perceptions of those with whom the individual comes into touch. Microsoft acknowledges this connection and has a made a renewed commitment to user experience (UX) as a part of the end-to-end experience. UX is more than a pretty UI; it is the aggregation of the interaction point of a user with an application. Our mission is thus to enable a great user experience wherever the customer needs that: on the Web, on devices, in Office, and in Windows.

Two recent examples of Microsoft's own investment in UX are Microsoft Windows Vista and Microsoft Office 2007. By focusing on the end-user experience first, subtle and somewhat radical changes were made to both products in order to address productivity and satisfaction.

  • Windows Vista introduces easier ways to visualize and organize your files, media, and communications. In every case of the UI, a focus on user-centric task accomplishment and experience was put first. Other examples of focusing on UX include the new task switcher (Alt+Tab) and Wi-Fi signal notification.
  • Microsoft Office 2007 has introduced the new "Ribbon" concept to replace traditional toolbars. A natural extension, the ribbon reduces time to find any given feature in an Office application to about 10 seconds.

Both of these decisions were heavily influenced by design and designers, working collaboratively with the rest of the development team. To learn more, visit http://www.microsoft.com/design.

사용자 삽입 이미지

Figure1. Microsoft UX continuum

From a platform perspective, Microsoft introduces a consistent offering that uses common skills to address the different application-interaction surfaces, as indicated in Figure 1.

  • ASP.NET AJAX offers the benefits of standard Microsoft support (around-the-clock support for a period of 10 years) for AJAX-enabled applications built around Web standards. It allows standard Web applications to be more effective by improving the interaction parameters of the application (such as refresh, resource usage, and navigation).
  • For Web experiences that need 2-D animation, vector graphics, and high-fidelity audio and video on the Web, Silverlight is being introduced to extend the capability of the browser to render XAML in addition to HTML. By embracing Web architecture for development, including industry-standard AJAX (Asynchronous JavaScript+XML) and inline XML markup (XAML) for presentation, Microsoft is working to break rich elements on Web pages out of the "black box" that exists today. As an added benefit, content authored in Silverlight and ASP.NET AJAX becomes more discoverable while offering the benefits of being cross-platform (Windows and Macintosh) and cross-browser (Internet Explorer, Firefox, Safari).
  • ASP.NET AJAX and Silverlight are designed to be complementary technologies. In the broader sense, Silverlight can interact with any AJAX application, both client- and server-side. Examples for such integration include mapping applications, video playback with rich presentation, and more.
  • For connected applications on Windows, Microsoft provides the .NET Framework 3.0 programming layer (shipped in Windows Vista and available for Windows XP) that includes the Windows Presentation Foundation (WPF). By using WPF, one can create rich, immersive, connected applications and experiences that can take full advantage of the Windows platform, including UI, media, offline communication, and document support. WPF uses a superset of the same XAML that is used by Silverlight.

사용자 삽입 이미지

Figure 2. Microsoft end-to-end offering for UX

As Figure 2 shows, Silverlight is not an isolated island; it is a piece in a consistent end-to-end offering that enables taking application experiences to the next level. This offering includes server-side components, tools (Microsoft Expression and Microsoft Visual Studio), and UX technologies.

Silverlight Architecture

Silverlight has few basic properties:

  • It integrates with various browsers on Windows and on the Macintosh.
  • It enables rendering of richer user experiences that are defined by XAML.
  • It render media (music and video).
  • It enables programming that is consistent with the Web programming model.
  • It is small.

Silverlight was designed to address these properties, as Figure 3 shows.

사용자 삽입 이미지

Figure 3. Silverlight architecture

  • Lightweight browser plug-in—Silverlight has Windows and Macintosh modules that are designed to enhance Internet Explorer (versions 6.0 and 7.0), Firefox 2.0, and Safari browsers. The December 2006 CTP for Windows is 1.1 MB in size.
  • Native presentation runtime— Software-based browser enhancement that allows rendering of XAML-based interactive 2-D graphics, text, and media, in addition to the browser native rendering of HTML. XAML can be used inline, in a file, or in a package.
  • Interactive video and audio—Cross-platform independent media runtime that can render Windows Media content (WMV and WMA) in addition to MP3 (will be available after the December 2006 CTP). Video and audio are handled as a media element in XAML, enabling flexibility in their presentation. Furthermore, the media support leverages the huge infrastructure and ecosystem around Windows Media, enabling cost-effective delivery of top-quality media.
  • Programming layer—In consistency with the Web architecture, Silverlight XAML is exposed using a DOM model to JavaScript. That way, AJAX programs can utilize the extended markup rendering capability using the same programming paradigms and practices (on the client and on the server). After the December 2006 CTP, we will also enable a managed code programming model using a subset of full CLR that will enhance the programmability side of the browsers to enable more performant and more scalable Web applications.

Deployment and Packaging

Content for a Web page that contains Silverlight elements can be created by using the following tactics:

  • Inline XAML and JavaScript.
  • External XAML files and JavaScript files.
  • Compressed content package (available after the December 2006 CTP) that contains XAML, managed code, images, fonts, and media. Streaming media sources can be referenced from the XAML media elements.

사용자 삽입 이미지

Figure 4. Silverlight packaging (after Feb 2007 CTP)

We believe that the flexibility of application packaging and the consistency of the application architecture with Web standards and operations will create many opportunities for improving the impact and effectiveness of Web applications, making applications more scalable, fault-tolerant, and dynamic (they can change their markup on the fly), and making content more discoverable.

Web pages that require Silverlight can detect if the Silverlight plug-in is installed, and can direct users to download it and install it (either through a redirect or through an object tag). The Silverlight SDK has documentation on that.

Scenarios for Using Silverlight

Silverlight is perfect for the following Web application scenarios that encompass many real-world scenarios:

  • Web media— Branded playback with events, video and marketing mix, dynamic videos with ads, audio playback, and so forth
  • Rich islands on a page (mini apps)— Casual games and gadgets
  • Web visualization elements— Navigation properties, data visualization, and ads

Silverlight is designed for Web page content that is connected to its host (it will not work offline), that deeply engages the user, and that can render on any browser.

Conclusion

This article provided a high-level overview of the Silverlight architecture and how it fits into the Microsoft offering for building next-generation Web applications. Silverlight is part of a larger revolution of the ways applications are designed, built, and delivered. With markup-based UI and flexible programming models, businesses will be able to offer better experiences on the right form factor for their customers.

"Silverlight" 카테고리의 다른 글
  • SilverLight Introduction (0)2007/07/10
  • Silverlight Architecture Overview (0)2007/06/21
  • Microsoft Silverlight 1.1 Development Reference (0)2007/05/03
2007/06/21 22:44 2007/06/21 22:44
Posted by webdizen
Tags Architecture, Silverlight
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/3051

Leave your greetings.

[로그인][오픈아이디란?]

Programming/.NET2007/04/29 11:52

High-Performance .NET Application Development & Architecture

Introduction

It has always been a goal of project architects to plan an effective strategy from the ground up in regards to an new application. All relevant factors are taken into consideration with respect to the application, from its design and layout to a functional website infrastructure. Pre-.NET strategies and design guidelines still effective now were developed with Microsoft's DNA (Distributed interNet Application) platform. This model successfully served the purpose of architecting N(any number of)-Tier (levels) applications. In its basic sense, as in most robust, distributed applications, you'll architect 3 main layers or Tiers: presentation, business rules and data access.

Now, each independent layer within itself, is another issue altogether. Each one has its own methodologies regarding its perspective best practices. In other words, many factors will determine its proper design, efficient data access and visually pleasing presentation. That is why each Tier, with respect to the overall success and health of your application, should be maximally optimized. So in light of such, we'll go through each Tier and dependent of your situation, offer the very best methods resulting in one robust, secure and high-performance distributed application.

One issue that is slightly bemused is that of Performance and Scalability. However similar these may sound in end-result, none could be further from the truth. Performance is a matter of responsiveness, how well a application performs, as our General .NET Best Practices section below will help you capitalize on. Scalability is another subject slightly paralleling performance only within the confines that it has to be high-performance for all users and not affect anyone else nor the tie up the server for that matter. Highly-scalable applications do their best to absolutely minimize network traffic, and server-side database interaction. By these measures then, could scalability be in collaboration with performance.

At any rate, as aforementioned, architecting a robust application involves the time-tested, structurally sound methodology in having an application made up of separate, easily maintainable components that would require modification only once to effect site-wide changes. This, among other things, creates harmony among IT teams, guaranteeing no one will interfere with or break someone else's work. The parts individually, in this sense, are on par to the sum total. To digress, how many audiophiles would buy a all-in-one stereo unit, rather than various individual high performance components? Right, I think none would.

Anyway, before proceeding on, this article assumes you have some basic .NET and or development experience. Still, it's important to realize that this article is a codified manual of tips and optimization techniques for the more or less experienced developer and, or expert looking for more ways in maximizing an application. Beginners may find it hard in following some sections. Nevertheless, I have made ample effort to direct beginners to any outside sources where more in-depth information is available, should one require it, and recommended.

In any case, we'll begin.

Planning

Planning is the first stage all developers embark on - what to do, how to do it or the best way to do it. Proper planning is key in determining that all aspects of the application are architected correctly and efficiently, and the right direction is chosen. Once this is established, the actual development begins to take place. From this point on you'll begin to deal with the application at all levels and its individual components, and how each requires individual optimization. Thus as a whole it becomes one solid, cohesive application.

Good robust, application architecture insists on it being functional, responsive, secure and user friendly. I'll briefly point out that when presenting an finished application, it must be faultless. People like a speedy application with complementing visually appealing elements. Most users will never fully appreciate all the sophistication it took behind the scenes to make the application work, they initially focus on its design and layout. Although, I won't demonstrate web site and graphics design, I felt it a point needing attention, even thought this article will not demonstrate such. So keep this in mind, that for a fully robust, cohesive application, design and back end do go hand-in-hand, not productively but ultimately. So all parts must be on equal level in making it an cohesive application. Again, even thought this article is really more for .NET project architects, it's a fact that some developers out there simply do it all. For some more info of project planning read - Web Application Development - A Guide to Success.

That aside, prior to dealing with the three archetypal levels inherent to "N-Tier," we'll be discussing some conventional information regarding application and server security. After that, we'll dive right into offering general .NET Best Practices. Then move on to error handling, and further deal with some common .NET errors you may encounter, and finally look into performance testing.

As a final note, .NET's documentation offers an absolutely exhaustive collection of information which is the reason why you'll notice numerous links throughout this article directing you to more in-depth information where applicable and necessary.

Now let's get started with .NET security, and rest assured that our application is being built on a secured platform, and that all security precautions were taken and are intact.

Application/Server Security

Security in .NET, and really in any application, is and should be of the highest importance. It is critical that at all times your application be unbreakable and tamperproof, as much as possible, from anything. Anywhere from someone fiddling with your query string to server / data access authorization to preventing SQL Injection attacks.


As the topic of security is really too vast and complex to be dealt with here in any great detail, we'll offer some generalized pointers and tips to set you off in the right direction with a good overview of the various security methods available. Oh, btw, work closely with your Network Admin, make sure you're both on the same page.

Security in .NET works with two types of concepts:

  1. Authentication : Confirms users identity and credentials in allowing them access, through either valid Windows Accounts or IIS, that include methods such as certificate (SSL), Windows (NLTM or Kerberos), Forms, and Passport authentication.
  2. Authorization : Allows or denies file or url access to a given user based on certain criteria, or on ACL (Access Control List) settings in Windows. Authorization parallels .NET's users and roles settings within its web.config file's <authorization> element node. Note all authorization is always done after authentication.

With which introduces us to the following kinds of security implementations.:

IIS Security

IIS (Internet Information Services) is the first line of defense for application security, since all requests must go through here first. This method of security rests solely on setting certain elements found in IIS's Directory Security / Anonymous Access and Authentication Control tab. This verifies IP/Domains and user accounts via ACLs, that are preset Windows or Active Directory User Accounts. Incidentally, ACL access is verified whether or not anonymous access is enabled. Disabling Anonymous Access will bring up the logon dialog box, that would require you a valid Windows account, unless you're on the same domain.

Generally, for any fully public sites you should leave all default settings to manage Anonymous Access . Windows (Windows Integrated Security) handles this, whereby it assigns its own IUSR_computername account the privilege, and all users of this site fall under the Guest group account.

Moreover, you could also disable anonymous access and integrate Basic Authentication (with disabled Windows Integrated Security) that presents the user with the common dialog-driven box to enter in their credentials. Basic security mode further allows control via a domain controller, though this should not be the sole method in doing such. At any rate, Basic Authentication is the most frequently used security measure because this works well among all browsers, and is commonly used in concert with SSL (Secure Sockets Layer) technology for added security.

Another IIS security measure, though not widely used since all browsers do not support it, is Digest Authentication . This was Microsoft's way of remedying one issue that has befallen Basic Authentication which was sending passwords in plain text, and the solution here sends a digest (Hash encryption) in place of the actual password.

Finally, is Integrated Windows Authentication or NTLM challenge/response protocol. This increased security method, since it doesn't work with Netscape, is not really suited for the Internet, but rather a fully IE-inherent Intranet.

Now that we've got a grasp on the IIS's security options, IIS has many more options within its properties that are adjustable for not only additional security measures, but even performance.

.NET/IIS Permissions

Moving on now, .NET allows programmatic determination of NT group permissions as well, using two .NET (principal objects) classes : WindowsPrincipal (automatically created when using Windows authentication) or GenericPrincipal (customizable event using the WindowsAuthentication_OnAuthenticate event (within the Global.asax file) that occurs during authentication, used with None Authentication mode in web.config):

// With users being members of a Windows account group on a domain: 
if (User.IsInRole ("Domain\\Group")) {
...
// Or via Windows built-in account groups users get added to:
if (User.IsInRole ("BUILTIN\\Administrators")) {
...

Or through user identity and role, including web.config's case-sensitive credential information, as discussed in the next section containing Forms Authentication, and through Windows Authentication:

using System.Security.Principal;
if ((User.Identity.Name == "authorizedUsername") && (User.Identity.IsAuthenticated == true)) {
AllowAccess();
}

Finally, you could also implement the WindowsIdentity Class to validate a Windows user account, using the GetCurrent method:

using System.Security.Principal; 

WindowsIdentity User = WindowsIdentity.GetCurrent();

if ((User.Name == "Domain\\User") && (User.IsAuthenticated == true)) {
AllowAccess();
}

Note: Anonymous Access, as well as impersonation, should be disabled to initiate these kinds of Role-Based Security inquiries, and Authentication Mode should be set to Windows in your web.config file. Otherwise, you'll retrieve .NET's IUSR_machinename user account info - "Domain\ASPNET", or simply nothing at all, due to the enabled impersonation.

Moreover, employing this works as well for applying file authorization through the file's Security Permissions - right-click Properties settings, and URL Authorization.

So now that we've got a good overview on identifying permissions, and since we're on the topic of IIS, we'll briefly discuss some general IIS optimizations that will help our server's overall efficiency and performance.

General IIS Optimizations

  • Make sure Mappings under Home Directory-->Configuration-->Application Configuration has Cache ISAPI Applications enabled, as well as Buffering and other Cache Options under Options
  • Also enable HTTP compression found under the Service tab
  • Adjust the Performance Tuning of your server to an amount of anticipated site activity or hits you may expect to get, and enable Process Throttling in preventing your site from overusing CPU processing, which may indicate an external attack of some kind. Both these adjustments can be made under the Performance tab, within the Web Site's Master Properties
  • Finally, enable performance settings for all your sites under the Default Web Site Properties-->Server Extensions tab, and adjust the performance list box for the appropriate amount of pages that you may have on your site

Web.Config or ASP.NET Security

.NET incorporates this configuration file that is capable of doing a great deal when it comes to security, among other things. For starters, it's the perfect place to store all your appsettings or database connection strings that'll be accessed in your application. Furthermore, everything regarding your application's security can be stored here within its perspective nodes, from allowing specific users and groups access to a particular file location path or multiple location paths to storing account credentials, examine specific HTTP access, and standard Authentication.

A typical web.config configuration file

<configuration> 
      <appSettings> 
        <add key="myDataBase" value=id; _=pw; Data=myDS; _=myCat; Enlist=false;" /> 
      </appSettings> 
      <location path="securePage.aspx"> 
        <system.web="None | Windows | Forms | Passport"/> 
          <forms forms="securepage" loginUrl="login.aspx" /> 
          <credentials passwordFormat="Clear | MD5 | SHA1"> 
            <user name="Jimmy" password="hashed Password"/> 
          </credentials> 
          </authentication> 
          <authorization> 
            <!-- General application authorization -->
            <allow verbs="POST" users="Jimmy, Lumi" roles="Administrators" /> 
            <allow verbs="GET" users="Peter" roles="Debugger Users" /> 
			<!-- URL Authorization --> 
            <allow users="domain1\user, domain2\group" /> 
            <!--Deny anonymous or All Users--> 
            <deny users="? | *" /> 
          </authorization> 
        </system.web> 
      </location> 
      <!--For a second secure page--> 
      <location path="securePage2.aspx"> 
        <!-- Other configuration settings--> 
      </location> 
<configuration> 

As seen, the web.config file is capable of many security measures, from public access to Passport authentication. We'll now discuss them in turn:

<authentication mode="None | Passport | Windows | Forms "/>

Impersonation

.NET allows general, public access through impersonation, where IIS uses its own IUSR_computername account process token to control authentication and authorization. As far as strict security is concerned, this is not really it. That is why it best serves all public sites, and is set in the web.config file like so:

<system.web="true" /> 
</system.web>

The identity key element holding the attribute impersonate, set to true is the equivalent of IIS's Anonymous access, but directly affects your .NET application here more, since it helps overcome any " Access Is Denied " problems with .NET on a public site.

And due to this, your SQL connection string would be this below, providing both your application and SQL Server share the same domain or trusted domains. Otherwise you'll receive the Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON' error.

"Data Source=myDS; Initial Catalog=myCat; Enlist=false; Trusted_Connection=yes"

For more info on .NET Impersonation, readImplementing Impersonation in an ASP.NET Application.

Default/None (Custom) Authentication (IIS's Anonymous Authentication)

The default setting of no authentication or None mode , is typically for public sites (impersonation). When included for this purpose in your configuration file, does two things, helps performance since no extra runtime processing is needed and could allow customized authentication to take effect, whether application wide via the global.asax or HTTP modules, working with the AuthenticateRequest event.

Passport Authentication

As noticed in the authentication key element above, one such technique, different among the others as I'm sure most have seen is .NET Passport authentication mode . This service offered by Microsoft, is a somewhat of a one-stop shopping methodology, enabling you a unified access across many applications.

Windows Authentication (IIS's Integrated Windows / Digest Authentication)

Next, as aforementioned in the IIS section above, is Windows Mode , the default security method, as it indeed relies on Windows Authentication in IIS for its authentication, prior to .NET gaining control. Furthermore, because of its nature it is best suited for Intranet sites.

In the web.config file, the authentication node is set for ACL Windows authorization, and is also based on the elements contained within the authorization nodes for which users, roles or groups are allowed or denied access, or URL authorization. Additionally, within these nodes you may even specify what type of HTTP action is allowed, using the verbs key, and setting it for either POST, GET, HEAD, or DEBUG.

Here we've set Role-Based Security within the following web.config's <allow> element key setting, and in this instance it'll allow only Admins and Debuggers access, and deny everyone else:

<configuration> 
<system.web="Windows" /> 
  <authorization> 
	<allow roles="Administrators, Debugger Users"/> 
	<deny users="*"/> 
  </authorization> 
</system.web> 
</configuration>

Forms Authentication

And finally, there is Forms (Cookie based) Authentication Mode , where your dealing with security based upon criteria captured through a form on your web page. This could be Forms-based (using configuration credentials) or Windows/Role-Based, with account credentials set in place and stored in a database, XML file, text file, or even a remote Web Service, rather than solely in an ACL list. Incidentally, this mode enables good flexibility for creating more personalized sites.

Forms Authentication is your best bet for Internet security-based applications such as an E-Commerce site, since it supports all browsers, is fully customizable, and works well with other security additions such as SSL. Incidentally, cookie size limit with IE5 and higher browsers, has no limit.

Here is an example of Forms-Based Authentication using the FormsAuthentication Class ,

if (FormsAuthentication.Authenticate (userName, userPassword)) { 
//Redirect user back to original URL once logged in or do whatever
FormsAuthentication.RedirectFromLoginPage (userName, boolean);
} else {
Response.Redirect ("login.aspx");
}

with the web.config file holding the user's credentials and authorization:

<authentication mode="Forms"> 
	<forms name=".ASPXAUTH" loginUrl="/login.aspx"> 
	  <credentials passwordFormat="userName" password="encryptedPassword"/> 
	  </credentials> 
	</forms> 
</authentication> 
<authorization> 
	<!--Deny all unauthenticated users-->
	<deny users="?"/> 
</authorization> 

Forms authorization as seen, is controlled via cookies (name attribute) that you name within the forms element key, and the loginUrl or login page to use. This is useful for any pages requiring strict security measures, whereby all unauthorized users get sent to your login page to enter their credentials in a form, and must match the Forms Authentication Credentials before access is granted.

Alternatively, you can utilize the same FormsAuthentication class technique above using a database housing users and roles, as well as utilizing the FormsAuthenticationTicket Class. This method of course has its advantages since a database could store as many credentials as you need. Additionally, if you so choose, you could even store credentials within an XML file, providing you set ACL permissions on its location.

Now, as far as encrypting passwords is concerned, its significance cannot be really stressed enough. It's fortunate however, that it is incredibly easy to do for the above credentials using the (get ready for a long one) FormsAuthentication.HashPasswordForStoringInConfigFile Method. This method uses two parameters, one for the password itself, and the other for the type of hash algorithm you require, SHA1 or MD5:

string encyptedPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(password.Text, "encryptionMethod");

Furthermore, within the web.config file you could add any specific authenticated page and allow certain user's access, based on specific HTTP method and deny access to all all or specific non-authenticated user's. Subsequently, by choosing Forms Authentication as a custom security measure, then bear in mind that Anonymous Authentication should be enabled in IIS.

Read Forms Authentication in .NET's documentation for more info.

Miscellaneous

Now aside from these aforementioned security measures, I'll discuss a few miscellaneous encryption-enabling configuration settings helpful in further securing your application.

If you're concerned about the security of any viewstate data being examined or manipulated in any way, then set enableViewStateMac (MAC stands for message authentication code) property to true, as demonstrated below, and individually within each .aspx page's @Page Directive - EnableViewStateMac="true" as well. This property hash encrypts the viewstate and ensures that it has not been altered in any way. It stores this information in the machine.config file's <machineKey> node element. Luckily, this is already the default in .NET, phew!

Further encryption of any viewstate, or forms authentication cookie data could be physically set within the web.config by adding - <machineKey validation="3DES" /> , .NET's Triple-DES (3DES) encryption or any other encryption method you prefer.

As for sites dealing with file uploading, we both know limits have to be set. Users obviously can't upload to their hearts content, and bog down the server. So setting .NET's HTTP runtime maxRequestLength parameter, for 2 megabytes as demonstrated below, ensures that any larger files are declined.

<system.web="true" enableViewStateMac="true" /> 
	<machineKey validationKey="autogenerate | value" decryptionKey="autogenerate | value" 
		validation="SHA1 | MD5 | 3DES" /> 
	<httpRuntime maxRequestLength="2048" /> 
</system.web>

ADO.NET Security

In all database applications you're dealing with a form of some kind that will be accessed by a user who will enter information to be verified against a database or other means, before any access or data is allowed. Protecting information or access in this situation isn't too difficult a concept, it's simply a matter of storing (preferably encrypted info) into a database, then validating this on login. For more info check out - Using MD5 to Encrypt Passwords in a Database. Almost certainly your site will also include a searchable form for users to enter search criteria in obtaining data.

Aside from these somewhat innocent scenarios, and by virtue of creating forms that enables users the ability to submit information to your application, you're left vulnerable to a malevolent technique exploited by hackers known as SQL Injection . This is a security threat whereby SQL statements or other malicious code, through form fields, are injected in addition to your code and executed, and can cause great damage to your data, whether they retrieve, delete confidential information or simply cause havoc among it!

To prevent SQL Injections you should:

  1. Validate all entered criteria via regular expressions for any mischievous keywords or text. Furthermore, apply HTML Encoding to any inputted text. Fortunately, version 1.1 of the .NET framework, offers superior validation, whereby if any user enters certain un-encoded HTML syntax or characters, .NET will raise an error. Read Request Validation - Preventing Script Attacks for more info.
  2. Use parameterized Stored Procedures (Sprocs) for your queries
  3. Create custom error pages so no one could inadvertently retrieve any data or server information from non-custom error pages.

Some added security measures when working with ADO.NET are:

  1. If caching data, store critical info server-side via session state or with the Cache object. I discussed this in light of a real-world example in my article Drilldown Datagrid Searching with ASP.NET, and read more about the various method for storing state.
  2. SQL server access should be performed through Windows Integrated Security, not "mixed mode," and never leave the default "sa" username and blank password as is, set a good username and password instead, which lead us to number 3.
  3. If possible create a trusted connection to SQL with the Integrated Security set to SSPI (Security Support Provider Interface), as this eliminates the need in storing any user id's and passwords.
    "Data Source=myDS; Integrated Security=SSPI; Enlist=false; Initial Catalog=myCtlg" 

    However, you may encounter - Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON,' where remedying this is to have your Windows Account be a Domain Account and share the same or trusted domains with IIS and SQL Server.
  4. Encrypt your connection strings in your web.config file, or other critical data elsewhere, and then later decrypt them, via the CryptoStream class in your page code, when you need to use them. Also dependent on the size of your data, whether large or small will determine Symmetric or Asymmetric Encryption.
  5. Finally, never hard-code anything, like any of the aforementioned, in your client-side pages.

Code Security

This security measure deals with setting permissions on projects, files, code and resources from anything unauthenticated. The CodeAccessPermission class comes in to play in allowing administrators the power to delegate certain types of access to various resources, thus ensuring authorized access only. It works alongside the trust element key within the web.config file in setting code access security (Full is the default):

<trust level="Full | High | Medium | Low | Minimal" originUrl="url"/>

Read Secure Coding Guidelines for the .NET Framework and Secure Coding Guidelines for more info .

Furthermore, as this also applies to all aspects in this article, if you really, really need the utmost security for very critical data, you do have a couple of nice options:

  1. Retrieve sensitive information and settings using serialization , that converts data to bytes for any type of transmission, that later gets deserialized on the other end.
  2. Directly reference an object's (dll/assembly) metadata (binary info about your dll) and other information or invoke methods contained within it during run time via Reflection using the System.Reflection namespace

Look at ASP.NET Security for more info and if you got the time read Microsoft's 608 page - Building Secure ASP .NET Applications treatise. Furthermore, peruse ASP.NET Architecture as well.

Now that we've dealt with security as an good overview, we now can move on to the actual components involved in making our application's architecture robust and high-performance. We'll first begin looking at some best practices that will determine general application health, before we discuss the best methods with each Tier.


General .NET Best Practices

The best practices to be discussed stem from real-world .NET application use, and have proven themselves very viable and sound in producing very scalable, high-performance applications. Since I'll be dealing with .NET programming a la hand coding and web forms, those interested in strict Visual Basic.NET optimizations should see - Performance Optimization in Visual Basic .NET for more info. Nevertheless, the best practices discussed here, generally apply to VB.NET as well. Moreover, all the tips offered here are general application page optimizations.

  • Right at the top of your .aspx page's @ Page directive, it is always important to disable any features you won't need or use. For example, set EnableSessionState to false on any pages not requiring use of session state, as well as Debug, Trace and EnableViewState. For strongly-typed error-free compilation, Strict and Explicit should be set to true to enforce early binding and variable declaration. Moreover, always set the page's Buffer to true for nice performance boosts, and application-wide within the web.config file's system.web nodes as well - <pages buffer="true"/> .
    <%@ Page Language="C#" Debug="false" Strict="true" Explicit="true"
        Trace="false" EnableSessionState="false" EnableViewState="false"
        Buffer="true" %>

Note, all of the above attributes are applicable to an .ascx user-control's @ Control directive, except for Buffer, Trace and EnableSessionState.

  • On Page_Load set Response.BufferOutput to true and Response.Flush at some later key point in your code.
    void Page_Load(Object sender, EventArgs e) { 
    
        Response.BufferOutput = true; 
    
        //...... 
    Response.Flush(); }
  • Utilize Page caching by incorporating the @ OutputCache directive to speed up page display by storing this page is memory. You start by specifying, in seconds, the duration for the cache to remain in memory, your particular request scenario and its location. Other customizable request attribute settings include VaryByCustom, VaryByHeader, VaryByParam and VaryByControl , and for the Location attribute (not supported in User Controls or .ascx files) you're allowed - "Any | Client | Downstream | Server | None."
    <%@ OutputCache Duration="7200" VaryByParam="value" Location="Any" Shared="True" %>
    Output caching could also be enabled with the HttpCachePolicy Class. Not only that, but the OutputCache directive include-syntax also fully applies to Fragment Caching or caching server user controls (.ascx) files separately as well, and works along the exact same lines. However, one distinct advantage this has over standard Page output caching, is that the user control file supports the Shared attribute setting, whereas the .NET Web Forms page (.aspx) does not.

    Therefore, by setting your server user control's Shared attribute to true, you in effect allow this control to be shared among all your pages, as opposed to creating separate cached versions of it. As you can probably guess, you'll end up with more available memory and even better performance!

    Now that's not all, caching your code-behind's source file is very different from what we've seen. To cache your code-behind control you'd declaratively implement the duration attribute in your source file's metadata like so:

    [C#]
    [PartialCaching(7200)] 
    
    public class myClass : UserControl { 
    
       //Your code here 
    }

    [VB]
    <PartialCaching(7200)> _ 
    
    Public myClass : Inherits UserControl 
    
       'Your code here 
    End Class
    Reference PartialCachingAttribute Classfor more info.
  • Aside from Page Caching, Data Caching is extremely important, and what you tend to do once you present data to the client. How have you developed the page in question in light of scalabilty and performance? If the user is returned 10,000 records that will assuredly require paging, will your application keep re-hitting the database each time or does it take advantage of .NET's data caching methods?

    I have written two articles that cover such topics in much greater detail .NET Data Caching and Drilldown Datagrid Searching with ASP.NET. I'll refer you to these two articles for all the information you'll need. As for more generalized data access, we'll be discussing this in greater detail in our Data Layer section, and reveal different scenarios and the best data retrieval method to be used for the best performance.

  • Check for Postback on Page_Load to avoid unnecessarily hitting the server when the page is posting back to itself:
    void Page_Load(Object sender, EventArgs e) { 
    
       if ( !IsPostBack ) { 
    
         //...rest of code here 
    } }
  • Don't unnecessarily use server-side web server controls for simple tasks where standard HTML controls would suffice.
  • Use .NET's StringBuilder class for all your string writing/creation and manipulation needs.
  • When it comes to your code and values try to minimize boxing and unboxing of values, as this can cause a performance hit.
  • Be very paranoid when it comes to any text you'll be accepting through forms, or query strings. Unless imperative and not practical although easier, utilize POST primarily instead of GET, for any data requests or passing among pages.
  • Use <%@ Page AspCompat="true" %> only if it's an absolute must where you require pre-.NET apartment-threaded VB6 COM object compatibility. It truth, it's best that you simply make the effort to fully migrate your application completely to .NET, as this is better in the long run.
  • Particular settings within your configuration file - web.config , prove useful in improving application performance. First of all, set all pages to buffer, as mentioned. Second, if your site is fully public, setting authentication to None mode further helps, as well as disabling site wide debugging. No public pages or applications should ever have debug mode enabled.
    <system.web="None" /> 
       <pages buffer="true" /> 
       <compilation debug="false" /> 
    </system.web> 
  • Take advantage of .NET's machine.config file processModel attributes. They have much to do with the robustness of the application as it's the server and how well it lives that will further epitomize your application. The old days of rebooting IIS for component registration or recycling and so forth are long gone with all of .NET's way cool abilities contained within this one file. Heck, this file even helps with automatic crash recovery! Read Configuring the ASP.NET Worker Process through the <machine.config> file for some good tips.
  • When compiling any classes in a code behind scheme or as a data object, outside of VS.NET, use /optimize thus assuring smaller, more efficient runtime code:
    (csc/vbc).exe /t:library /out:c:\inetpub\wwwroot\bin\sf.dll sf.(cs/vb) /optimize

Within VS.NET, you could enable optimizations through your Project Solutions properties, under Configuration Properties-->Optimizations.

Furthermore, you could utilize .NET's Native Image Generator (Ngen.exe) to cache your components or applications (.exe) within the GAC (Global Assembly Cache) for faster start-up times:

ngen myComponent.dll/exe
  • When possible and applicable, utilize Asynchronous Calls for added scalability to your application, anywhere from I/O actions to ASP.NET Web Forms.
  • Always, always remember to close, null and dispose of all your objects. Even though .NET's garbage collection scheme is magnificent, do it as well nevertheless.
  • For maximum readability, always properly indent your code.
  • And finally, add comments to your code. .NET comment tags are <%-- Code --%> , whereas dependent on the language you've chosen, VB uses an apostrophe ' to comment out code and C# uses slashes // . This practice ensures not forgetting certain logic or program flow when the time arises. We don't always remember why we coded what we did or how, do we?

Now that we've gotten some great performance enhancing tips for our standard .NET pages, we'll proceed to the N-Tier portions, and individually deal with each one.

Directory Structure

This should be a simple enough concept, separate all key components in their own folders: directories like: includes, images, bin, info, documents, stylesheets, scripts, etc. You get the idea, what a nightmare to have your entire application in one folder, yikes! Furthermore, for stronger security measures, never place your site's folder in your server's root folder.

Also working with a source code control software such a Microsoft's Visual Source Safe goes a long way in protecting code. Many editors available now from HomeSite to Dreamweaver integrate this. Furthermore, Source Safe promotes versioning as well, just like .NET.

Presentation / Business Layer

N-TIER

The presentation layer is just that the presentation of the application via a User Interface (UI). It encapsulates our HTML code and any controls or components that make up our entire application. In classic ASP this page would look like a unpleasant interspersion of code, or spaghetti code as it's known. Simply put, this means server, client and HTML code all mixed together without a care in the world.

This approach is messy, problem prone and doesn't follow .NET's Object-Oriented approach. Our .NET page in comparison will be cleanly laid out, and lightly coded. Why? Well, again because of .NET Platform model. How? With .NET's code-behind . Code-Behind is, as its name implies, the method where all your commonly used code is placed in another file, "behind" the page, in a dll or vb/cs source file, that get's inherited via your page's @ Page Directive. Alongside this benefit, there are performance advantages of writing code this way, since .NET automatically pre-compiles these controls!

The page's @ Page Directive inheriting code-behind is thus:

<%@ Page Inherits="MyNamespace.ClassName" Src="source file" %>

The source file would look something like this:

          

// Page inherits code-behind source file

using System;
using System.Diagnostics; //For Tracing, Performance Monitoring
using System.Drawing; // For Graphics, Datagrid Colors
using System.Web; // For HttpContext
using System.Web.UI; //For Literal Controls
using System.Web.UI.WebControls; // For Datagrid

namespace MyNamespace {

// All your variables, properties here

public class ClassName : Page { //Inherits Page Class

// All your code here }

}

Above we imported any necessary libraries we might need. Next we created our namespace, and within this our class, which is what our Page's @ Page Directive will inherit for code-behind to work. However, if you prefer for whatever reason, you could simply create a standalone class in your code-behind file, whereby the Page Directive's Inherits attribute is the class name alone, instead in our example where it is "MyNamespace.ClassName."

Also notice that our class inherits the Page class, because this is what constitutes our code-behind interaction with our caller page.

Alternatively, if you compile your source code into a dll,

(csc/vbc).exe /t:library /out:c:\inetpub\wwwroot\bin\sf.dll sf.(cs/vb) /optimize

you would then import it and instantiate it, like so:

          

// Import It

<%@ Import Namespace ="MyNamespace" %>

// Then Instantiate It

[C#]

ClassName variableName = new ClassName();

[VB]

Dim variableName As New ClassName()

Another method that implement's code-behind methodology are pagelets or .NET's new improved include files/ Web Server User Controls , or .ascx files . These files expand on the content (UI)/code separation by including commonly used code, in nicely stored controls, again just like include files in classic ASP, but certainly more powerful. How? Well, they for one they can assign and pass parameters, not to mention handle events!

Apart from the more conventional application of user controls, and normal code-behind modules, yet another instance is in creating reusable, Custom Server Controls . Basically these are new, custom built, super-duper controls, acquiring their functionality from inheriting its target control's base class, and expanding on it. Creating one works along the same lines as the above source code, except instead of a Page code-behind file inheriting the Page Class in that example, you'd inherit your particular control's base class. Take for example creating a custom datagrid control:

          

namespace MyNamespace {

// All your variables, properties here

public class ClassName : DataGrid { //Inherits DataGrid Class

// All your code here

}

}

After you compile your source file, you'd then register your assembly for use in your page like so:

          

<%@ Register TagPrefix="myControl" Namespace="myNamespace" Assembly="myDll Name" %>

Then implementing it is as easy as:

          

<myControl:myNamespace ID="MyControl ID" runat="server" property1 = "false" _

property2 = "Red" OnClick="Click Method Name" />

Notice how (providing your source code includes this) your custom control could accept and set, parameters and or properties, and handle events, as we've mentioned. Moreover, this could also apply to standard code-behind user controls as well! Custom control creation tends to get more advanced, and the coding skill requirements jump up a few notches. At any rate, a user controls' more common usage stems, more or less, in reusable site code, i.e. a page's header and footer for instance.

Below demonstrates a typical, albeit, bare bones .aspx page. It has a header and footer, whereby the respective code is separated between two web server controls or modules - header.ascx and footer.ascx. All your page would need to do is register them, and place them in the page accordingly:

          

// The control's first get registered at the top of the page


<%@ Register TagPrefix="Header" TagName="Top" Src="header.ascx" %>
<%@ Register TagPrefix="Footer" TagName="Bottom" Src="footer.ascx" %>

// Then get placed in your page where needed

<body>

<Header:Top ID="Header" runat="server" />

<Footer:Bottom ID="Footer" runat="server" />

</body>

Man, .NET rocks! Now that's a nice, clean presentation I think! But wait, that's not all, your web server controls themselves could also further inherit code-behind code! In this case the inherit/src members are implement this time via the control's @ Control directive.

// Header.ascx
          

<% @ Control inherits="ClassName" src="source file" %>

// Your code here

And your control's code-behind file is identical to your page's code behind file, except the control doesn't inherit the Page class, but rather the UserControl class, since it's a control that's calling this file.

          

// User Control's code-behind source file


using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class ClassName : UserControl {

// Your code here

}

Additionally, if you compile your code-behind file as a dll with a namespace that looks like this:

          

namespace ClassName {

public class myClass : UserControl {

// Your code here

}

}

Then there are now two ways for including it for use in your page. You could inherit it as follows:

          

// Inherit it

<%@ Control inherits="ClassName.myClass" src="source file" %>

Or you could import it and instantiate it as demonstrated earlier. Still yet another cool feature in .NET is the ability for the global.asax file to inherit code-behind as well!

<%@ Application Inherits="MyApp" %> 

For more info on the fine art of OOP Programming, it'll be worth your while in taking the time to thoroughly read - The Quick and Dirty .NET Guide to C#/VB Object-Oriented Programming.

As a final afterthought, since a majority of your initial code within your pages and source file will interact on your code's Page_Load method, you may find that aside from this common function, you may to need to process something even before this or something else as well. Well then have a look at these six additional Page methods, that are contiguous to your Page's event handlers:

  • Page_Init - for pre-Viewstate processing
  • Page_PreRender - for pre-Page rendering tasks.
  • Page_DataBind - for when the Page binds data
  • Page_Dispose - for when the Page get's disposed
  • Page_Error - for any errors on the Page
  • Page_Unload - for code to run on Page unloading or exit

So the above are simply just something to keep in mind. Now you should have a real good idea on creating a clean Presentation Layer with the use of web server controls.

Business Rules/Logic Layer:

This layer is quite simple, as it involves all specific and particular business rules and requirements to any given company. It enforces rules pertaining to data that is retrieved from a database, i.e. mathematical, monetary, formatting, etc.

These rules are stored as methods in this layer separately from other components, thus any changes effective to this app would take place only once. Again, these are functions or methods capable of anything required by your application, to effect all particular business practices. Therefore, in light of efficient N-Tier design, you really do want to avoid placing any business logic in your presentation layer, and here is where it would all go.

Data Access Layer

The data layer, on the other hand, is where we'll be covering various scenarios, and the best methods to use for the best performance and results. This layer encapsulates and compartmentalizes all our data access code within nice, clean components, that interact with our database. Also, keep in mind that the following tips apply to non-Tier standalone applications as well :-)

Incidentally, take the time and prep yourself with An Introduction to ADO.NET for a good look at ADO.NET, with v1.1 features as well, prior to diving into this section. Furthermore, although this section is named Data Access, it could nevertheless include XML as a viable data source. Therefore, read Reading, Storing and Transforming XML Data in .NET for a good look into this methodology.

Now to start, some quick tips off the top dealing with both aspects of data, SQL and ADO.NET. We'll divide these here solely to offer optimal means in each for prime data access. This involves both efficient database design and queries, and employing proficient ADO.NET techniques in retrieving already polished data.

SQL

  • Normalize your data for maximum efficiency and faster performance.

  • When creating new SQL tables always consider the best data types to employ with the type of column data you'll be storing.

  • Index your tables using SQL's Create Index command and or Query Analyzer's Index Tuning Wizard, assuring that your databases are finely tuned.

  • Use SQL Stored Procedures for all your data access, as SQL Server compiles them for all future uses. Furthermore, in SQL, straight and narrow is the best method in writing SQL Stored Procedures. Never overcomplicate your procedures with unnecessary or excessive temporary tables, server-side cursors , as these do create performance bottlenecks. You're better off creating subqueries off a base query and or with a join (avoiding left joins).

  • Never name your stored procedures with a "sp_" prefix, as SQL will interpret this as a system procedure.

  • Create SQL Views for added clarity and security.

  • Include SET NOCOUNT ON in all your stored procedures, as this diminishes network traffic by eliminating the need for SQL in always returning how many rows the procedure affected.

  • Use sp_executesql to execute any standard non-Sproc SQL statements in your code, gaining Stored Procedure-type benefits and reducing overhead:

    sp_executesql N'Select * from table' 

    and even within a Stored Procedure, instead of strictly EXECing any query strings:

    DECLARE @sqlQuery nvarchar (100)

    SET @sqlQuery = N'SELECT * FROM database.dbo.table'

    EXECUTE sp_executesql @sqlQuery



  • Finally, optimize SQL Server itself to maximize performance. Read SQL Server Settings Optimization Tips for more info.



    ADO.NET


  • Create all your database access routines as generic, versatile objects, rather than client-side repeated-code methods. All your UI should do is interact with these components, and not have to work out any details. The methods aforementioned in the Presentation Layer apply here as well in creating components and controls.

  • For all intents and purposes, the golden rule for data access is as follows: If you want to page data or provide your application with functionality use a Dataset as the preferred method of disconnected data, otherwise use a Datareader for all your data retrieval. For XML users this would translate to an XmlReader , and StreamReader for text files, both equivalent as that of a DataReader for their respective file types.

  • Use the correct managed data provider for your particular database, ex. System.Data.SqlClient for SQL Server , System.Data.OleDb for Access, System.Data.OracleClient for Oracle , etc.

  • Use Strongly-Typed Datasets over the standard, common un-Typed ones when possible, as this yields better performance. A generated typed Dataset is basically an early bound class inheriting the Dataset base class, as opposed to the typical late bound, non-inheritable Dataset. Thus, it allows for greater flexibility in dealing with your data. In turn, you'll be dealing with easier to read code, whereby you can access fields and tables by customizable names, instead of the conventional collection-based way. There's a good article here on DNJ that you should definitely read called Using Typed DataSets . Here you'll find all you need to know to get you going.

  • As mentioned briefly in the General .NET Best Practices, take full, and I mean full advantage of .NET Caching, as this will significantly boost performance and greatly diminish any persistent database interaction. However, and an important however is, if you decide on caching your data from within your data object, then conventional caching methods won't apply. Within the confines of components, and its interaction with the caller page, these requests happen via an HTTP request. Therefore, caching within your component can only be implemented by using the HttpContext.Cache Class property, part of .NET's Page class.

  • Use parameterized Stored Procedures along side .NET's Command Class Prepare() method, that caches your query for all future SQL Server uses.

    objCommand.Prepare()

  • Make chunky calls to your database rather than smaller, chatty calls. It's better to group all similar, associated calls in one SQL Server access. In other words, use one solid connection to retrieve as much as you can, as opposed to multiple ones.

  • Avoid using Universal Data Link ( UDL ) files for OleDb connections as these can cause potential performance hits. .NET's SQLClient managed data provider does not support this, as prior versions of SQL Server did.

  • Take advantage of connection pooling (whereby all your connection strings are identical) by storing all your connection strings in your web.config file. Additionally, if your not enlisting any transactional procedures, include enlist=false ; to your database's connection string for added performance.

    Example:

    <configuration>

    <appSettings>

    <add key="myDatabase" value="User ID=id; Password=pw; Data Source=datasrc; _
    Initial Catalog=dbCat; Enlist=false;"
    />

    </appSettings>

    <configuration>

and call it from your page, code-behind source file or component like so:

            

[C#]

ConfigurationSettings.AppSettings["myDatabase"].ToString();

[VB]

ConfigurationSettings.AppSettings("myDatabase").ToString()

  • Finally, remember to close, clear and dispose of all your data objects no matter what. If you would like to further confirm that your database connection is indeed closed, you would write:

    if (dbConnection.State != ConnectionState.Closed) { dbConnection.Close(); }

Common ADO.NET Scenarios

  1. You want to retrieve one single value or item:

    Use the command class's ExecuteScalar method.

    object dbValue = objCommand.ExecuteScalar();

    Remember, this method always returns an object that you have to convert/cast to your specific type.

  2. You need to retrieve just a single row of data instead:

    Use the ExecuteReader's SingleRow Command Behavior

  3.               

    objDataReader = objCommand.ExecuteReader(CommandBehavior.SingleRow);



  4. You want to retrieve multiple database rows and automatically close your connection:

    Use a data reader.

    objDataReader = objCommand.ExecuteReader(CommandBehavior.CloseConnection);


    Not fast enough, then read all data sequentially as a data stream via ExecuteReader's SequentialAccess Command Behavior. Note that although obvious, I should point out all fields are to be read and access in sequential order starting from 0, dependent on your SQL query columns order.


    objDataReader = objCommand.ExecuteReader(CommandBehavior.SequentialAccess); 


    Still not enough? Read all fields by index position or strongly-typed accessor method, instead of field name


    string value = objDataReader(0);

    or try

    string value = objDataReader.GetString(0);



    *The GetString is one of the Datareaders type specific members to read columns thus reducing any runtime conversions.

    And get your results with your preferred method of datareader field reads:


    while (objDataReader.Read() == true)
    {

    Response.Write (objDataReader(0));

    }



  5. You'd like to open a database connection, read your data, then close it all pretty quickly without too much code

    This can be accomplished only in C#, with the using statement.

    using (SqlConnection string) {


    // Do database work


    } // Now connection is automatically closed



  6. Best method to retrieve values from a Stored Procedure, instead of looping through rows with a datareader:

    objCommand.ExecuteNonQuery();


  7. Want even better functionality when working with SQL Server? Then use Microsoft's new Data Access Application Block (DAAB) 2.0 . .NET introduces the SqlHelper class that dramatically cut's down development time by allowing you to execute commands against a SQL database, with Sprocs, all within a few lines of code (about 75% less code than you would typically need)!

    The example below demonstrates how incredibly easy it is to implement a Datareader to connect to and query a SQL database, whether using simple SQL syntax or a SQL Parameter, and all with one line of code!

    <%@ Import Namespace="System.Data" %> 
    <%@ Import Namespace="System.Data.SqlClient" %>
    <%@ Import Namespace="Microsoft.ApplicationBlocks.Data" %>

    <script language="C#" runat="server">


    void Page_Load (Object Source, EventArgs E) {

    string strConn = "server=(local);uid=sa;pwd=;database=northwind;";
    int categoryID = 1;


    //Using a SQL Query
    //Connection String, Command Type (Text), and SQL Query

    SqlDataReader objDataReader = SqlHelper.ExecuteReader_
    (strConn, CommandType.Text, "SELECT * FROM Products");



    //Using a Sproc
    //Connection String, Command Type (Stored Procedure), and Parameter
    SqlDataReader objDataReader = SqlHelper.ExecuteReader_
    (strConn, "getProductsByCategory", categoryID);


    while (objDataReader.Read() == true) {

    Response.Write (objDataReader[1].ToString() + "<BR>");

    }


    //Close and clear our object
    objDataReader.Close();
    objDataReader = null;

    }

    </script>



    That's amazing, considering this would usually be accomplished with roughly more or less 10 lines of code!

    The SQLHelper class used here provides the same amazing robustness for the Dataset. Not only that, but you're allowed transactional and Dataset database updating, as well as exception management!

    Now to implement this class into your project, you can do this one of two ways. One, as a private assembly by simply xcopying the Microsoft.ApplicationBlocks.Data.dll into your project's bin folder, or two, as a Shared Assembly whereby you install the dll into the Global Assembly Cache using .NET's gacutil.exe command line utility while noting that it has to be assigned a Strong Name. This can be accommodated using the Assembly Linker (Al.exe) utility program. Finally, within Visual Studio.NET, it's all a matter of simply referencing the DLL, by importing into your project.

    This sure is a cool new class, huh? I think so too. Download the Data Access Application Block for .NET v2 here.

So there you have most ADO.NET data access scenarios that you'll run into while creating your application. Pretty sure you've got enough now to get you moving.

Now that we've gotten our Tiers taken care of, we'll discuss methods that'll ensure us from having our application blow up in our faces - Error Trapping and Handling.

Error Trapping & Handling

Error handling is an essential consideration in all applications. You always want to make sure users aren't scared half to death with some unintelligible error message. Furthermore, you never, ever want any server-side errors ever shown in any way to the client, ever!

Not only that, but you'd want to catch any errors that may in effect break your application. Usually employing typical if-then conditionals are the best way to go in dealing with standard errors and controlling program flow. Still, at times prior to critical code execution, you may need further protection, and better overall error handling. However, overusing try/catch exceptions can decrease system performance!

.NET offers its try/catch error handling , where you'd first issue "try" to run the following code, capture any errors that may occur, and display the exception message, then take any appropriate steps to remedy it. Moreover, this error code block further attaches a finally to itself for any final code to execute:

          

try {

myDataGrid.Databind()

} catch (Exception e) {

Response.Write ("The following error occurred :" + e.Message);

} finally {

myDataGrid.CurrentPageIndex = 0

}

Of course, using finally is not mandatory, and doesn't require it being included. For more info read - Handling and Throwing Exceptions and Best Practices for Handling Exceptions.

Further VB error objects available is the On Error Statement, capable of resuming next and going to a preset error handling label via Goto.

Alternatively to assigning custom error pages through IIS's Custom Errors tab, another such method involves our famous web.config file. Invoking the try/catch error blocks do well for code errors, but server errors? Nope, not these. Here we'll use web.config's custom errors nodes :

          

<system.web>

<customErrors mode="On" defaultRedirect="errorpage.aspx">

<error statusCode="403" redirect="AccessIsNotAllowed.aspx"/>
<error statusCode="404" redirect="PageNotFound.aspx"/>
<error statusCode="500" redirect="InternalServerError.aspx"/>

</customErrors>

</system.web>

Now all errors are redirected to more friendly error pages, and if you prefer, why not pull in additional error information, and e-mail yourself or the appropriate party when the error occurs.

Don't forget that you may also implement global error handling not dealt with our try/catch code blocks, via your global.asax file's Application_Error method using .NET's System Error codes:

          

protected void Application_Error (Object sender, EventArgs e) {

Server.Transfer ("error.aspx?error="+Server.GetLastError().Message);

}

Now error handling in .NET, can and should at times be given over to Stored Procedures via the two good methods found in SQL:

  1. @@ERROR :

    DECLARE @RetValue int

    UPDATE database
    SET database.dbfield = 'Jimmy'
    WHERE dbfield = 'Dimitrios'

    IF @@ERROR <> 0

    BEGIN

    PRINT 'An error occurred'

    SET @RetValue = @@ERROR

    END

    ELSE

    BEGIN

    PRINT 'All OK'

    SET @RetValue = '0'

    END

    RETURN @RetValue



    With the @@Error function you declare a variable for the error, return this value at the end and read this client side or print the error through SQL itself. Note an error return of zero (0) indicates no errors at all.

  2. RAISERROR:

    Hard-coded error messages:

    RAISERROR ('Error Occurred in : %s', 16, 1)

    Or utilizing the sp_addmessage system stored procedure to produce error messages using the msg_id, as long as the msg_id is over 50000.

    RAISERROR (50001, 16, 1, @columnId)

Debugging

Debugging is the art of program flow error handling, where you track down errors that has prevented your code from fully executing. .NET has much improved the classic ASP way of Response.Writing to find and trap program errors and flow. To employ debugging you could do this:

  1. Application wide in your web.config file:

    <system.web>

    <compilation debug="true"/>

    </system.web>


  2. Or locally and easier is by setting Debug to true in your page's @ Page Directive and also your user-control's @ Control Directive

Tracing

Tracing in .NET is another means of debugging, but allows you to insert custom statements added to your page's output, whereby you can "trace" the flow of your code and determine the order of things at run time. Tracing, contrary to debug mode, presents you with a lot of information about your page. It further can help much in ascertaining any performance issues concerning your code. In any event, like debugging, tracing could be implement the same two ways:

  1. Application wide via the web.config file:

    <system.web>

    <trace enabled="true"/>

    </system.web>


  2. Or locally within each page's @ Page Directive:


    <%@ Page Trace="true" TraceMode="SortByTime | SortByCategory" %>


    And within your code you would trace by writing:

    Trace.Write("Tracing has started")

    Trace.Warn("Examine more closely here")

    Trace.Write("Tracing has ended")


    Trace. Write produces standard output, whereas using Trace.Warn would output your text in red for added notice. And bear in mind that the best place to Trace is usually before and after any major code sections, i.e. Datagrid binding, editing, etc.

With all this error handling now under our belt, what happens now when an error does occur? How do we fix it? Well, next we'll look at some common, though not basic, .NET system errors.

Common .NET Errors

  • CS0019: Operator '&' cannot be applied to operands of type 'type' and 'type'

    This happens when you are trying to use the wrong operator for the specific operation.

  • CS0029: Cannot implicitly convert type 'object' to 'string'

    This error occurs when you are typically trying to present an object as a string. The solution here is to append ".ToString()," that now represents the object as a string.

  • CS0103: The name 'whatever' does not exist in the class or namespace / CS0246: The type or namespace name 'whatever' could not be found (are you missing a using directive or an assembly reference?)

    This will usually occur when you have not declared a variable globally and or it's missing altogether. CS0246 error also occurs when you are improperly declaring a object or variable, as well as it not existing in your code.

  • CS0117: 'object' does not contain a definition for 'Length'

    Again this has to do with improperly trying to convert a value. To remedy this properly cast or box the value in question.

  • CS0118: 'System.Configuration.ConfigurationSettings.AppSettings' denotes a 'property' where a 'method' was expected

    This error occurs when your AppSettings key is accessed with parentheses in VB, instead of brackets in C# or vice-versa.

  • CS0119: 'whatever' denotes a 'class' which is not valid in the given context / Object reference not set to an instance of an object

    One cause of this error is to improperly call an object without the "new" keyword in C# and "As New" in VB

  • CS0161: 'method name': not all code paths return a value

    This will happen when you are trying to make a function method behave like a subroutine or vice-versa. Use the proper method keyword to remedy this. Void is for methods that do not return a value, although you could response write the output. Whereas, applying a keyword value like string, int, works alongside a return value at the end of the method.

  • CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement

    This error is produced by a number of sources.

    1. If you call an object that requires () after the command, you'll get this error. Ex. database.Open() not database.Open
    2. Using an assignment operator as opposes to an equality operator


  • CS1001: Identifier expected / BC30183: Keyword is not valid as an identifier.

    Both these similar errors occur when you forget to identify a variable without a keyword, or you were inadvertently forcing a keyword to behave as a variable or type.

  • BC30451: Name 'whatever' is not declared.

    This happens when you are referencing a web form control or variable that either doesn't exist or is named different. Also by chance the control in question may be missing the mandatory runat="server" option.

  • BC30512: Option Strict On disallows implicit conversions from 'type' to 'type'.

    Improper type conversions produce this error. Convert the value or method to the proper cast to fix this.

  • BC30554/BC30560: 'object' is ambiguous.

    This error occurs when you have more than one similarly named dll in your bin folder when compiling or it matched your control inherits call. Furthermore, more than one dll root namespace or class within are named the same. Your page or control are trying to access one source file where a source file and dll may simultaneously exist.

  • BC30574: Option Strict On disallows late binding

    This can happen from any number of reasons in your code. Some common ones are:

    1. Not setting the object's proper data type
    2. An expression that binds data was incorrectly parsed against the object at runtime In Datagrids, for instance, this occurs when omitting the DataBinder.Eval method on a data field
  • BC30684: 'name' is a type and cannot be used as an expression

    This can happen usually when you forget to use the new keyword when instantiating an object or invoking a constructor.

Phew, hope this all helps in fixing those pesky errors you may run into when coding. Don't think for a minute that they're all here. Yeah, right, take a look at a complete list of Compiler Errors CS0001 Through CS9999. Here I simply showed a number of the more common ones you'll probably run into, with some quick ways in figuring them out and remedying them.

Performance Testing

I really won't dwell too much on this topic, as whole books are available on this topics alone! Performance testing takes time and patience to fully realize before and after results. To monitor your site's performance, use the Admin Tools' performance monitors and take the time to add the appropriate counters to the system monitor and take it from there.

Not only that, but .NET gives you ability to programmatically do the same things, alongside accessing system logs and system processes with its System.Diagnostics namespace. Read Displaying Performance Monitor Information through an ASP.NET Web Page for more info.

At any rate, read the book in the above link, and check out the article. Subsequently, Microsoft also offers a software tool that pushes your app to its limits, its WAS Tool. This tool and other useful information can be found here - Performance Optimizing Tools.

Conclusion

Well you have alot to think about and take into consideration regarding the creation of a finely-tuned application machine, both scalable and secure, not to mention lightning fast. At least it'll give you pride in the finished result, when you present a robust, high-performance application, with little or no down time. In the world of Internet development and deployment, that speaks volumes!

Until Next Time. Happy .NETing </>

[Originally published on dotnetjunkies.com - 6/03]

".NET" 카테고리의 다른 글
  • Windows Workflow Foundation 규칙 엔진 소개 (0)2007/07/23
  • Introduction to Windows Communication Foundation (0)2007/06/15
  • High-Performance .NET Application Development &... (0)2007/04/29
  • 데이터 바인딩 어플리케이션 만들기 기초 (0)2007/01/11
  • 개체를 이용한 데이터 바인딩 어플리케이션 만들기 (0)2007/01/11
2007/04/29 11:52 2007/04/29 11:52
Posted by webdizen
Tags .NET, Application, Architecture, Development, High-Performance
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/2866

Leave your greetings.

[로그인][오픈아이디란?]

«Prev  1  Next»

RSS HanRSS
Blog Image
webdizen
이곳은 컴퓨터에 대해 연구하고, 공유하고, 소통하기 위한 연구실입니다. 개인적으로는 OLAP, Data Mining, Semantic Web, Data Modeling에 대해서 연구하고 있습니다.

Categories

전체 (3009)
Webdizen (141)
Life (6)
Diary (16)
Blog (9)
IDEA (2)
Travel (10)
Book (16)
Photo (7)
Movie (8)
Music (14)
Leisure Sports (10)
Funny (6)
Hardware (121)
Software (120)
Windows (5)
Unix & Linux (120)
Installation (5)
Kernel (10)
System (34)
Develop (22)
X-Window (0)
Applicaton (31)
Security (4)
Framework (2)
Hadoop (2)
Programming (804)
Algorithm & Data Structure (1)
Assembly (38)
UNIX/Linux C (95)
C++ (128)
STL (4)
Java (38)
Win32 API (92)
ATL/COM (44)
MFC (151)
.NET (26)
WCF/WPF (4)
C# (28)
Network Programming (17)
Database Programming (12)
OpenGL / DirectX (13)
Multimedia Programming (0)
Game Programming (21)
Parallel Distributed Progra... (0)
Reverse Engineering (0)
Debugging (9)
Python (1)
Ruby (1)
Ruby on Rails (1)
QT (4)
GTK (0)
JSP (0)
PHP (6)
ASP.NET (6)
ASP (2)
Development (28)
Useful Library (2)
Data Modeling (0)
Database (105)
Oracle (4)
MSSQL (41)
MySQL (2)
Data Warehouse (2)
Data Mining (4)
Network (66)
Web (79)
DHTML (4)
XHTML (1)
Javascript (1)
CSS (1)
AJAX (9)
XML (11)
Flex (1)
Silverlight (3)
Security (91)
DoS (1)
Kernel (10)
Scanning (3)
Sniffing (0)
Spoofing (4)
Overflow (28)
Web (11)
Shell (10)
Format String (14)
Window (2)
Embedded (70)
Multimedia (27)
Mobile (14)
Graphic (24)
Management (633)
Knowledge (581)
Hadoop (0)

Notice

  • 메타 블로그 사이트에 등록
  • 새해 맞이 블로그의 변화
  • 블로그 명칭 변경
  • 도메인(www.webdizen.net) 구...
  • TEXTCUBE 1.6.1로 업그레이드...

Tags

  • TaskBar
  • putty
  • 패킷 캡처
  • JPEG
  • SHOW
  • dBASE
  • 보드카 알렉산더
  • 시스템 제어
  • 태양에너지 가방
  • Windows Communication Foundation
  • 메인 프레임 윈도우
  • 유닉스
  • 스냅샷 격리
  • 암호화
  • 야후
  • 20대
  • WebOS
  • processor
  • 생성자
  • 볼링

Recent Articles

  • 트위터(Twitter)의 시작!.
  • 청년 리더의 조건.
  • 애플의 타블렛 PC - 아이패드....
  • 미래의 인터페이스 - 육감 기....
  • 기초발성법 동영상 강좌.

Recent Comments

  • 학교 과제물중 쓰레드에 대하....
    장진혁 03/17
  • 관리자만 볼 수 있는 댓글입....
    비밀방문자 03/12
  • 상대방의 이야기를 열심히 경....
    DoNuts 03/03
  • Lots of students know techn....
    Bobbi35Shannon 02/25
  • 좋은글 잘 보고 갑니다..
    Und_hacker 01/08

Recent Trackbacks

  • printf,scanf를 이용한 형식....
    yundream의 프로그래밍 이야기 03/10
  • 파일 열기/저장하기 CFileDialog.
    은마군의 나태블록 2009
  • World IT Show 2008.
    상우 :: Oranzie's BLOG 2008
  • cvs서버 설치하기.
    3인3색 2008
  • 속속 공개되는 Google Chart....
    PHP와 Web 2.0 2007

Archive

  • 2010/02 (1)
  • 2010/01 (6)
  • 2009/12 (5)
  • 2009/09 (3)
  • 2009/08 (1)

Calendar

«   2010/03   »
일 월 화 수 목 금 토
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

Bookmarks

    • Administration
      • IIS.NET
      • NTFAQ
      • OS의 모든 것
      • 리눅스포털
    • Database
      • SQL Server Central
      • SQL Team
    • Development
      • .NET Heaven
      • ASP Alliance
      • ASP.NET 2.0
      • Bullog.net
      • C# Corner
      • C++ (C PlusPlus.com)
      • C++ Reference
      • CodeGuru
      • CodePlex
      • DebugLab
      • Dev Articles
      • Devpia
      • DotNet Junkies
      • DotNet Zone
      • Driver Online
      • GOSU.NET
      • HOONS 닷넷
      • Joinc 팀블로그
      • KOSR
      • MSDN Home Page
      • OSR Online
      • Sky.ph - 개발자 커뮤니...
      • TAEYO.NET
      • The Code Project
      • WindowsClient.net
      • 김상욱의 개발자 Side
      • 조인시 위키
    • Human Networks
      • belief21c's e-space
      • I think I can
      • Invisible Rover's Blog :D
      • Rodman®
      • ■ Feel So Good~! ■
      • 까만 나비
      • 나를 가꾸는 시간.
      • 나만의 즐거움~~!
      • 단녕
      • 상우 :: Oranzie's BLOG
    • Information Technology
      • Microsoft TechNet
      • 지디넷코리아 - 글로벌...
    • Security
      • FoundStone
      • milw0rm
      • NewOrder
      • OpenRCE
      • Phrack.org
      • Reverse Engineering b1...
      • Reverse Engineering Team
      • RootKit
      • SecurityFocus
      • SecurityXploded by Nag...
      • Wow Hacker
      • Zone-H
Textcube
Louice Studio Inc.
Powered by Textcube. Original designed by Tistory.