ASP.NET MVC Routing

 

블로그나 카페등에서 사용되는 확장자 없는 URL을 자유롭게 설정해 주는 기능

Global.asax에서 routes.MapRoute() 메소드를 통해 매핑규칙을 추가하면

http://www.mnstime.com/microsoft/aspnet/mvc/routing 와 같은 URL이 가능하다는 것이다.

 

RoutingGlobal.asax에서 설정을 한다.

Global.asax의 소스를 보면 다음과 같다.

 

public class MvcApplication : System.Web.HttpApplication

    {

        public static void RegisterRoutes(RouteCollection routes)

        {

            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(

                "Default",                                              // Route name

                "{controller}/{action}/{id}",                           // URL with parameters

                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults

            );

        }

        protected void Application_Start()

        {

            RegisterRoutes(RouteTable.Routes);

        }

    }

 

프로젝트를 생성하면 Global.asax에 기본 routes.MapRoute() 이 설정되어 있다.

만약 URL /Home/Detail/10 로 요청이 들어오면 "{controller}/{action}/{id} 순으로

 

Controller

Home Controller

Action

Detail Method

Id

10 ( 5 Parameter )

이렇게 매핑이 된다.

 

이 매핑의 규칙은 Global.asax에서 routes.MapRoute() 통해 다양하게 설정할 수 있다.

URL 요청은 순서대로 다양하게 설정한 routes.MapRoute() 중에서 적용이 되는 제일 첫번째 설정으로 매핑이 된다.

 

Default Routing

MVC URL에 대한 Default Routing 다음과 같다.

 

Global.asax.cs

 

routes.MapRoute(

                "Default",                                              // Route name

                "{controller}/{action}/{id}",                           // URL with parameters

                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults

            );

 

다음은 URL에 대한 요청 설명이다.

http://localhost/ 라면 Paramter defaults로 인해 Home Controller Index Method를 호출한다.

http://localhost/Shop/List/ 라면 Shop Controller List Method가 호출된다.

http://localhost/Shop/List/1 라면 Shop Controller List Method 1값이 파라메터로 전달이 된다.

 

Customer Routing

Routing은 기본적으로 {controller}/{action}/{id} 형태로 구성되지만 다른 형태로 구성 할 수 있다.

 

Global.asax.cs

 

routes.MapRoute(

                "Plan",                                                     // Route name

                "Plan/{action}/{id}",                                       // URL with parameters

                new { controller = "Plan", action = "List", id = "" }    // Parameter defaults

            );

http://localhost/Plan/View/2

PlanMgt Controller View Method 2값이 파라메터로 전달이 되며 /Plan View.aspx를 호출한다.

그리고 List.aspx 뷰가 만들어져야 http://localhost/Plan/ 를 요청했을 경우 List.aspx가 호출이 된다.

 

Global.asax.cs

 

routes.MapRoute(

                "ShopProduct",                                                     // Route name

                "Shop/{controller}/{action}/{id}",                                       // URL with parameters

                new { controller = "Product", action = "Index", id = "" },    // Parameter defaults

                new { controller = "(Product)|(Product2)" }

            );

 

※ 중요

Route를 여러개 지정하여 사용할 경우 위에서부터 차례대로 해석하는데 Default Route이 최상단으로 올리는 경우 Default Route에서 URL을 해석하여 페이지 에러가 발생하게 된다.

Customer Route를 생성했을 경우에는 먼저 Customer Route를 넣어준 후 Default Route를 넣어주는게 좋은 방법이다.

 

 

URLController 찾기

http://localhost/Shop

기본으로 Product Controller Index Method를 호출하여 /Product Index.aspx를 호출한다.

 

http://localhost/Shop/Product2/

Product2 Controller Index Method를 호출하여 /Product Index.aspx를 호출한다.

 

http://localhost/Shop/Product3/

Product3 Controller가 존재하지 않아 오류가 발생한다.

 

 

URLParameter 전달하기

http://localhost/Shop/Product/Index/Hello

Controller Index Method Hello파라메터값을 전달하여 Index.aspx를 호출한다.

값의 전달을 위해 소스를 아래와 같이 수정하였다.

 

ProductController.cs

 

        public ActionResult Index(string id)

        {

            ViewData["ProductParam"] = id;

            return View();

        }

 

Index.aspx

 

<%=Html.Encode(ViewData["ProductParam"]) %>

  

간단하게 하나의 파라메터 값을 전달하였다.

 

 

응용해서 2개의 파라메터를 전달하려면 어떻게 해야 할까?

http://localhost:7002/Shop/Product/Index/Hello/Hi

 

Global.asax.cs

 

            routes.MapRoute(

                "ShopProduct",                                                     // Route name

                "Shop/{controller}/{action}/{id}/{id2}",                                       // URL with parameters

                new { controller = "Product", action = "Index", id = "", id2 = "" },    // Parameter defaults

                new { controller = "(Product)|(Product2)" }

            );

 

ProductController.cs

 

        public ActionResult Index(string id , string id2)

        {

            ViewData["ProductParam"] = id;

 ViewData["ProductParam2"] = id2;

            return View();

        }

 

Index.aspx

 

<%=Html.Encode(ViewData["ProductParam"]) %> / <%=Html.Encode(ViewData["ProductParam2"]) %>

 

 

 

Views Win Form 추가하기

지금까지는 그림에서 처럼 Views/ProductView 항목을 통해 Page를 추가했다.

 

지금은 새 항목을 통하여 Web Form을 추가하는 것을 해보겠다.

 

 

새 항목을 클릭 후 Web Form 선택하여 Detail.aspx라는 Web Form을 만들자.

다음으로 Product Controller Detail Action을 만들어 연결을 해보자

Product Controller.cs

 

        public ActionResult Detail()

        {

            return View();

        }

 

 http://localhost:7002/Shop/Product/Detail URL을 입력하면 다음과 같은 에러가 출력된다.

Detail.aspx ViewPage의 상속을 받지 않아서 생기는 문제이다.

  

Detail.aspx.cs의 코드를 수정하자.

Detail.aspx.cs

 

using System.Web.Mvc; // 추가

 

namespace MvcMyApplication.Views.Product

{

    public partial class Detail : ViewPage //System.Web.UI.Page 를 변경

    {

        protected void Page_Load(object sender, EventArgs e)

        {

 

        }

    }

}

 

'Web Platform' 카테고리의 다른 글

ASP.NET MVC TagBuilder  (0) 2009.06.29
ASP.NET MVC View  (0) 2009.06.29
ASP.NET MVC 개발 환경 만들기  (0) 2009.06.29
ASP.NET MVC(Model, View, Controller)란?  (0) 2009.06.29
날짜 관련 함수  (0) 2009.06.29

ASP.NET MVC Web Application 만들기

 

새로운 MVC 프로젝트를 만들기 위해서는 아래와 같은 환경이 준비되어야 한다.

1.      Microsoft Visual Studio2008

2.      .NET Framework 3.5 SP 1

3.      ASP.NET MVC 1.0

4.      IIS 7.0 (IIS 6.0 이상)

 

 

ASP.NET MVC 1.0http://www.asp.net/MVC/ 에서 다운 받을 수 있다.

