Programming/.NET

 1. 회원관리공급자

 

ASP.NET에서 회원(사용자)관리를 위한 공급자입니다.

 

(1) SqlMembershipProvider

 

회원관리시스템을 연결하는 공급자입니다. C:\Windows\Microsoft.NET\Framework\v4.0.xxxxx\Config 안에 machine.config의 내용을 보면 기본 설정내용을 확인할 수 있습니다.

 

<membership>
    <providers>
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="LocalSqlServer" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="10" passwordStrengthRegularExpression=""/>
    </providers>
</membership>

 

IIS내의 모든 웹애플리케이션에 적용하려면 machine.config에 설정을 변경해야 하고 개별적으로 적용하려면 해당 웹애플리케이션의 web.config에 재정의해야 합니다. 다음부터 언급할 거의 모든 공급자가 마찬가지입니다. 참고로 connectionStringName 속성에 보면 LocalSqlServer 라고 되어 있는데 이 연결설정은

 

<connectionStrings>
    <add name="LocalSqlServer" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient"/>
</connectionStrings> 

 

위와 같이 정의되어 있습니다. SQL Express에 mdf파일로 연결하는 것이 기본임을 알 수 있는데 이 공급자를 원격지의 SQL Server에 연결하려면 connectionStringName 속성을 바꿔야 합니다.

 

이후에 설명할 대부분의 공급자도 마찬가지지만 특정 공급자는 해당 공급자의 동작방식을 변경하는 것 또한 가능합니다. 예를 들어 SqlMembershipProvider의 경우 machine.config 의 내용중 minRequiredPasswordLength="7"이라는 부분이 있는데 이는 회원가입이나 비밀번호변경시 최소 암호길이가 7자 이상은 되어야 함을 의미합니다. 만약 웹애플리케이션을 개발하고 있는 프로젝트의 자체회원관리방식에 따라 최소 암호길이가 5자이상만 되도 암호생성을 허락하고자 하는 경우 이 속성을 5의 값으로 변경하면 됩니다.

 

이미 설명한 바와 같이 machine.config는 IIS하의 모든 웹애플리케이션에 적용이 되는데 해당 하는 특정 웹애플리케이션에만 이 규칙이 적용되는 경우 해당 웹애플리케이션의 web.config에서 machine.config에 명시된 name속성을 다른것으로 지정해 공급자를 재정의해야 합니다.

 

<membership>
  <providers>
    <add name="MyAspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, 

System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 

connectionStringName="LocalSqlServer" enablePasswordRetrieval="false" enablePasswordReset="true" 

requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" 

passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="5" 

minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="10" 

passwordStrengthRegularExpression=""/>
  </providers>
</membership>

 

아니면 <Clear /> 요소를 추가하여 기존공급자를 제거하는 방식을 사용하는 것도 가능합니다.

 

<membership>
  <providers>
    <clear/>
    <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, 

System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 

connectionStringName="LocalSqlServer" enablePasswordRetrieval="false" enablePasswordReset="true" 

requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" 

passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="5" 

minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="10" 

passwordStrengthRegularExpression=""/>
  </providers>
</membership>

 

이는 다른 공급자에도 공통으로 적용되는 부분이니 참고하시기 바랍니다.

 

(2) ActiveDirectoryMemberShipProvider

 

회원관리시스템을 액티브디렉토리 혹은 ADAM으로 연결하는 공급자입니다. 이 공급자를 활용하려면 우선 아래와 같은 형식으로 연결정보를 생성하고

 

<configuration>

    <connectionString>

        <add name="adm_connection" connectionString="--" />

    </connectionString>

</configuration>

 

공급자를 web.config에서 다음과 같이 ActiveDirectoryMemberShipProvider로 재정의해야 합니다. 왜냐하면 회원관리공급자 자체가 machine.config에 SqlMembershipProvider로 정의되어 있기 때문입니다.

 

<membership>
        <providers>
            <add name="AspNetActiveDirectoryMembershipProvider" type="System.Web.Security.AspNetActiveDirectoryMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="adm_connection" />
        </providers>
</membership>

 

 2. 역활공급자

 

특정 사용자에 대한 웹애플리케이션의 사용권한이나 접근관리를 위한 공급자입니다.

 

(1) SqlRoleProvider

 

역활 관리시스템과의 연결에 필요한 공급자입니다.

 

