공룡호가 사는 세상 이야기

하이퍼링크 or Method=GET : Request.QueryString
폼Method="POST" : Request.Form

가끔, 어떤 경우는 GET 방식으로도, POST 방식으로도 같은 이름의 데이터가 넘어오는 경우가 있을 수 있다.
그러한 경우에는 동일한 이름을 사용하여 GET 혹은 POST로 넘어 오는 데이터를 얻어낼 수 있는 방법이 필요한데, 그러한 경우에는 어떻게 대처해야 하는가? Request 개체는 그러한 경우에 사용할 수 있는 특별한 컬렉션을 별도로 준비해 두었는데, 그것은 Params 이다.

Request.Params 속성은 내부적으로 QueryString과 Form을 모두 수행한다.
그러므로 ASP.NET 페이지가 어떠한 경우는 GET방식으로 넘어오는 "email" 이라는 이름의 값을 얻어내야 하고, 어떠한 경우는 POST 방식으로 넘어오는 "email"이라는 이름의 값을 얻어내야 한다면 다음과 같이 작성하여, 두 가지 모두의 경우를 대비할 수 있다.

Request.Params["email"]

이 코드는 내부적으로 먼저 email이라는 키에 대해서 QueryString을 수행하고, 그에 해당하는 값이 없으면 Form 작업도 수행한다. 그리고, 지정된 키에 해당하는 값을 찾으면 그 값을 읽어 온다. 또한, 이 코드는 다음과 같이 줄여서 사용할 수도 있다.

Request["email"]

이것 때문에 대체 얼마나 삽질을 해댔는지. 포스트 백만 일어나면 값이 사라졌다.
처음엔 값이 사라지는줄도 몰랐다. FindControl() 메소드도 null만 리턴해댔다.
값이 사라지는 것인지, 컨트롤이 사라지는 것인지 분간도 되지 않았다.

TextBox Property는 내부적으로 작성된 소스를 보게 되면 텍스트의 내용이 null일 경우, string.Empty를 리턴한다.
그래서 참조를 할 경우 참조 에러가 나게 된다.

한가지 더.
패널을 사용하여 각 패널에 컨트롤을 나누어 놓았을 때, Page_Load()의 패널.Visible=false로 설정되면,
페이지가 열릴 때, 해당 패널은 렌더링 되지 않는다.(-_ - 아놔..)
그래서 해당 패널에 동적으로 생성된 컨트롤이 존재 했다면 그 패널 컨테이너 안의 컨트롤은 FindControl()로 찾을 수가 없게 된다.

또 하나 중요한 것은. 웹 폼에서 포스트백 이후에는 변수의 값을 유지할 수가 없다.
그럴때에는 ViewState를 사용해서 값을 유지할 수 있으며, 정적 컨트롤 들은 내부적으로 ViewState를 사용하기 때문에 값이 유지된다. 하지만, 동적으로 생성된 컨트롤의 데이터는 ViewState에 저장이 되지만,
동적인 컨트롤 자체는 ViewState에 저장이 되지 않는다
. 즉 접근할 방법이 없어지므로,
FindControl()은 계속 null을 리턴하고, 접근이라도 할라치면 참조 오류가 나 버린다. 그러니 내가 알 리가 있나..

입력된 값을 가지고 동적으로 TextBox를 생성하고, 생성된 컨트롤로부터 값을 다시 얻어 합을 구한다고 가정.
먼저, 최초에 입력될 값을 보관할 ViewState를 설정한다.
이 설정은, 사용자로부터 값을 입력 받은 다음에 설정한다.

ViewState["TextBoxCount"] = nNumber; // ViewState로 생성된 TextBoxCount에 변수를 저장하여 보관.

다음으로 동적 할당할 TextBox Control을 코딩한 부분을 하나의 함수(메소드)로 묶어서 언제든지 호출 가능한 형태로 구분한다. 여기서는 DrawTextBox() 라고 가정하고, 간단하게 코딩하면 다음과 같다.

private void DrawTextBox()
{
 if(ViewState["TextBoxCount"] != null)               // null이 아니면 값이 할당되었다는 의미
 {
  nNumber = (int)ViewState["TextBoxCount"];     // 캐스팅 하여 본래 값을 복원
  for (int i=1; i<=nNumber; i++)
  {
   Literal li = new Literal();
   li.Text = "<br>" + i + "번째 텍스트 박스 : ";
   Panel2.Controls.Add(li);

   TextBox txt = new TextBox();
   txt.ID = "txt"+i.ToString();
   txt.Width = 80;
   Panel2.Controls.Add(txt);
  }
 }
}

이런식으로 하여 ViewState에 TextBox의 개수를 저장하고,
Page_Load 에서 ViewState 에 값이 있다면 매 페이지마다 다시 컨트롤을 추가해야 한다.

private void Page_Load(object sender, System.EventArgs e)
  {
      DrawTextBox();
  }

그러한 방법으로 TextBox의 값을 유지할 수 있게 된다.
3일동안 삽질했다. 아놔 -_ ㅜ

내 참, 캐스팅 때문에 또 이렇게 시간을 허비하다니.
문법을 다 배우는 게 너무 오랜 시간이 걸린다고 생각해서 간단한 거 하나 만들어 보자는 생각에,
무턱 대고 만들기 시작했는데 생각 외로 많은 문제들에 부딪힌다.
다음은 C#에서의 String Type to Integer Type 캐스팅

int nNumber = Convert.ToInt32(Text1.Text);

ToInt16은 short Type으로 변환되고 ToInt32는 int Type으로, ToInt64는 long Type으로 변환.
다른 Type으로도 변환이 가능한데 Convert의 메소드를 보면 알 수 있다.

주의 할 점이 있다.
String Type에서 Integer Type으로 변환시, 문자열이 정수로 변환할 문자열에 낑겨져 있다면 오류.
변환하기전에 숫자만이 입력 됐는지 체크를 하시던지 아니면 try를 걸어서 예외처리.