버튼을 클릭하면 Web Platform Installer 2.0 Beta를 설치한다.

 

 

설치를 완료 하면 아래와 같은 화면이 나온다.

 

Web Platform -> Frameworks and Runtimes Customize를 선택하면

ASP.NET MVC 1.0 .NET Framework 3.5 SP1를 체크한 후 Install을 하면 설치가 된다.  

 

 

이제 환경이 준비 되었으니 새로운 MVC 프로젝트를 만들어보자.

 

 

Microsoft Visual Studio2008을 실행 한 후 새 프로젝트를 선택하면 아래와 같이 ASP.NET MVC Web Application이 생성된 것을 볼 수 있다.

 

 

 

MvcMyApplication 이름으로 새 프로젝트를 생성하자.

다음과 같은 화면이 나오는데 No, do not create a unit test project를 선택 -> OK

(Yest, create a unit test project를 하게 되면 단위테스트를 위한 프로젝트가 같이 생성이 된다.)

 

Ctrl + F5를 눌러 실행해보자.

 

이렇게 해서 하나의 MVC Application을 만들어보았다

 

 

'Web Platform' 카테고리의 다른 글

ASP.NET MVC View  (0) 2009.06.29
ASP.NET MVC Routing 기술  (0) 2009.06.29
ASP.NET MVC(Model, View, Controller)란?  (0) 2009.06.29
날짜 관련 함수  (0) 2009.06.29
JavaScript를 이용한 정규식 표현  (0) 2009.06.29

MVC란 객체지향언어인 Smalltalk에서 도입되었다.

 

MVC의 세부분의 구성은 다음과 같은 역활을 한다.

 