<roleManager>
        <providers>
            <add name="AspNetSqlRoleProvider" connectionStringName="LocalSqlServer" applicationName="/" type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
            <add name="AspNetWindowsTokenRoleProvider" applicationName="/" type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
        </providers>
</roleManager> 

 

machine.config에 선언된 내용입니다. 마찬가지로 connectionStringName이 LocalSqlServer로 설정되어 있어서 기본적으로 SQL Express를 사용하도록 합니다.

 

(2) WindowsTokenRoleProvider

 

윈도우 자체의 인증시스템과 연결하기 위한 공급자이며 roleManager의 두번째 add요소가 해당 공급자의 인스턴스입니다. 이 공급자는 다른 공급자들처럼 ASP.NET에서 직접 구성할 수 있는 항목이 많이 제한되어 있는데 윈도우 자체의 인증시스템을 사용하는 것이므로 시스템 자체에 적용된 설정사항을 대부분 사용하기 때문입니다.

 

(3) AuthorizationStoreRoleProvider

 

이 공급자는 흔히 AzMan(Authorization Manager Policy Store)이라고 하는 내부에 역활을 저장하기 위한 공급자입니다. 해당 공급자는 machine.config에 인스턴스로 구성되어 있지 않으므로 필요하다면 web.config에 직접 설정하도록 합니다. 이 공급자를 활용하기 위해서는 다음과 같이 XML(AzMan의 XML데이터 저장소)연결정보를 먼저 구성하고

 

<configuration>

    <connectionString>

        <add name="LocalPolicyStore" connectionString="msxml://App_Data\aaa.xml" />

    </connectionString>

</configuration>

 

공급자에 연결정보를 설정하면 됩니다.

 

 <system.web>
    <roleManager>
      <providers>
        <add name="AspNetAuthorizationStoreRoleProvider" type="System.Web.Security.AuthorizationStoreRoleProvider" connectionStringName="LocalPolicyStore" />
      </providers>
   </roleManager>
</system.web>

 

 3. 개인화 공급자

 

웹애플리케이션 사용자와 관련된 데이터를 다루는 개인화 시스템과의 연결을 위한 공급자입니다.

 

(1) SqlProfileProvider

 

<profile>
    <providers>
        <add name="AspNetSqlProfileProvider" connectionStringName="LocalSqlServer" applicationName="/" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
    </providers>
</profile>

 

해당 공급자를 실제로 활용하려면 필요한 항목을 직접 구성해야 합니다. 예를 들어 사용자의 이름과 주소정보를 다루고자 할때는 다음과 같이 선언할 수 있을 것입니다.

 

<properties>
    <add name="Name" />
    <add name="Address" />
</properties>

 

 4. 사이트 맵 공급자

 

사이트맵을 다루기 위한 공급자입니다.

 

(1) XmlSiteMapProvider

 

실제 사이트맵으로 활용하는 sitemap XML파일과의 연결을 담당하는 공급자로서 web.config에 siteMap요소로 선언되며 siteMapFile속성으로 sitemmap파일을 지정합니다.

 

<siteMap>
  <providers>
    <add name="AspNetXmlSiteMapProvider" type="System.Web.XmlSiteMapProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" siteMapFile="mysite.sitemap" />
  </providers>
</siteMap>

 

 5. 세션상태 공급자

 

세션상태를 다루기 위한 공급자 입니다. 보통 세션상태를 저장하는데 사용할 수 있는 모드로는 InProc, StateServer, SQLServer, Custom 네가지가 있으며 IIS안에서 직접 설정이 가능합니다.

 

 

(1) InProcSessionStateStore

 

ASP.NET의 기본설정인 InProc 모드를 사용하기 위한 것으로서 세션을 프로세스(aspnet_wp.exe, w3wp.exe)내부에 저장하는 방식입니다. 가장 성능이 우수하지만 만일 예기치 않은 상황으로 인해 프로세스가 죽거나 web.config와 같은 설정파일 수정으로 인해 프로세스가 재시작 되는 경우라면 저장된 세션도 모두 무효화되는 단점이 있습니다.

 

<system.web>
 <sessionState mode="InProc"></sessionState>
</system.web> 

 

(2) OutOfProcSessionStateStore

 

명칭에서도 알 수 있듯이 프로세스밖에 세션을 저장하는 방식입니다. 따라서 프로세스 재시작에 관계없이 세션상태를 유지할 수 있지만 성능은 InProc보다는 다소 떨어집니다.

 