1. Model(Biz 로직

비즈니스를 처리한다. 데이터 부분의 클래스 및 논리적인 데이터 기반 구조를 표현

2. View(Biz의 프리젠테이션)

사용자가 보게 될 결과 화면을 담당한다.

3. Contoller(흐름제어)

Model View와의 통신을 담당한다.


MVC 어플리케이션을 만들기는 결정할 때

ASP.NET MVC framework 인지 혹은 ASP.NET Web Forms 모델 인지를 결정하는 것은 주의 깊게 고려해야 한다.

MVC framework ASP.NET Web Forms을 교체하지는 않는다.

결정하기 이전에 웹 어플리케이션에 주는 이점을 살펴야 한다

 

ASP.NET MVC 기반 웹 어플리케이션은 다음과 같은 이점을 제공한다.

* Model, View, Controller가 분리되어 있으므로 관리의 복잡성이 줄어든다.

* View State Server Based Control을 사용하지 않는다. 이것은 어플리케이션의 동작을 완전히 제어하려는 개발자들에게 이상적이다.

* 좀더 나은 Test-Driven Development의 지원

* 높은 수준의 제어가 필요한 개발자와 설계자들의 큰 팀을 지원하는 Web 어플리케이션에 적합

 

Web Forms 기반 웹 어플리케이션은 다음과 같은 이점을 제공한다.

* HTTP를 통해 상태를 저장하는 이벤트 모델을 제공한다. 서버컨트롤에서 지원하는 수만은 이벤트들을 지원한다.

* 상태정보를 쉽게 관리할 수 있는 View Status 또는 Server-based Forms를 제공한다.

* 많은 수의 컴포넌트를 빠르게 개발하려는 개발자 및 설계자들의 작은 팀에 적합.

* 일반적으로 컴포넌트가 긴밀하게 통합되어 있고 MVC 모델 보다 적은 코드가 필요하기 때문에 개발의 복잡도가 적다

 

MVC 어플리케이션에서는 더 이상 ViewState와 포스트백을 사용하지 않는다.

 

'Web Platform' 카테고리의 다른 글

ASP.NET MVC Routing 기술  (0) 2009.06.29
ASP.NET MVC 개발 환경 만들기  (0) 2009.06.29
날짜 관련 함수  (0) 2009.06.29
JavaScript를 이용한 정규식 표현  (0) 2009.06.29
location.href 와 location.replace의 차이  (0) 2009.06.29

/**
 * Copyright (c) 2000 by LG-EDS Systems Inc
 * All rights reserved.
 *
 * 날짜관련 자바스크립트 공통함수
 *
 * 분단위 이하(= 초)는 고려하지 않았습니다.
 * YYYYMMDDHHMI 형식의 String => 'Time'으로 칭함
 *
 * 주로 YYYYMMDD 까지만 쓰인다면 아래 함수들을
 * YYYYMMDD 형식의 String => 'Date'로 하여 적당히
 * 수정하시거나 아니면 함수를, 예를들어 isValidDate()처럼,
 * 추가하시기 바랍니다.
 *
 * @version 2.0, 2001/01/28
 * @author 박종진(JongJin Park), jongjpark@lgeds.lg.co.kr
 */


/**
 * 유효한(존재하는) 월(月)인지 체크
 */
function isValidMonth(mm) {
    var m = parseInt(mm,10);
    return (m >= 1 && m <= 12);
}

/**
 * 유효한(존재하는) 일(日)인지 체크
 */
function isValidDay(yyyy, mm, dd) {
    var m = parseInt(mm,10) - 1;
    var d = parseInt(dd,10);

    var end = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
    if ((yyyy % 4 == 0 && yyyy % 100 != 0) || yyyy % 400 == 0) {
        end[1] = 29;
    }

    return (d >= 1 && d <= end[m]);
}

/**
 * 유효한(존재하는) 시(時)인지 체크
 */
function isValidHour(hh) {
    var h = parseInt(hh,10);
    return (h >= 1 && h <= 24);
}

/**
 * 유효한(존재하는) 분(分)인지 체크
 */
function isValidMin(mi) {
    var m = parseInt(mi,10);
    return (m >= 1 && m <= 60);
}

/**
 * Time 형식인지 체크(느슨한 체크)
 */
function isValidTimeFormat(time) {
    return (!isNaN(time) && time.length == 12);
}

/**
 * 유효하는(존재하는) Time 인지 체크

 * ex) var time = form.time.value; //'200102310000'
 *     if (!isValidTime(time)) {
 *         alert("올바른 날짜가 아닙니다.");
 *     }
 */
function isValidTime(time) {
    var year  = time.substring(0,4);
    var month = time.substring(4,6);
    var day   = time.substring(6,8);
    var hour  = time.substring(8,10);
    var min   = time.substring(10,12);

    if (parseInt(year,10) >= 1900  && isValidMonth(month) &&
        isValidDay(year,month,day) && isValidHour(hour)   &&
        isValidMin(min)) {
        return true;
    }
    return false;
}

/**
 * Time 스트링을 자바스크립트 Date 객체로 변환
 * parameter time: Time 형식의 String
 */
function toTimeObject(time) { //parseTime(time)
    var year  = time.substr(0,4);
    var month = time.substr(4,2) - 1; // 1월=0,12월=11
    var day   = time.substr(6,2);
    var hour  = time.substr(8,2);
    var min   = time.substr(10,2);

    return new Date(year,month,day,hour,min);
}

/**
 * 자바스크립트 Date 객체를 Time 스트링으로 변환
 * parameter date: JavaScript Date Object
 */
function toTimeString(date) { //formatTime(date)
    var year  = date.getFullYear();
    var month = date.getMonth() + 1; // 1월=0,12월=11이므로 1 더함
    var day   = date.getDate();
    var hour  = date.getHours();
    var min   = date.getMinutes();

    if (("" + month).length == 1) { month = "0" + month; }
    if (("" + day).length   == 1) { day   = "0" + day;   }
    if (("" + hour).length  == 1) { hour  = "0" + hour;  }
    if (("" + min).length   == 1) { min   = "0" + min;   }

    return ("" + year + month + day + hour + min)
}

/**
 * Time이 현재시각 이후(미래)인지 체크
 */
function isFutureTime(time) {
    return (toTimeObject(time) > new Date());
}

/**
 * Time이 현재시각 이전(과거)인지 체크
 */
function isPastTime(time) {
    return (toTimeObject(time) < new Date());
}

/**
 * 주어진 Time 과 y년 m월 d일 h시 차이나는 Time을 리턴

 * ex) var time = form.time.value; //'20000101000'
 *     alert(shiftTime(time,0,0,-100,0));
 *     => 2000/01/01 00:00 으로부터 100일 전 Time
 */
function shiftTime(time,y,m,d,h) { //moveTime(time,y,m,d,h)
    var date = toTimeObject(time);

    date.setFullYear(date.getFullYear() + y); //y년을 더함
    date.setMonth(date.getMonth() + m);       //m월을 더함
    date.setDate(date.getDate() + d);         //d일을 더함
    date.setHours(date.getHours() + h);       //h시를 더함

    return toTimeString(date);
}

/**
 * 두 Time이 몇 개월 차이나는지 구함

 * time1이 time2보다 크면(미래면) minus(-)
 */
function getMonthInterval(time1,time2) { //measureMonthInterval(time1,time2)
    var date1 = toTimeObject(time1);
    var date2 = toTimeObject(time2);

    var years  = date2.getFullYear() - date1.getFullYear();
    var months = date2.getMonth() - date1.getMonth();
    var days   = date2.getDate() - date1.getDate();

    return (years * 12 + months + (days >= 0 ? 0 : -1) );
}

/**
 * 두 Time이 며칠 차이나는지 구함
 * time1이 time2보다 크면(미래면) minus(-)
 */
function getDayInterval(time1,time2) {
    var date1 = toTimeObject(time1);
    var date2 = toTimeObject(time2);
    var day   = 1000 * 3600 * 24; //24시간

    return parseInt((date2 - date1) / day, 10);
}

/**
 * 두 Time이 몇 시간 차이나는지 구함

 * time1이 time2보다 크면(미래면) minus(-)
 */
function getHourInterval(time1,time2) {
    var date1 = toTimeObject(time1);
    var date2 = toTimeObject(time2);
    var hour  = 1000 * 3600; //1시간

    return parseInt((date2 - date1) / hour, 10);
}

/**
 * 현재 시각을 Time 형식으로 리턴

 */
function getCurrentTime() {
    return toTimeString(new Date());
}

/**
 * 현재 시각과 y년 m월 d일 h시 차이나는 Time을 리턴
 */
function getRelativeTime(y,m,d,h) {
/*
    var date = new Date();

    date.setFullYear(date.getFullYear() + y); //y년을 더함
    date.setMonth(date.getMonth() + m);       //m월을 더함
    date.setDate(date.getDate() + d);         //d일을 더함
    date.setHours(date.getHours() + h);       //h시를 더함

    return toTimeString(date);
*/
    return shiftTime(getCurrentTime(),y,m,d,h);
}

/**
 * 현재 年을 YYYY형식으로 리턴
 */
function getYear() {
/*
    var now = new Date();
    return now.getFullYear();
*/
    return getCurrentTime().substr(0,4);
}

/**
 * 현재 月을 MM형식으로 리턴
 */
function getMonth() {
/*
    var now = new Date();

    var month = now.getMonth() + 1; // 1월=0,12월=11이므로 1 더함
    if (("" + month).length == 1) { month = "0" + month; }

    return month;
*/
    return getCurrentTime().substr(4,2);
}

/**
 * 현재 日을 DD형식으로 리턴

 */
function getDay() {
/*
    var now = new Date();

    var day = now.getDate();
    if (("" + day).length == 1) { day = "0" + day; }

    return day;
*/
    return getCurrentTime().substr(6,2);
}

/**
 * 현재 時를 HH형식으로 리턴
 */
function getHour() {
/*
    var now = new Date();

    var hour = now.getHours();
    if (("" + hour).length == 1) { hour = "0" + hour; }

    return hour;
*/
    return getCurrentTime().substr(8,2);
}

/**
 * 오늘이 무슨 요일이야?

 * ex) alert('오늘은 ' + getDayOfWeek() + '요일입니다.');
 * 특정 날짜의 요일을 구하려면? => 여러분이 직접 만들어 보세요.
 */
function getDayOfWeek() {
    var now = new Date();

    var day = now.getDay(); //일요일=0,월요일=1,...,토요일=6
    var week = new Array('일','월','화','수','목','금','토');

    return week[day];
}

* 영문/숫자조합 6~12자 비밀번호 체크(정규식)
 
function mycheck(p)
{
    chk1 = /^[a-z\d]{6,12}$/i;  //a-z와 0-9이외의 문자가 있는지 확인
    chk2 = /[a-z]/i;  //적어도 한개의 a-z 확인
    chk3 = /\d/;  //적어도 한개의 0-9 확인
    return chk1.test(p) && chk2.test(p) && chk3.test(p);
}

 * p : 검사 값
 * 조합이면 true 반환


*javascript로 숫자 또는 지정한 문자만 받게 필터링
 
<숫자만 가능>
function onlyNum(txtbox) 
{
    var v=txtbox.value;
    if(v.match(/[\-\+]?\d*(\.\d*)?/g)[0]!=v)
    {
        txtbox.value=v.match(/[\-\+]?\d*(\.\d*)?/g)[0]
    }
}
 
<문자만 가능>
function onlyNum(txtbox) 
{
    var v=txtbox.value;
    if(v.match(/[\-\+]?[a-z]*(\.[a-z]*)?/g)[0]!=v)
    {
        txtbox.value=v.match(/[\-\+]?\d*(\.\d*)?/g)[0]
    }
}


* HTML 태그 제거

function stripHTMLtag(string)

    varobjStrip = new RegExp(); 
    objStrip = /[<][^>]*[>]/gi; 
    return string.replace(objStrip, ""); 
}

.href 와 .repalce()는 모두 location의 하위객채로 브라우저에서 URL이동때 쓰인다.

그러나 쓰는 형태를 보면 알겠지만 .href 는 프로퍼티고, .replace()는 메소드다.

 

location.href = http://www.naver.com        <= [1] 값을 정의해야 하는프로퍼티