<system.web>
 <sessionState mode="StateServer" stateConnectionString="tcpip=localhost:42424">
    </sessionState>
</system.web>

 

StateServer 모드를 사용하고자 하는 경우 stateConnectionString속성에 어느서버에 세션을 저장할지 정해야 합니다. 예제의 경우 localhost로 지정해 동일한 서버에 세션을 저장하지만 해당 서버내의 다른 프로세스에 세션을 저장합니다. 만일 다른 서버로 지정하고자 한다면 해당 서버의 도메인혹은 IP주소등을 설정하면 됩니다.

 

(3) SqlSesstionStateStore

 

세션을 SQL 서버에 저장하는 방식으로서 성능은 가장 떨어지지만 DB서버에 데이터를 저장하는 만큼 가장 유연하게 관리할 수 있는 세션상태기법입니다.

 

<system.web>
 <sessionState mode="SQLServer" sqlConnectionString="Data Source=localhost;Initial Catalog=aspnetdb;">
    </sessionState>
</system.web>

 

 6. 웹 이벤트 공급자

 

웹 애플리케이션의 상태를 감지할 수 있는 상태 모니터링과의 연결용 공급자 입니다. 상태 모니터링은 웹애플리케이션에서 발생할 수 있는 거의 모든 상태(웹 이벤트라고 하며 인증, 오류, 성능관련등이 포함됩니다)를 감지할 수 있게 하는 것으로서 해당 데이터를 공급자에서 지시한곳에 저장하게 되고 관리자는 이 데이터를 분석하여 웹애플리케이션의 상태를 파악할 수 있게 됩니다.

 

(1) EventLogWebEventProvider

 

웹 애플리케이션의 오류사항을 윈도우 이벤트에 기록하도록 합니다. 해당 공급자에 관한 상세내용은 web.config.comments 파일에서 확인할 수 있습니다.(healthMonitoring 요소 확인)

 

특히 rules요소에 보면 All Errors Default와 Failure Audits Default유형의 오류를 감지하고 있음을 확인할 수 있으며 provider 속성에 EventLogProvider지정에 따라 오류가 발생하면 이벤트 로그를 통해 해당 오류가 저장되는 것 또한 알 수 있습니다.

 

독특한 점은 하나이상의 공급자를 지정하여 로그가 여러 저장소로 저장되도록 할 수 있다는 것입니다. 예를 들어 이벤트 로그 뿐만 아니라 SQL 서버에서도 같은 내용이 저장되도록 하는 것이 가능합니다.

 

(2) SimpleMailWebEventProvider

 

오류가 발생하면 관리자에게 메일로 통보가 가도록 하는 것이 가능하며 이 공급자가 그 역활을 수행합니다.

 

<healthMonitoring heartbeatInterval="0" enabled="true">
  <bufferModes>
    <clear />
    <add name="mailNotification" maxBufferSize="100" maxFlushSize="20"

urgentFlushInterval="00:01:00" urgentFlushThreshold="1"

regularFlushInterval="00:01:00" maxBufferThreads="Infinite" />
  </bufferModes>
  <providers>
    <clear/>
    <add name="AspNetSimpleMailWebEventProvider"

type="System.Web.Management.SimpleMailWebEventProvider, System.Web,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"

from="web@aaa.com" to="admin@aaa.com" bodyHeader="Error!"

bodyFooter="---" subjectPrefix="---" buffer="true" buffferMode="mailNotification"

maxEventLength="4096" maxMessagePerNotification="1" />
  </providers>
  <rules>
    <clear />
    <add name="All Errors Default" eventName="All Errors" provider="EventLogProvider"

profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:01:00" custom="" />
    <add name="Failure Audits Default" eventName="Failure Audits" provider="EventLogProvider"

profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:01:00" custom="" />
    <add name="All Errors Defaul2t" eventName="All Errors" provider="AspNetSimpleMailWebEventProvider"

profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:01:00" custom="" />
    <add name="Failure Audits Default2" eventName="Failure Audits" provider="AspNetSimpleMailWebEventProvider"

profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:01:00" custom="" />
  </rules>
  <eventMappings>
    <clear />
    <add name="All Audits" type="System.Web.Management.WebAuditEvent,System.Web,Version=4.0.0.0,

Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" startEventCode="0" endEventCode="2147483647" />
    <add name="Failure Audits" type="System.Web.Management.WebFailureAuditEvent,System.Web,Version=4.0.0.0,Culture=neutral,

PublicKeyToken=b03f5f7f11d50a3a" startEventCode="0" endEventCode="2147483647" />
  </eventMappings>
</healthMonitoring>

 

AspNetSimpleMailWebEventProvider 이름의 공급자를 정의하고 from과 to속성에 원하는 메일 주소와 내용, 제목등을 설정합니다. 특히 buffer속성을 true로 하고 bufferMode를 지정했다는 점에 주목해 주시기 바랍니다. bufferMode에서 지정한 mailNotification은 bufferModes에 선언되어 있는데 이는 오류가 발생하면 그 즉시 보내는 것이 아니라 일정부분 쌓아뒀다가 한번에 보내기 위함입니다.

 

또 rules부분에 동일한 규칙이 2개씩 설정되어 있는데 하나는 이벤트 로그에 또 하나는 메일 공급자를 provider로 설정해서 같은 이벤트가 발생하면 이벤트로그에 기록함과 동시에 메일로도 발송되도록 하였습니다.

 

(3) TemplatedmailWebEventProvider

 

SimpleMailWebEventProvider와 거의 모든 부분이 동일하지만 추가적으로 template속성을 사용할 수 있습니다.

 

<add name="AspNetTemplatedMailWebEventProvider" type="System.Web.Management.TemplatedMailWebEventProvider, System.Web,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" template="/template.aspx" from="web@aaa.com" to="admin@aaa.com" bodyHeader="Error!" bodyFooter="---" subjectPrefix="---" buffer="true" buffferMode="mailNotification" maxEventLength="4096" maxMessagePerNotification="1" />

 

template는 일종의 메일 서식을 지정하는 것으로 이해하시면 됩니다.

 

(4) System.Web.Management.SqlWebEventProvider

 

이벤트 발생시 로그를 SQL 서버에 저장하도록 하기 위한 공급자입니다. SQL 서버를 저장소로 하는 다른 공급자와 마찬가지로 SQL 서버에 대한 연결정보를 생성하고

 

<connectionStrings>
 <add name="sqlprovider" connectionString="Data Source=localhost;Initial Catalog=aspnetdb;"/>
</connectionStrings>

 

공급자를 구성합니다.

 

<healthMonitoring heartbeatInterval="0" enabled="true">
  <providers>
    <clear/>
    <add name="AspNetSqlWebEventProvider" type="System.Web.Management.SqlWebEventProvider, System.Web,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="sqlprovider" buffer="true" bufferMode="SQL Analysis" />
  </providers>
</healthMonitoring>

 

참고로 SqlWebEventProvider 공급자도 BufferedWebEventProvider를 상속받기 때문에 이벤트는 즉시가 아닌 일정동안 쌓아뒀다가 일괄적으로 기록할 것입니다.

 

(5) TraceWebEventProvider

 

웹애플리케이션 상태및 기타 정보를 볼 수 있도록 추적하기 위한 공급자이며 해당 정보를 ASP.NET페이지에 전송합니다.

 

<healthMonitoring heartbeatInterval="0" enabled="true">
  <providers>
    <clear/>
    <add name="AspNetTraceWebEventProvider" type="System.Web.Management.TraceWebEventProvider, System.Web,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" maxEventLength="4096" maxMessagesPerNotification="1" />
  </providers>
  <rules>
    <clear />
    <add name="All Errors Default" eventName="All Errors" provider="EventLogProvider" profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:01:00" custom="" />
    <add name="Failure Audits Default" eventName="Failure Audits" provider="EventLogProvider" profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:01:00" custom="" />
  </rules>
</healthMonitoring>

 

rules에 정의된 오류를 감지하고 해당 정보를 페이지로 보낼 것입니다.

 

(6) IisTraceWebEventProvider

 

TraceWebEventProvider 공급자는 추적정보를 페이지에 보내지만 IisTraceWebEventProvider 공급자는 정보를 IIS에 전달합니다. 그외 다른점은 없습니다.

 

(7) WmiWebEventProvider

 

이 공급자는 상태 모니터링에서 발생한 이벤트를 WMI(Windows Management Instrumentation)시스템에 전달하도록 합니다. 이 공급자는 web.config.comments에 기본적으로 설정되어 있습니다.

 