location.replace(http://www.naver.com)    <= [2] 파라미터로 동작을 명령하는 메소드

 

아. 그게 뭐가 중요하냐... 브라우저가 주소만 바뀌면 되는거 아냐... 라고 하겠지만..

그게 아니라 이거지... ㅡ ㅡa

 

골아프겠지만, 자바스크립트에서 정의한 정확한 의미를 집어보자.

 

location 은 현재 브라우저에 떠있는 URL 주소값에 관련된 내용을 다루는 객체다.

브라우저의 주소표시줄에 있는 URL은 다음과 같이 정의된다.

 

protocol :// hostname : port / pathname ? search # hash

 

location.href는 위에 써있는 전체를 가르키며,

location.pathname 이라고 하면 같은 사이트에 파일경로만을 가르킨다.

(예를 들면...http://www.naver.com/blog/myinfo/profile.asp  라는 페이지가 떠있따면...

location.href에는 이거 전체가, location.phthname 에는 [blog/myinfo/profile.asp] 가 들어있다.)

 

그래서 location.href 라고 하면 브라우저의 주소표시줄에 떠있는 URL를 가르킨다.

그러므로 [1]처럼하면 브라우저의 주소표시줄 값이 변경되므로 페이지가 바뀌게 된다.

(물론 프레임, 아이프레임을 썼을땐 그 프레임의 주소가 바뀐다.)

 

[1]을 했을떄 일어나는 일은 우리가 주소표시줄에 키보드로 직접 주소를 넣고 엔터를 치는것과 정확히 같은 일을 일으킨다.

여기서 같은 일이란,

새로은 페이지로 이동(a)되고,

[뒤로]버튼을 누르면 이전 URL로 이동(b)되는것을 말한다.

 

(a) , (b)에 대해 좀만더 자세히 보자.

 

(a)  새로운 페이지로 이동.

브라우저 옵션을 손대지 않았을때, 브라우저의 주소값이 바뀌면 브라우저는 '인터넷 임시파일'

(C:\Documents and Settings\Administrator\Local Settings\Temporary Internet Files\)

에 캐쉬가 있는지를 먼저 보고, 있으면 그걸 보여준다.

그래서 가끔 우린 사이트내용이 바뀌었는데도, 로컬에 있는 파일을 보는 경우가 있다.

location.href로 주소이동을 했을떄 이와 같은 일이 일어난다.

 

(b) [뒤로]버튼을 누르면 이전 URL로 이동.

[뒤로]버튼이 정상장동되는것은 History객체에 배열처럼 이전 URL들이 기록되어있기때문이다.

우리가 [뒤로]버튼을 누르는건 History객체를 역순으로 되집어 가는 과정이다. ( history.back()이 그 일을 한다. )

location.href를 쓰면 [뒤로]버튼도 history.back()도 직접URL바꿨을때와 똑같이 작동한다.

 

그럼 location.replace()는 뭐가 다를까?

location.repalce()는 다음과 같이 작동한다.

 

1. location.replace() (a)의 경우  '인터넷 임시파일'을 쓰지 않는다. 매소드가 실행될때마다 매번 서버에 접속해서 페이지를 가져온다. 게시판 리스트같은 곳을 이동할때 location.href를 쓰면 새 글이 올라온것을 모르고 '로컬에 있는 파일'만 보는 일이 생길 수 있는데, location.replace()를 쓰면 이를 방지할 수 있다.

 

2. location.replace()은 새 페이지로 이동하는게 아니라 현재페이지를 바꿔주는 거다.

말장난 같아도 이거 중요한거다.. 왜중요한고하니...

(b)의 경우, History객체에 새로운 URL를 기록하는게 아니라 현재 페이지값을 바꾼다.

그러므로 location.replace()로 이동하고 [뒤로]버튼을 누르면 이전페이지가 아니라 이전,이전페이지가 뜬다. 이해가 안된다고?

 

A --> B --> C    처럼 페이지가 이동을 했다하자. (현재 당신은 C사이트에...)

B --> C로 이동할때 location.href를 썼다면

C페이지트에서 [뒤로]버튼을 누르면 B가뜬다.

하지만..

B --> C로 이동할때 location.replace()를 썼다면

C페이지에서 [뒤로]버튼을 누르면 A가뜬다.

그럼 사용자입장에선 '어 내가 클릭을 두번했나?' 하게 된다...

 

이런 차이로 인하여 적절히 써야 한다.

[뒤로]버튼을 눌렀을때 두페이지 이전으로 넘어가면 안되는 경우가 있는 반면,(.href를 써야겠지..)

프레임을 쓴 사이트 의 경우는 [뒤로]버튼 한두번 클릭으로 사이트를 빠져나가게 할 수도 있다. (.repalce()를 쓴경우...)

이 문제는 IE 6에서만 나타나는 문제이며 이로 인해 가시적으로 드러나는 현상는

이미지의 깜박거림이지만 더욱 치명적인 문제는 깜박거리는 현상이 발생할때마다 (또는 깜박거리지는 않더라도) 해당 이미지를 가지고 있는 서버로 이미지 전송 요청을 보내거나 local cache 를 access (file access) 하는  현상이 유발되고 이로인해 사용자 브라우저의 메모리 및 CPU 과다사용, 랜더링 속도 저하, working cursor(모래시계)로 마우스 커서 바뀌는 현상 등이 동반되므로 더 나은 서비스를 제공하고자 한다면 각별히 주의해야될 문제다.

이러한 현상은 일어나는 원인은 크게 두가지 유형 정도로 판단된다.

문제 1) href 속성이 주어진 A 태그가 있고 해당 A 태그 혹은 그 하위 element에 css로 background-image 를 적용하였을 경우, A 태그에 hover(마우스 오버, 포커스 이동 등)가 되면 A 태그와 그 하위에 있는 모든 element에 적용된 background-image가 - 같은 이미지 일지라도 element 수만큼 - 서버에 재요청되는 현상이 생긴다.
-> 깜박거림, working cursor등이 동반될 수 있다.

문제 코드1 보기

<html>
<head>
<title> test </title>
<style type="text/css">
span {
  background-image: url(test1.gif);
}
a {
  background-image: url(test2.gif);
}
</style>
</head>
<body>
<a href="#">
    <span>test</span>
    <span>test</span>
    <span>test</span>
    <span>test</span>
</a>
</body>
</html>

문제 2) 임의의 element에 css로 background-image 를 적용하였을 경우, onload이벤트 후에 해당 element나 그 상위 element의 style을 수정하면 해당 element에 적용된 background-image가 서버에 재요청되는 현상이 생긴다. 바꿔 말해서 onload 이후에 background-image가 적용된 부분을 포함하고 있는  element의 style을 바꾸면 해당 element와 그 하위에 있는 element들에 적용되어있는 모든 background-image가 - 같은 이미지 일지라도 element 수만큼 - 서버에 재요청 되는 현상이 생긴다.
-> 깜박거림, working cursor등이 동반될 수 있다.-> 깜박거림, working cursor등이 동반될 수 있다.


문제 코드2 보기

 
<html>
<head>
<title> test </title>
<style type="text/css">
#test {
  background-image: url(test1.gif);
}
span {
  background-image: url(test1.gif);
}

</style>
<script type="text/javascript">
function init() {
    document.getElementById('test').style.position = 'relative'
    document.getElementById('test').style.top = '1px'
    document.getElementById('test').style.left = '2px'
}
</script>
</head>
<body onload="init()">
<div id="test">
    <span>test</span>
    <span>test</span>
    <span>test</span>
    <span>test</span>
    <span>test</span>
</div>
</body>
</html>


문제1, 2를 완벽히 해결하는 방법.


사용자들에게 브라우저를 바꾸도록 강요할 수 있다면 IE6 이외의 브라우저를 사용하게 한다.
문자1, 2의 상황이 생기는 필요조건을 충족하지 않도록 코드를 바꾸는게 가능하다면 바꾼다.
  (ex. background-image를 사용하지 않은 css 혹은 img태그로 대체.)
하나마나한 얘기인가?. 그래도 모른다. 고민해보자.. 이 두가지가 가능한지.


문제1, 2가 일어나는 브라우저 범위를 줄이는 방법.

Internet Explorer 6 서비스 팩 1(Windows XP SP1) 이후의 브라우저에서는 "BackgroundImageCache" 라는 Command Identifier로 execCommand를 호출함으로써 이 문제들을 해결할 수 있다.
 - 서비스팩 2에서는 포함되어 있으며, 서비스 팩 1(6.00.2800.1106)은 update 유무에 따라 다를 수 있다. - 브라우저 버젼 확인 방법 ( http://support.microsoft.com/kb/164539/ko )

document.execCommand("BackgroundImageCache", false, true);

이 생소한 BackgroundImageCache라는 녀석은 MSDN에서 제공하고 있는 Command Identifiers list (http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/commandids.asp) 에서도 찾을 수 없다.

MSDN KB를 뒤진 결과.
 Available memory decreases when you view a Web page in Internet Explorer 6 Service Pack 1 (http://support.microsoft.com/kb/823727) 에서 이 녀석에 대한 언급을 볼 수 있었다. 이 문서에서 말하고 있는 해당 hotfix의 원인과 설명은 보든 안보든 달라질게 없는 쓸모없는 내용이다. 또한 "Document.ExecCommand" 처럼 대소문자 규칙까지 어기고 있다. 여튼 이 너저분한 내용의 hotfix와 그 해결 방식은 치명적일수도 있는 결함에 대한 MS의 궁여지책 같은 냄새가 짙다.
결론은 Internet Explorer 6 서비스 팩 1 이후의 브라우저에서만 이 문제를 해결하고자 한다면,
BackgroundImageCache Identifier가 없는 브라우져에서 발생할 수 있는 예외를 무시할 수 있는 코드가 첨가된 아래 코드만으로 충분하다.

Internet Explorer 6 서비스 팩 1(Windows XP SP1) 이후 브라우저를 위한 해결.

try {
    doument.execCommand("BackgroundImageCache", false, true);
} catch(ignored) {}

주의. 아래와 같은 해결방법에 대한 제시를 본적이 있다.
html {
    filter: expression(document.execCommand('BackgroundImageCache', false, true));
}
유사해 보이지만 다른 내용이다. 이 방식은 두가지 측면에서 좋지않다. 첫째는 BackgroundImageCache Identifier가 없는 브라우져에 대한 예외처리가 없다는 것이고, 둘째는 한번만 수행하면 되는 코드가 지속적으로 수행된다는 것이다.


구제받지 못한 IE6들을 위한 개선 방법

간단한 코드로 IE6 서비스팩 2와 서비스팩 1이후의 일부는 문제 대상에서 제외됐지만, 아직 서비스팩이 포함되지 않은 IE6가 방치되어 있다. 불행히도 이 브라우저들을 위한 간단한 해결책은 없는 듯하다. 그래서. 문제를 개선할 수 있는 방법을 정리한다.

개선 1. 브라우저와 서버의 통신을 줄인다.

방법 1.1. 사용자 브라우저의 임시 인터넷 파일 설정을 바꾸도록 한다.

브라우저의 임시 인터넷 파일 설정이 기본 설정값인 "페이지를 열때 마다" 일때 더 심각한 문제를 유발하므로 사용자에게 브라우저 설정을 바꾸는 것을 강요할 수 있는 상황이라면 그렇게 하라.
방법 1.2. 서버에서 expires나 cache-control헤더를 포함한 컨텐츠를 보내서 클라이언트의 local cache 사용을 유도한다.


서버설정참고 열기

 
아파치일 경우

httpd.conf 에 아래 내용을 추가

ExpiresActive On
ExpiresByType image/gif A2592000
ExpiresByType image/jpeg A2592000
ExpiresByType image/png A2592000

LoadModule expires_module modules/mod_expires.so

httpd.conf 를 수정할 수 없다면 자신의 .htaccess 파일을 수정한다. (단, mod_expires는 load되어 있어야한다)

설정방법 참고 : http://dean.edwards.name/my/flicker.html
mod_expires에 대한 설명 : http://httpd.apache.org/docs/2.2/ko/mod/mod_expires.html

IIS일 경우

아래의 헤더를 추가
Cache-Control: post-check=3600,pre-check=43200

설정방법 참고 : http://www.aspnetresources.com/blog/cache_control_extensions.aspx


서버 설정을 할 수 없다면 웹 어플리케이션 작성시 expires나 cache-control헤더를 클라이언트에게 보내는 코드를 추가하라.
이 방법들은 컨텐츠를 서버에서 받아간 후, 파기(expire)되는 기간까지 서버에 재요청하지 않고 local cache를 사용하게 하는 일반적인 웹어플리케이션 성능향상 팁이기도 하다.

위에서 제공 것은 개선 방법임을 다시 한번 강조한다. 절대. 해결 방법이 아니다. 원격서버와의 통신을 줄어드나 local cache에 대한 불필요한 접근들은 일부 방치된다. 어떤 것들이 방치되는지 궁금하다면.. 브라우저 프로세스가 여는 파일 핸들들을 감시해보라.

개선 2. 문제1에서의 이미지 깜박거림을 감소시킨다.

이 부분은 아래의 링크에 수록된 잼있는(?) 내용을 전제로 한다.
Minimize Flickering CSS Background Images in IE6  (http://www.fivesevensix.com/studies/ie6flicker/)

이 문서에서는 문제 1에서 발생하는 깜박거림에 대한 집요한 테스트 결과가 있다.

아래의 속성이 직접 적용되거나 상속되는 경우,
    background-color : transparent 이외의 값
    background-repeat : repeat 이외의 값
    background-position : 모든 값
또는
background-image가 적용된 element의 크기가 2500픽셀 미만일떄,
또는
투명 gif를 백그라운드 이미지로 사용했을때,

깜박거림 현상이 더 크게 발생하며

A태그의 상위엘리먼트에 같은 background-image를 지정해둠으로써 깜박 거림 현상을 감소시킬 수 있는 방법등을 제시하고 있다. 잼있는 개선방법중 하나지만 다른 개선이 배제된 상태에서의 이런 개선방법은 별로 추천하고 싶지는 않다.

개선 3. 문제2에 대한 개선

문제2에서의 특이한 사항은 특정 element의 style을 보정할때 style이 직접 대입되는 element는 그 대입횟수만큼 background-image를 다시 로딩하는 현상(download 혹은 local cache 접근) 이 생긴다는 것이다. 이와 달리 그것의 하위 element들은 상위element에 style이 대입되는 처음 시점에 단 한번의 불필요한 로딩만 다시 일어난다.

따라서 문제2를 조금 개선할 수 있는 방법은 style을 보정할 element에는 background-image css가 적용되어 있지 않게 하거나 뺄 수 없다면 불필요한 element로 싸는 정도의 간단하고 깔끔하지 못한 방법으로 문제를 축소시킬 수 있다.

모든 style 적용에서 테스트를 해본 것이 아니라. 항상 이 규칙이 적용된다는 보장은 할 수 없지만, 분명히 일반적인 위치이동 등의 처리에서는 개선되는 효과가 있다.

페이지에서 쿠키 값을 체크 하여 팝업을 열지 말지를 선택하는 소스이다.
자주 쓰이고 쉽게 검색 할 수 있는 소스이지만, 정리 차원에 써놨다.

팝업 페이지에 체크 박스의 체크 여부나, onClick 이벤트 등을 이용하여 쿠키값을 지정한다.
지정하는 방법은 아래와 같다.

<script language=javascript>
    function setCookie(name, value, expiredays) {
        var todayDate = new Date();
        todayDate.setDate( todayDate.getDate() + expiredays );
        document.cookie = name + "=" + escape( value ) + "; path=/; domain=.saramin.co.kr;
                                expires=" + todayDate.toGMTString() + ";"
    }
</script>

체크 박스를 이용한다면, 선택 되어 있는지 확인 후,
쿠키를 지정해 주면 된다. 그리고 self.close() 그러면 끝!!!

마지막으로 메인페이지에서 팝업 페이지를 열지의 여부는 쿠키값을 체크하여
팝업을 열어주면 된다.
쿠키 값을 체크하는 소스는 아래와 같다.

<script language=javascript> 
    function getCookie(sName) {
        var aCookie = document.cookie.split("; ");
        for (var i=0; i < aCookie.length; i++) {
            var aCrumb = aCookie[i].split("=");
            if (sName == aCrumb[0]) {
                return unescape(aCrumb[1]);
            }
       }
       return "";
    }
</script>


ASP.NET Performance Tips

At times even after applying the best coding policies & practices you don’t get the desired level of performance you are hoping from your ASP.NET application. This is because there are number other very important factors that directly affect ASP.NET applications. To get the best out of any system requires detail architectural, design, coding and deployment considerations. The post lists few of some of the many performance tweaks that you can implement to boost up ASP.NET performance.

Remove Unused HTTP Modules

There are various HTTP modules in ASP.NET that intercept each request sent to the server. Session State is a very commonly used HTTP module used to load session data in context object. It’s referred with SessionStateModule name. HTTP modules kick in at each request and process them, therefore if you are not using the functionality provided by the module there is no use referring it as they would use additional CPU cycles. There is a list of HTTP Modules that your application automatically uses when it inherits config setting from web.config placed in $WindowsFolder\Microsoft.NET\Framework\$versiosn\CONFIG folder.
Below is a list of such entries:

<httpModules>
  <add name="OutputCache" type="System.Web.Caching.OutputCacheModule"/>
  <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
  <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule"/>
  <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule"/>
  <add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule"/>
  <add name="RoleManager" type="System.Web.Security.RoleManagerModule"/>
  <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule"/>
  <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule"/>
  <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule"/>
  <add name="Profile" type="System.Web.Profile.ProfileModule"/>
  <add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
  <add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</httpModules>

There are bunch of HTTP modules listed here and I am quite positive not all of them are being used by your application. Removing unused HTTP module can definitely give slight performance boost as there would be less work to be performed. Suppose one doesn’t needs Windows authentication in application. To remove the inherited setting, under httpModules section in your web.config application add a remove element and specify name of the module that isn’t required.

Example:
      <httpModules>
            <remove name="WindowsAuthentication" />
      </httpModules>

<compilation debug=”true”/> Killer
As a developer I have seen numerous incidents were the application is deployed to production with <compilation debug=”true”/>. This is really a performance killer because:
  • Compilation of ASP.NET pages take longer.
  • Code execute slower as debug paths are enabled.
  • More memory is used by the application.
  • Scripts and images from WebResource.axd handler are not cached.

Always make sure that debug flag is set to false on production instances. You can override this by specifying following entry in machine.config for production instances:

      <configuration>
            <system.web>
                    <deployment retail=true/>
            </system.web>
      </configuration>

This will disable the <compilation debug=”true”/> for all applications deployed on the server.

Turn off Tracing

Do remember to turn off tracing before deploying application to production. Tracing adds additional overload to your application which is not required in production environment. To disable tracing use the following entries:

      <configuration>
            <system.web>
                    <trace enabled="false" />
            </system.web>
      </configuration>

Process Model Optimization
ASP.NET allows you to define many process level properties. You can get the detail of all these properties from http://msdn.microsoft.com/en-us/library/7w2sway1.aspx.  By default these are set to auto config. This means that ASP.NET automatically configures maxWorkerThreads, maxIoThreads, minFreeThreads, minLocalRequestFreeThreads and maxConnection to achieve optimal performance. You can tailor these by specifying your own value to achieve better performance. Some of the major settings are:
  • maxWorkerThreads. The default value is 20 per process and it determines the maximum number for request that ASP.NET can process in a given second. For application that are not CPU intensive and most of time wait on database request or any external processing this can increased to get better performance.
  • maxIOThreads. The default value is 20 per process and it determines the maximum number for I/O request that ASP.NET can process in a given second. If you have enough I/O resources you can increase this value for better results.
  • memoryLimit: The default is 60%. This is the max memory ASP.NET can use until worker process is refreshed. If you have a dedicated web server with no other services running you can increase this value for better results. 
  • connectionManagement: This is a property of System.Net configuration and specifies the maximum parallel connections that can be established to a server. If your web application extensively connects to other server you can increase this value.
Enable Buffering

Make sure that buffering is enabled unless you have a specific need to turn it off. By default its enabled. ASP.Net sends response to IIS in a 31 KB buffer which then passes that to the client. When buffering is disabled ASP.NET only sends few characters to IIS thus not utilizing this buffer and increasing the trips between IIS and the worker process. To enable it you can change the web.config or enable it on each page through @page directive

      <pages buffer="true">

      <%@ Page Buffer="true"%>

Caching
Caching in ASP.NET dramatically help in boosting application performance by reducing the load on the underlying server and serving cached content that doesn’t need to be recreated on each request. ASP.NET provides two types of caching:
  • Output Cache which stores dynamic pages and user controls. One each request code is not executed if a cached version of page or control is available 
  • Data Cache which allows application to save application objects, DataSet etc in server memory so they are not recreated on each request.

Use caching whenever possible to reduce the load on your web server and to increase response time.

Caching is a huge topic can not be discussed in detail in one post. For more details visit http://msdn.microsoft.com/en-us/library/xsbfdd8c.aspx.

Kernel Cache
Use Kernel Cache if you are using IIS 6 or above. When Output cache is used in ASP.NET the request still goes to ASP.NET that itself returns the cached content. However if Kernel Cache is enabled and the request is output cached by ASP.NET, IIS receives the cached content. If a request comes for that data again IIS will serve the cached content and end the response. This can save valuable CPU cycles as it minimizes work performed by ASP.NET.

Avoid using Response.Redirect
Instead of using Response.Redirect, use Server.Transfer where ever you can. Response.Redirect sends response to the client which then sends a new request to the server. Server.Transfer however performs the redirect on the server. Only use Response.Redirect when you want authentication and authorization to be performed on redirects or you want URL on client browser to be changed because Server.Transfer will not do this as it is a server side transfer.

Avoid using Server-Side Validation
Where ever you can use client-side validation instead of Server-Side validation. This will save you from additional reposts in cases in invalid input. If you don’t trust the browsers that they will be able to perform complex validations still use client-side validation and on repost check Page.IsValid to check if the input passed the given set of rules.

Avoid DataBinder.Eval Calls
Avoid calling DataBinder.Eval multiple times for example in case of grids, repeaters etc. Instead use Continer.DataBind. DataBinder.Eval uses reflection to evaluate the arguments and therefore can decrease performance if called numerous times.

Avoid Using Page.DataBind
Never call Page.DataBind until your really need to do so. Instead if you want to bind a specific control only bind that. Calling Page.DataBind will call DataBind for all the controls that support binding.

ViewState Optimization
Avoid using ViewState for storing huge objects or disable it when you don’t need it. ViewState is also used by server controls so that they can retain their state after postback. You can also save your objects that are marked Serializable in the ViewState. ASP.NET serializes all objects and controls in the ViewState and transmits them in a hidden field to the browser. If not managed properly ViewState can increase page size and therefore increase network traffic. Also precious CPU cycles are used for Serialization and De-Serialization of ViewState objects. Disable ViewState if:
  • Your pages don’t do postback.
  • You controls are not bound to a data source or they don’t handle server events like OnClick, OnSelectedIndexChanged etc or their properties are set on each postback
  • You recreate controls on every postback.

You can disable ViewState in both web.config or @Page directive

      <pages enableViewState="false">
      or
      <%@ Page EnableViewState="false"%>

Save or Compress ViewState
In case where ViewState in mandatory and the ViewState contains enough data that can cause Network congestion or increase download response time for the user try saving or compressing the ViewState. The Page class provide two very useful methods LoadPageStateFromPersistenceMedium() and SavePageStateToPersistenceMedium(object ViewState). You can override these methods to either compress the ViewState or even prevent it from going to the client by saving it in some persistent medium on the server.

Use HTTP Compression
If your page size is large enough to cause noticeable lag between subsequent request and response you can use HTTP compression. HTTP compression is a feature of IIS and what it means is that you can compress data sent to the client using compression techniques like GZIP and Deflate. On the other side the browser decompresses the data and shows the response to the client. Most of the modern browser are capable of handling compressed data. You will certainly get a huge performance boost if your page size is large.

For more details on HTTP compression visit http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/d52ff289-94d3-4085-bc4e-24eb4f312e0e.mspx?mfr=true

Data Paging / Sorting
When ever using data grid to show data with paging enabled one thing needs to understood that if your query returned let say 5000 record and you are only showing 100 records per page the rest of the 4900 record will be discarding and the same will apply when ever you will change the page or apply sorting. The additional 4900 rows will definitely take up memory and if your database is located on a different server which is most commonly the case you will also be transferring unnecessary data over the network. Make sure you are only returning the required results to the ASP.NET application by filtering out the data in your database query and apply custom paging. SQL Server 2005 and onwards provide valuable function for ranking data that can be used to accomplish this.

Connection Pooling
Creating a connection to a database is a resource intensive process and takes time. Connection pooling allows you to reuse these connections saving time and resources. When a new connection is requested the connection pool managers first searches in the connection pool and if doesn’t finds one, it creates a new one. There are various things that need to be done to use connection pooling effectively:
  • Avoid Connection Leakage. This means that you opened a connection but didn’t close it. If you don’t close the connection the connection pool manager will never put it in the pool for later reuse until the GC is called.
  • Use the same connection string. Connection pool manager searches for similar connection in the pool by the connection string.
  • Use SQL Servers and .NET CLR Data performance counters to monitor pooling.
  • Open connections as late as possible and close them as early as possible
  • Don’t share same connection between multiple function calls. Instead open a new connection and close it in each function.
  • Close transactions prior to closing the connection.
  • Keep at least one connection open to maintain the connection pool.

Avoid Multiple Database Access
Avoid accessing database multiple times for the same request. Analyze your code and see if you can reduce the number of trips to database because these trips reduce the number of request per second your application can serve. You can do this by returning multiple records in the same stored proc, combining multiple DB operations in same stored proc etc.

Use DataReader Instead of DataSet
Use DataReader objects instead of DataSet when ever you need to display data. DataReader is the most efficient means of data retrieval as they are read and forward only. DataSet are disconnected and in-memory therefore uses valuable server resources. Only use them when you need the same data more then once or want to do some processing on the data.

Last but certainly not the least follow the best coding, design and deployment patterns and practices. Here are few more usefull links that can be very helpful in performance optimization of you ASP.NET application

HTML 코드에서 span 태그 또는 a 태그에 title를 이용하여 tooltip를 나타내는 경우가 있는데,
아래는 두줄로 나타내는 방법이다.

<span title="안녕하세요.&#10;ToolTip 테스트">ToolTip Test</span>
 
ToolTip 테스트(마우스UP)
 
 
줄단위의 \r\n 를  &#10; 로 표현하시면 Tooltip 이 2줄로 나타나게 된다.
 

[직접 만드는법]

실행창에서 notepad 명령어를 입력하여 메모장을 엽니다.
아래와 같이 입력한 후, 저장합니다.

[Shell]
Command = 2
IconFile=explorer.exe,3
[Taskbar]
Command=ToggleDesktop

파일명은 바로가기만들기.scf 로 저장합니다.

ASP.NET Web Application Projects

The Web Application Projects add-in provides a Visual Studio 2005 Web project model that will serve as the standard for .NET applications development. The new model will replace the existing Web Site model.
Adding Web application projects to Visual Studio 2005 requires you to install both an update and an add-on to Visual Studio 2005. The two installations perform the following tasks: The next service pack released for Visual Studio 2005 should contain the update and add-in, however, until that time these require a manual installation.
For additional information, refer to the Knowledge Base article on MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/wap.asp.

Project templates

Two project templates have been created and are available for developers to download and use with Visual Studio 2005. The templates provide the basic Web application project configuration for the presentation and business tiers, and eliminates the majority of the start-up coding necessary to begin developing an application.
While the project templates contain much of the code outlined in the Application Configuration section, it is recommended that you read the section in its entirity to understand the logic and reasoning behind the choices made.
To add the project templates to Visual Studio 2005, complete the following steps:
  1. On the Visual Studio 2005 toolbar, click on Tools
  2. Select Options...
  3. Click on Projects and Solutions
  4. In the box below Visual studio user project templates location: enter \\dotnettest01\ProjectTemplates
  5. Click on OK
Once the project templates have been added to Visual Studio 2005, create the presentation and business tiers for your Web application project using the following steps:
  1. Select File > New > Project...
  2. Under the Project types listing on the left, select Visual C#
  3. Click on UCS - ASP.NET Web Application under the My Templates heading
  4. Name the presentation tier using the Pascal capitalization standard
    For example: AdminConsole
  5. Click on OK
  6. After creating the presentation tier, add the business tier by right clicking on the solution name and select Add > New Project...
  7. Click on UCS - Class library under the My Templates heading
  8. Name the business tier using the Pascal capitalization and Uppercase standards
    For example: BSU.UCS.AdminConsole
  9. Click on OK
  10. Note: The presentation tier contains an invalid reference to the BSU.UCS.ASPDotNetTemplate project. You will need to remove this reference and add a new project reference to the class library you created in the step above.
Using these standards will create the necessary folder structure needed to follow the Microsoft Visual SourceSafe naming conventions.
There are several benefits gained by using the aforementioned project templates. First, the templates are stored in a common area available to all developersWhen a new template is deployed to the server by copying the ZIP file to the share, all developers immediately have access to it from within Visual Studio. After the initial deployment, changes to the template can be made in one place instead of having to be deployed to each developer's workstation.
In addition, because the template is used as a true template, it remains unchanged and can be used repeatedly to create new projects. This is a vast improvement over the old "copy and paste" approach where one developer would create a file or project and hand it off to another. Without careful management, the original was quickly lost and modified with no chance to get back to a known good configuration.


 

Microsoft recently released a cool new ASP.NET server control - <asp:chart /> - that can be used for free with ASP.NET 3.5 to enable rich browser-based charting scenarios:

Once installed the <asp:chart/> control shows up under the "Data" tab on the Toolbox, and can be easily declared on any ASP.NET page as a standard server control:

<asp:chart /> supports a rich assortment of chart options - including pie, area, range, point, circular, accumulation, data distribution, ajax interactive, doughnut, and more.  You can statically declare chart data within the control declaration, or alternatively use data-binding to populate it dynamically.  At runtime the server control generates an image (for example a .PNG file) that is referenced from the client HTML of the page using a <img/> element output by the <asp:chart/> control.  The server control supports the ability to cache the chart image, as well as save it on disk for persistent scenarios.  It does not require any other server software to be installed, and will work with any standard ASP.NET page.

To get a sense of how to use the <asp:chart /> control I recommend downloading the Microsoft Chart Controls Sample Project.  This includes over 200 ASP.NET sample pages that you can run locally.  Just open the web project in VS 2008 and hit run to see them in action - you can then open the .aspx source of each to see how they are implemented.

The below example (under Chart Types->Line Charts->3D Line and Curve Charts) demonstrates how to perform Line, Spline and StepLine charting:

The below example (under Chart Types->Pie and Doughnut Charts) demonstrates a variety of pie and 3D doughnut options:

The below example (under Chart Types->Advanced Financial Charts) demonstrates some graph charts:

In addition to the above samples, you can download the Microsoft Chart Control Documentation or ask questions on the Chart Controls Forum to learn more.

This should provide a useful (and free) addition to your standard ASP.NET toolkit of functionality, and enable you to easily add richer visualization and data workflow scenarios to your ASP.NET applications.


Every time I create an IIS website, I do some steps, which I consider as best practice for creating any IIS website for better performance, maintainability, and scalability. Here' re the things I do:

Create a separate application pool for each web application

I always create separate app pool for each web app because I can select different schedule for app pool recycle. Some heavy traffic websites have long recycle schedule where low traffic websites have short recycle schedule to save memory. Moreover, I can choose different number of processes served by the app pool. Applications that are made for web garden mode can benefit from multiple process where applications that use in-process session, in memory cache needs to have single process serving the app pool. Hosting all my application under the DefaultAppPool does not give me the flexibility to control these per site.

The more app pool you create, the more ASP.NET threads you make available to your application. Each w3wp.exe has it's own thread pool. So, if some application is congesting particular w3wp.exe process, other applications can run happily on their separate w3wp.exe instance, running under separate app pool. Each app pool hosts its own w3wp.exe instance.

So, my rule of thumb: Always create new app pool for new web applications and name the app pool based on the site's domain name or some internal name that makes sense. For example, if you are creating a new website alzabir.com, name the app pool alzabir.com to easily identify it.

Another best practice: Disable the DefaultAppPool so that you don't mistakenly keep adding sites to DefaultAppPool.

image

First you create a new application pool. Then you create a new Website or Virtual Directory, go to Properties -> Home Directory tab -> Select the new app pool.

image

Customize Website properties for performance, scalability and maintainability

First you map the right host headers to your website. In order to do this, go to WebSite tab and click on "Advanced" button. Add mapping for both domain.com and www.domain.com. Most of the time, people forget to map the domain.com. Thus many visitors skip typing the www prefix and get no page served.

image

Next turn on some log entries:

image

These are very handy for analysis. If you want to measure your bandwidth consumption for specific sites, you need the Bytes Sent. If you want to measure the execution time of different pages and find out the slow running pages, you need Time Taken. If you want to measure unique and returning visitors, you need the Cookie. If you need to know who is sending you most traffic - search engines or some websites, you need the Referer. Once these entries are turned on, you can use variety of Log Analysis tools to do the analysis. For example, open source AWStats.

But if you are using Google Analytics or something else, you should have these turned off, especially the Cookie and Referer because they take quite some space on the log. If you are using ASP.NET Forms Authentication, the gigantic cookie coming with every request will produce gigabytes of logs per week if you have a medium traffic website.

image

This is kinda no brainer. I add Default.aspx as the default content page so that, when visitors hit the site without any .aspx page name, e.g. alzabir.com, they get the default.aspx served.

image 

Things I do here:

  • Turn on Content Expiration. This makes static files remain in browser cache for 30 days and browser serves the files from its own cache instead of hitting the server. As a result, when your users revisit, they don't download all the static files like images, javascripts, css files again and again. This one setting significantly improves your site's performance.
  • Remove the X-Powered-By: ASP.NET header. You really don't need it unless you want to attach Visual Studio Remote Debugger to your IIS. Otherwise, it's just sending 21 bytes on every response.
  • Add "From" header and set the server name. I do this on each webserver and specify different names on each box. It's handy to see from which servers requests are being served. When you are trying to troubleshoot load balancing issues, it comes handy to see if a particular server is sending requests.

image

I set the 404 handler to some ASPX so that I can show some custom error message. There's a 404.aspx which shows some nice friendly message and suggests some other pages that user can visit. However, another reason to use this custom mapping is to serve extensionless URL from IIS. Read this blog post for details.

image

Make sure to set ASP.NET 2.0 for your ASP.NET 2.0, 3.0 and 3.5 websites.

Finally, you must, I repeat you "MUST" turn on IIS 6.0 gzip compression. This turns on the Volkswagen V8 engine that is built into IIS to make your site screaming fast.


출처 : http://weblogs.asp.net/omarzabir/archive/2008/10/04/best-practices-for-creating-websites-in-iis-6-0.aspx

+ Recent posts