<providers>
    <add name="WmiWebEventProvider" type="System.Web.Management.WmiWebEventProvider,System.Web,Version=4.0.0.0,

Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" />
</providers>

 

 7. 구성설정 공급자

 

이 공급자는 구성 설정 파일에 있는 요소를 암호화 하는데 사용되는 공급자입니다.

 

(1) DpapiProtectedConfigurationProvider

 

DpapiProtectedConfigurationProvider는 윈도우 데이터 암호화 API를 통해 각 컴퓨터별로 암호화 하고 복호화 할 수 있도록 합니다.

 

<configProtectedData defaultProvider="RsaProtectedConfigurationProvider">
    <providers>
        <add name="RsaProtectedConfigurationProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="NetFrameworkConfigurationKey" cspProviderName="" useMachineContainer="true" useOAEP="false"/>

        <add name="DataProtectionConfigurationProvider" type="System.Configuration.DpapiProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses CryptProtectData and CryptUnProtectData Windows APIs to encrypt and decrypt" useMachineProtection="true" keyEntropy=""/>
    </providers>
</configProtectedData>

 

machine.config에는 위와 같이 DpapiProtectedConfigurationProvider와 RsaProtectedConfigurationProvider가 정의된 것을 확인할 수 있습니다. 우선 useMachineProtection속성에 주목해 주세요. 이 속성을 true로 하면 서버하에 있는 모든 웹애플리케이션에 같은 암호화와 복호화방법을 적용하게 됩니다. 또한 keyEntropy속성에 특정 문자열 값을 설정하면 복호화를 할 수 없도록 하는 효과를 가져올 수 있습니다. 

 

machine.config에 정의된 구성설정 공급자는 기본적으로 RsaProtectedConfigurationProvider공급자를 사용하도록 합니다. 만약 DpapiProtectedConfigurationProvider를 사용하려면 defaultProvider 속성을 변경하거나 web.config에서 다시 재정의해야 합니다.

 

단, web.config에 재정의 할때는 configProtectedData 단락 전체를 system.web안에 정의하면 안됩니다.

 

(2) RsaProtectedConfigurationProvider

 

이 공급자는 3DES암호화 방법으로 암호화를 수행합니다. 특히 keyContainerName라는 속성은 암호화/복호화에 사용되는 키를 의미하며 useOAEP속성은 암호화/복호화때 OAEP(Optional Asymmetric Encryption and Padding)기능 사용여부를 지정하는 것입니다. 다만 이 기능은 윈도우 서버 2003부터 지원합니다.

 

 8. 웹 파트 공급자

 

웹 파트기능을 사용하면 사용자 별로 웹 구성환경을 저장하여 해당 사용자가 접근시 저장된 환경정보를 적용함으로서 각 사용자별로 다른 형태의 화면구성을 보여주도록 할 수 있습니다. 웹 파트 공급자는 이 구성정보를 어디에 저장할 것인가에 대한 공급자입니다.

 

(1) SqlPersonalizationProvider

 

해당 공급자는 C:\Windows\Microsoft.NET\Framework\v4.0.xxxxx\Config의 web.config안에 선언되어 있습니다.

 

<webParts>
    <personalization>
        <providers>
            <add connectionStringName="LocalSqlServer"
                name="AspNetSqlPersonalizationProvider" type="System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>

        <authorization>
            <deny users="*" verbs="enterSharedScope" />
            <allow users="*" verbs="modifyState" />
        </authorization>
    </personalization>

    <transformers>
        <add name="RowToFieldTransformer" type="System.Web.UI.WebControls.WebParts.RowToFieldTransformer" />
        <add name="RowToParametersTransformer" type="System.Web.UI.WebControls.WebParts.RowToParametersTransformer" />
    </transformers>
</webParts>

 

구성 내용을 보면 connectionStringName속성에 SQL Express를 사용하도록 되어 있는데 원격지 SQL서버로 웹 파트 정보를 저장하려면 이 속성을 통해 연결문자열을 변경하면 됩니다.

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

[ASP.NET] XSLT  (0) 2016.04.05
[ASP.NET] 공급자 모델 - 3  (0) 2016.03.30
[ASP.NET] 공급자 모델 - 2  (0) 2016.03.22
[ASP.NET] 공급자 모델 - 1  (0) 2016.03.17
[ASP.NET] Menu  (0) 2016.03.10
[ASP.NET] Calender  (0) 2016.03.07
0 0