Title: Cliente%20Ligero%20en%20.NET%20Tema%204%20
1Cliente Ligero en .NETTema 4 ASP.NET
http//paginaspersonales.deusto.es/dipina/MasterIS
W/
- Dr. Diego Lz. de Ipiña Gz. de Artaza
- http//paginaspersonales.deusto.es/dipina
(Personal) - http//www.morelab.deusto.es (Research Group)
- http//www.smartlab.deusto.es (Research Lab)
- http//www.ctme.deusto.es (Cátedra de Telefónica
Móviles) - http//www.tecnologico.deusto.es
(Tecnológico-Fundación Deusto)
2ASP.NET
- Sucesor de Microsoft a la popular plataforma ASP
para el desarrollo de aplicaciones web - Configuración
- Atención Si no funciona, re-registrar ASP.NET
bajo IIS - aspnet_regiis.exe -i
3Ejemplo HTML simple.html
- lthtmlgt
- ltbodygt
- Hola mundo
- lt/bodygt
- lt/htmlgt
4Ejemplo Petición HTTP
- GET /simple.html HTTP/1.1
- Accept /
- Accept-Language en-us
- Accept-Encoding gzip, deflate
- If-Modified-Since Wed, 24 Oct 2001 141236 GMT
- If-None-Match "50b0d3ee955cc11a78"
- User-Agent Mozilla/4.0.(compatible MSIE.6.0
Windows NT 5.1) - Host www.wintellect.com
- Connection Keep-Alive
- blank line
5Ejemplo Respuesta HTTP
- HTTP/1.1 200 OK
- Server Microsoft-IIS/5.0
- Date Wed, 24 Oct 2001 141237 GMT
- Content-Type text/html
- Accept-Ranges bytes
- Last-Modified Wed, 24 Oct 2001 140053 GMT
- ETag "d02acf81975cc11a78"
- Content-Length 46
- blank line
- lthtmlgt
- ltbodygt
- Hola mundo
- lt/bodygt
- lt/htmlgt
6ASP.NET vs. ASP
- Active Server Pages (ASP) ofrecen un simple
modelo de programación en el que se puede
combinar código fuente y de marcado - Provee una serie de objetos prefabricados como
Request y Response - El código fuente se suele realizar normalmente
con VBScript, popular con programadores Visual
Basic. - Este código se coloca entre los delimitadores
lt y gt
7Ejemplo ASP
- lt!-- hello.asp --gt
- ltscript language"VBScript" runat"server"gt
- function buildForm()
- firstName Trim(Request.Form("firstName"))
- s ""
- if firstName "" then ' need a name...
- s s "What's Your First Name? "
- s s "ltinput type'text' name'firstName'
/gt" - s s "ltinput type'submit' /gt"
- else ' we know the user's name...
- s s "Hello, " firstName "!"
- end if
- buildForm s
- end function
- lt/scriptgt
- lthtmlgtltheadgtlttitlegtHello ASP Applt/titlegtlt/headgt
- ltbodygt
- lth1gtHello ASP Applicationlt/h1gt
8ASP.NET
- Los ficheros ASP.NET tienen extensión aspx.
- El código en un ASP.NET es muy similar al de ASP
con las siguientes diferencias - La lógica de la página está codificada en C o
VB.NET. El código es compilado cuando la petición
de la página es recibida y se cachea para ser
reutilizada - La directiva lt_at_Import Namespace...gt permite
importar espacios de nombres y utilizar el poder
de la framework .NET
9Ejemplo ASP.NET
- lt!-- hello.aspx --gt
- lt_at_ Page Language"C"gt
- lt_at_ Import Namespace"System.Web.UI"gt
- ltscript runat"server"gt
- private string buildForm()
- string firstName this.Request.Form"firstName"
- if (firstName null) firstName ""
- string s ""
- if (firstName.Trim() "") // need a name...
- s "What's Your First Name? "
- s "ltinput type'text' name'firstName'
/gt" - s "ltinput type'submit' /gt"
- else // we know the user's name...
- s "Hello, " this.Request.Form"firstName
" "!" -
- return s
-
- lt/scriptgt
10La clase System.Web.UI.Page
- En el anterior listado encontramos la línea
- string firstName this.Request.FormfirstName
- El this en esta sentencia es una referencia a una
instancia de System.Web.UI.Page, objeto que
representa a una página ASP.NET - Los objetos Request y Response de ASP son ahora
propiedades de la clase Page - El siguiente ejemplo muestra algunas de las
propiedades de Request
11Usando Page.Request y Page.Response I
- lt!-- dumpprops.aspx --gt
- lt_at_ Page Language"C" Debug"true"gt
- ltscript runat"server"gt
- private void dumpProps()
- // get Request and Response objects...
- HttpRequest req this.Request
- HttpResponse resp this.Response
- // and use them...
- resp.Write("Request.FilePath "
- req.FilePath "ltbr/gt")
- resp.Write("Request.PhysicalApplicationPath "
- req.PhysicalApplicationPath "ltbr/gt")
- resp.Write("Request.HttpMethod "
- req.HttpMethod "ltbr/gt")
- resp.Write("Request.UserAgent "
- req.UserAgent "ltbr/gt")
- resp.Write("Request.UserHostAddress "
- req.UserHostAddress "ltbr/gt")
12Usando Page.Request y Page.Response II
13Recuperando Datos de Formularios con Request
- Propiedades
- RequestType
- Usando GET recuperaríamos los datos de
QueryString - ControlValorControlValor
- Usando POST de la propiedad Form
- Request.Form"Direccion"
- La propiedad Params incluye además de los datos
de un formulario, las cookies y las variables del
servidor
14Formulario ASP.NET
- Un elemento FORM en el que no aparece ni action
ni method - Estos atributos son substituidos por
runat"server" - Indica que el motor ASP.NET debe procesar el
contenido del formulario - Controles aspTextBox, aspButton y similares
- Los formularios ASP.NET facilitan el desarrollo
de páginas dinámicas - Podemos acceder a los elementos del formulario
directamente (Nombre.Text), en vez de a través de
QueryString o Params.
15Ciclo de Vida del Objeto Page
- Cuando una petición HTTP es recibida ASP.NET
responde creando y devolviendo una página - Este proceso genera varios eventos
- La clase Page contiene varios métodos heredados
de System.Web.UI.Control que se pueden utilizar
para manejar estos eventos - OnInit ? inicialización requerida por la página
- OnLoad ? ejecuta acciones comunes a cada petición
HTTP de un página - OnPreRender ? para hacer cualquier cosa antes que
la página se visualice - OnUnload ? sirve para realizar tareas como
desconectarse de una base de datos cuando la
página se descarga
16Manejando Eventos de Página
- lt!-- pageevents.aspx --gt
- lt_at_ Page Language"C" Debug"true" gt
- ltscript runat"server"gt
- protected override void OnInit(EventArgs e)
base.OnInit(e) p("Init") - protected override void OnLoad(EventArgs e)
base.OnLoad(e) p("Load") - protected override void OnPreRender(EventArgs e)
base.OnPreRender(e) p("PreRender") - private void p(string s)
- Message.InnerHtml s "ltbrgt"
-
- lt/scriptgt
- lthtmlgtltheadgtlttitlegtHello Web Pagelt/titlegtlt/headgt
- ltbodygt
- lth1gtPage Events...lt/h1gt
- ltform action'pageevents.aspx' method'POST'gt
- ltspan id"Message" runat"server" /gt
- ltpgt
- ltinput type"submit" /gt
- lt/pgt
17Creando un Directorio Virtual I
- Creamos el directorio virtual ejemplosASP.NET
- Hacemos doble click en Herramientas
Administrativas - Doble click en Internet Information Services
18Creando un Directorio Virtual II
- Creamos el directorio virtual ejemplosASP.NET
- Hacemos clic con el botón derecho del ratón en
Default Web Site y luego seleccionamos
New?Virtual Directory - Seleccionamos el directorio donde vamos a dejar
los fichero accesibles por el contexto
ejemplosASP.NET
19Web Forms y Server Controls
- Un Web Form es un formulario con el atributo
runat"server" que hace que se procese en la
parte servidora - Un Server Control es un control que también tiene
el atributo runat"server" - Tanto los web forms como los server controls son
procesados en el servidor y generan HTML y
JavaScript que son enviados al navegador
20Ejemplo Web Form I
- lt!-- helloform.aspx --gt
- lt_at_ Page Language"C" Debug"true" gt
- ltscript runat"server"gt
- // greet the user...
- private void greetHandler(object sender,
EventArgs e) - firstNameTextBox.Text firstNameTextBox.Text.
Trim() - if (firstNameTextBox.Text "")
- // no name, so no greeting...
- greetingLabel.Text ""
- else
- // greet the user...
- greetingLabel.Text
- "Hello, " firstNameTextBox.Text "!"
-
-
- lt/scriptgt
21Ejemplo Web Form II
- lthtmlgtltheadgtlttitlegtHello Web Formlt/titlegtlt/headgt
- ltbodygt
- lth1gtHello Web Formlt/h1gt
- ltform action'helloform.aspx' method'POST'
runat'server'gt - ltasplabel text"What's Your First Name?"
runat"server"/gt - ltasptextbox id"firstNameTextBox"
runat"server"/gt - ltaspbutton
- id"greetButton"
- text"Greet"
- OnClick"greetHandler"
- runat"server"/gt
- ltpgtltasplabel id"greetingLabel"
runat"server"/gtlt/pgt - lt/formgt
- lt/bodygt
- lt/htmlgt
22Ejemplo Web Form III
- Puntos de interés
- Declaración del formulario mediante ltform
runat"server"/gt - En vez de usar HTML usamos etiquetas asp como
ltaspcontrol-type runat"server"/gt - Estas etiquetas corresponden a los controles de
la parte servidora - Se transforman en HTML por ASP.NET
23Ejemplo Web Form IV
24Ejemplo Web Form V
- Los controles del servidor preservan su valor a
través de peticiones HTTP - Lo hacen guardando las propiedades en un variable
de nombre __VIEWSTATE - El valor de __VIEWSTATE es una cadena de
caracteres codificada en base-64. - Los controles generan eventos que pueden ser
tratados por handlers. Por ejemplo - ltaspbutton idgreetButton
- textGreet
- OnClickgreetHandler
- runatserver/gt
- El manejador de eventos tiene una firma similar
al equivalente en Windows Forms - private void greetHandler(object sender,
EventArgs e) -
-
- Podemos sobrescribir el método OnLoad y también
usar el enfoque delegate - protected override void OnLoad(EventArgs e)
- base.OnLoad(e)
- // uso del delegate
- greetButton.Click new EventHandler(greetHandle
r) -
25Codificación Base 64
- Subconjunto de 64 caracteres ASCII que permiten a
grupos de 6 bits ser representados por un
carácter - El proceso de codificación representa grupos de
24 bits de entrada (3 bytes de entrada) como un
string de salida con 4 bytes de salida (26) - Referencia http//en.wikipedia.org/wiki/Base64
26System.Web.UI.WebControls y System.Web.UI.HtmlCont
rols
- El espacio de nombres System.Web.UI.WebControls
define un montón de controles, entre ellos - Button
- Calendar
- CheckBoxList
- DataGrid
- DataList
- DropDownList
- Label
- Panel
- Etc.
- En System.UI.HtmlControls se definen una serie de
controles como HtmlAnchor y HtmlTable que definen
una correspondencia uno-a-uno con la etiqueta
HTML equivalente, p.e., HtmlAnchor y HtmlTable
27System.Web.UI.WebControls y System.Web.UI.HtmlCont
rols
- Al insertar usando el Toolbox de Visual
Studio.NET controles HTML obtenemos - ltinput typetext/gt
- ltinput typecheckbox/gt
- ltinput typebutton valueButton/gt
- Al insertar web controls obtenemos
- ltaspTextBox idTextBox1 runatservergt
- lt/aspTextBoxgt
- ltaspCheckBox idCheckBox1 runatservergt
- lt/aspCheckBoxgt
- ltaspButton idButton1 runatservergt
- lt/aspButtongt
28Propiedades Interesantes de los WebControls
- Estilo Visual
- Height y Width
- Backcolor y ForeColor
- BorderColor, BorderStyle y BorderWidth
- Propiedades de comportamiento
- Enabled
- Visible
- AccessKey
- TabIndex
- ReadOnly
- Generación de Eventos
- AutoPostBack
- Indica si el control ha de producir
automáticamente una nueva solicitud al servidor
29Mantenimiento de Estado en Controles
- La propiedad EnableViewState determina si un
control ASP.NET debe mantener su estado entre
solicitudes - Su valor por defecto es True
- El campo oculto __VIEWSTATE es el mecanismo
utilizado por ASP.NET para conservar estado
30Usando el Control Calendar
- lt!-- calendarform.aspx.aspx --gt
- lt_at_ Page Language"C" Debug"true" gt
- ltscript runatservergt
- private void dateHandler(object sender,
EventArgs e) - myMessage.Text
- "You selected " myCalendar.SelectedDate.To
ShortDateString() -
- lt/scriptgt
- lthtmlgtltheadgtlttitlegtCalendar ASP.NET
Applt/titlegtlt/headgt - ltbodygt
- lth1gtCalendar ASP.NET Applicationlt/h1gt
- ltform runat"server"gt
- ltaspcalendar
- id"myCalendar"
- onSelectionChanged"dateHandler"
- Font-Name"Verdana"
- Font-Size"8pt"
- Font-Bold"true"
31Usando el Control Calendar
32Usando el Control DataGrid I
- lt!-- dataformexample.aspx --gt
- lt_at_ Page Language"C" gt
- lt_at_ Import Namespace"System.Data" gt
- lt_at_ Import Namespace"System.Data.SqlClient" gt
- ltscript runat"server"gt
- protected override void OnLoad(EventArgs e)
- base.OnLoad(e)
- SqlConnection con new SqlConnection("serverlts
erver-namegtdatabasepubsuidsapwdltpasswordgt")
- SqlDataAdapter com
- new SqlDataAdapter("select from titles",
con) - DataSet ds new DataSet()
- com.Fill(ds, "titles")
- titlesGrid.DataSourceds.Tables"titles".Defaul
tView - titlesGrid.DataBind()
33Usando el Control DataGrid II
- lthtmlgtltheadgtlttitlegtDataGrid ASP.NET
Applt/titlegtlt/headgt - ltbodygt
- lth1gtDataGrid ASP.NET Applicationlt/h1gt
- ltform runat"server"gt
- ltaspdataGrid
- id"titlesGrid"
- BackColor"Gainsboro"
- BorderColor"black"
- CellPadding"10"
- CellSpacing"0"
- Font-Name"Verdana"
- Font-Size"8pt"
- Font-Bold"true"
- HeaderStyle-BackColor"lightGreen"
- EnableViewState"false"
- runat"server" /gt
- lt/formgt
- lt/bodygt
- lt/htmlgt
34Usando el Control DataGrid III
- ltaspdataGrid /gt visualiza el DataGrid en el
formulario - Para cargar datos en el grid, usamos su propiedad
DataSource y le asociamos datos invocando a
DataBind() - DataGrid soporta paginamiento
- PageSize indica el número de filas a visualizar
por página - AllowPaging sirve para visualizar botones
Previous and Next en la página
35Usando el Control DataGrid III
36Usando DataGrid IV
- Una pregunta frecuente suele ser cómo añadir un
hiperlink a una de las celdas de un DataGrid - http//msdn.microsoft.com/library/default.asp?url
/library/en-us/vbcon/html/vbtskaddinghyperlinkcolu
mnstodatagridwebcontrol.asp
37Usando DataGrid V
- lt_at_ Page language"c" Codebehind"WebForm1.aspx.c
s" AutoEventWireup"false" Inherits"DataGridWithH
yperlink.WebForm1" gt - lt!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0
Transitional//EN" gt - ltHTMLgt
- ltHEADgt
- lttitle gtWebForm1lt/titlegt
- ltmeta content"Microsoft Visual Studio .NET
7.1" name"GENERATOR"gt - ltmeta content"C" name"CODE_LANGUAGE"gt
- ltmeta content"JavaScript" name"vs_defaultCli
entScript"gt - ltmeta content"http//schemas.microsoft.com/in
tellisense/ie5" name"vs_targetSchema"gt - lt/HEADgt
- ltbody MS_POSITIONING"GridLayout"gt
- ltform id"Form1" method"post"
runat"server"gt - ltaspDataGrid id"DataGrid1"
style"Z-INDEX 101 LEFT 192px POSITION
absolute TOP 104px - runat"server" DataSource"lt
TitlesDataSet gt" AutoGenerateColumns"False"gt - ltColumnsgt
- ltaspHyperLinkColumn DataTextField"title_id
" HeaderText"title_id" - NavigateUrl"http//paginaspersonales
.deusto.es/dipina"gtlt/aspHyperLinkColumngt - ltaspBoundColumn DataField"title"
SortExpression"title" HeaderText"title"gtlt/aspBo
undColumngt - ltaspBoundColumn DataField"type"
SortExpression"type" HeaderText"type"gtlt/aspBoun
dColumngt
38Usando el control HtmlTable I
- lt!-- tableform.aspx --gt
- lt_at_ Page Language"C" Debug"true" gt
- lt_at_ Import Namespace"System"gt
- lt_at_ Import Namespace"System.Web.UI"gt
- ltscript runat"server"gt
- protected override void OnLoad(EventArgs e)
- base.OnLoad(e)
- int cellNum 0
- if (IsPostBack) // falso cuando el formulario
se crea por primera vez - try
- cellNum Int32.Parse(cellTextBox.Text)
- catch (Exception)
- cellNum 0 // don't highlight any cell
-
-
- int rows 3, cols 3, num 0
- for (int i 0 i lt rows i)
- HtmlTableRow htmlRow new HtmlTableRow()
- for (int j 0 j lt cols j)
39Usando el control HtmlTable II
- lthtmlgtltheadgtlttitlegtHtmlTable Examplelt/titlegtlt/head
gt - ltbodygt
- lth1gtHtmlTable Examplelt/h1gt
- ltform runat"server"gt
- lttable
- id"myTable"
- border"1"
- cellPadding"10"
- cellSpacing"1"
- runat"server" /gt
- ltpgt
- Cell
- ltasptextbox
- id"cellTextBox"
- columns"1"
- maxLength"1"
- runat"server"/gt
- ltbrgt
- ltinput
40Usando el control HtmlTable I
- La propiedad de una página IsPostBack es falsa
cuando un formulario se carga por primera vez - Obsérvese cómo programáticamente podemos ir
creando la tabla - HtmlTable
- HtmlRow
- HtmlCell
41Controles de Usuario
- Podemos crear tres tipos de controles
- Pagelets
- Fragmentos de código HTML que pueden reutilizarse
como si de componentes se tratara - Controles simples
- Derivados de System.Web.UI.Control
- Controles compuestos
- Reutilizan uno o más controles ya existentes
- Los especializan
42Creación de Pagelets
- Es un conjunto de marcas HTML alojadas en un
archivo independiente y que se pueden reutilizar - Podemos personalizar ese contenido a través de
propiedades - Se alojan en ficheros con extensión .ascx
- Contienen marcado
- ltbr/gt
- ltpgtDistributed.NETlt/pgt
- Tendremos que registrar este fragmento, le damos
un nombre y le asociamos un prefijo, en todos los
.aspx donde queramos utilizar este control - lt_at_ Register TagPrefix"DN"
- TagNameFirma
- SrcFirma.ascx" gt
43Creación de Pagelets
- lt_at_ Register TagPrefix"DN"
- TagName "Firma"
- Src "Firma.ascx gt
- Si en lugar de tener un archivo .ascx, tuviéramos
un control alojado en un ensamblado,
substituiríamos src por Assembly - Después podríamos incluir el pagelet en cualquier
otra página utilizando - ltDNFirma id"Firma1" runat"server" gtlt/DNFirmagt
- runat"server" lo identifica como control del
servidor, ASP.NET lo substituirá por el código
asociado
44Pagelets con propiedades
- Cómo personalizar un pagelet?
- Tan sencillo como declarar variables públicas
- Ejemplo
- ltscript language"C" runat"server"gt
- public string BackgroundColor"white"
- public int BorderWidth 1
- public string Text"Distributed.NET"
- lt/scriptgt
- ltdiv style"clear left background-color
ltBackgroundColorgt border solid
ltBorderWidthgtpx"gt - ltp style"text-align center"gtltTextgtlt/pgt
- lt/divgt
45Pagelets con propiedades
- A continuación incluiríamos el siguiente
fragmento en el .aspx donde incluir esta cabecera - lt_at_ Register TagPrefix"DN"
- TagName "Cabecera"
- Src "Cabecera.ascx" gt
- Y en el código del .aspx podríamos crear entradas
como - ltDNCabecera id"Pie" runat"server"
BorderWidth"3" Text"Pie de página"gtlt/DNCabecera
gt - Revisar ejemplo en examples\asp.net\SecurityExampl
e
46Creando Controles Web de Usuario con Pagelets
- Permite encapsular dos o más elementos de
interfaz en un control reusable - Podemos incluso reutilizar formularios web en
controles de usuario - Podemos ensamblar formularios agrupando
componentes personalizados reutilizables - Pasos conversión web form -gt user control
- Guardar el formulario con extensión .ascx
- Eliminar todas las sentencias lthtmlgt, ltheadgt,
lttitlegt, ltbodygt o ltformgt
47Usercolor.ascx I
- lt!-- usercolor.ascx --gt
- ltscript language"C" runat"server"gt
- public string Color
- get
- if (colorTextBox.Text "") return
"white" - return colorTextBox.Text
-
-
- public bool Visible
- get
- return colorPanel.Visible
-
- set
- colorPanel.Visible value
-
-
48Usercolor.ascx II
- ltasppanel id"colorPanel" visible"false"
runat"server"gt - ltasplabel
- Font-Name"Verdana"
- Font-Size"7pt"
- text"Color "
- runat"server"/gt
- ltasptextbox
- Font-Name"Verdana"
- Font-Size"7pt"
- columns"10"
- id"colorTextBox"
- runat"server"/gt
- lt/asppanelgt
49Usercolor.ascx III
- Este control está compuesto de una label y una
textbox, contenidas dentro de un Panel. - Definimos dos propiedades públicas para el
control Color y Visible. - Para localizar el control en un formulario
debemos incluir - lt_at_ Page Language"C" Debug"true" gt
- lt_at_ Register
- TagPrefix"userColors"
- TagName"userColor"
- Src"usercolor.ascx" gt
- Para usar el control hacemos
- ltuserColorsuserColor id"userColorControl"
runat"server"/gt
50Colorform.aspx I
- lt_at_ Page Language"C" Debug"true" gt
- lt_at_ Register
- TagPrefix"userColors"
- TagName"userColor"
- Src"usercolor.ascx" gt
- ltscript runat"server"gt
- protected override void OnLoad(EventArgs e)
- base.OnLoad(e)
- body.Attributes"bgcolor"
userColorControl.Color - userColorControl.Visible !userColorControl.V
isible -
- lt/scriptgt
- lthtmlgtltheadgtlttitlegtThe UserColor
Controllt/titlegtlt/headgt - ltbody id"body" runat"server"gt
- lth1gtThe UserColor Controllt/h1gt
- ltform runat'server'gt
- ltuserColorsuserColor id"userColorControl"
runat"server"/gt - ltpgt
- This form uses the UserColor user
control.
51Colorform.aspx II
52Custom Controls
- Se diferencian de los controles de usuario en que
su código se aloja ya compilado en un ensamblado
de tipo DLL - Usamos la opción de proyecto Web Control Library
de Visual Studio.NET para crear un
WebControlLibrary1 - A continuación añadimos el proyecto
WebApplicationUsingCustomControl - Podemos utilizar la paleta de controles para
añadir el custom control creado - Lo mejor es heredar nuestros controles de clases
que derivan de System.Web.UI.Control como
System.Web.UI.WebControls.WebControl
53Custom Control Cabecera de nuevo
- Podemos o bien reimplementar el método Render()
de WebControl que renderiza el contenido de un
control - O mejor redefinir los métodos
- AddAttributesToRender() ? agrega nuevos
contenidos y atributos - RenderContents() ? invoca a la implementación
base de Render
54Creando un Control Compuesto con Código
- No genera su interfaz, se basa en otros controles
ya existentes - Los controles se añaden al control de usuario en
el método CreateChildControls()
55Creando un Control Compuesto con Código
- public class WebCustomControl1 Control,
INamingContainer -
- private TextBox euros, pesetas
- protected override void CreateChildControls()
-
- this.euros new TextBox()
- this.pesetas new TextBox()
-
- euros.Text "0"
- euros.AutoPostBack true
- euros.TextChanged new EventHandler(Euros_Te
xtChanged) - pesetas.Text "0"
- pesetas.AutoPostBack true
- pesetas.TextChanged new EventHandler(Peseta
s_TextChanged) - this.Controls.Add(this.euros)
- this.Controls.Add(new LiteralControl("ltbr/gt")
) - this.Controls.Add(this.pesetas)
56Validando la Entrada de Datos
- La plataforma Web Forms provee una selección de
controles de validación que sirven para - Validar la entrada de datos
- Mostrar mensajes de error al usuario
- Todos los controles de validación agregados a una
página ASP.NET pasan a formar parte de la
colección Validators, que es de sólo lectura - ValidatorCollection es el tipo de la colección
- Los validadores derivan todos de BaseValidator
- Para poner en marcha la validación se invoca el
método Validate() de Page - De manera directa
- A través de los controles con la propiedad
CausesValidation
57Validando la Entrada de Datos
- Los controles de validación proporcionados son
- RequiredFieldValidator
- CompareValidator ? compara una entrada con un
valor o la propiedad de otro control - RangeValidator ? entrada en un rango de valores
- RegularExpressionValidator ? requiere que una
entrada se corresponda con una expresión regular - CustomValidator ? validación propietaria
codificada por usuario - ValidationSummary ? muestra un resumen de errores
de validación para todos los controles de
validación en una página
58Validando la Edad I
- lt!-- ageform.aspx --gt
- lt_at_ Page Language"C" Debug"true" gt
- ltscript runat"server"gt
- private void ageHandler(object sender,
EventArgs e) - if (IsValid)
- ageLabel.Text "You are "
ageTextBox.Text " years old." - else
- ageLabel.Text "Please Enter Your Age."
-
- lt/scriptgt
- lthtmlgtltheadgtlttitlegtValidating a User's
Agelt/titlegtlt/headgtltbodygt - ltform runat'server'gt
- lth1gtValidating a User's Agelt/h1gt
- ltasplabel text"Age " runat"server"/gt
- ltasptextbox
- id"ageTextBox"
59Validando la Edad II
- lt!-- require an entry... --gt
- ltasprequiredFieldValidator
- controlToValidate"ageTextBox"
- errorMessage"Age required"
- enableClientScript"true"
- display"static"
- runatserver /gtltbr/gt
- lt!-- must be an integer... --gt
- ltaspregularExpressionValidator
- controlToValidate"ageTextBox"
- errorMessage"Age must be an integer"
- enableClientScript"true"
- display"static"
- validationExpression"\d1,3"
- runat"server" /gtltbr/gt
- lt!-- must be aged between 1 and 120 years...
--gt - ltasprangeValidator
- controlToValidate"ageTextBox"
- errorMessage"Age must be between 1 and 120
years"
60Validando la Edad III
- Los controles utilizados tienen las siguientes
propiedades en común - controlToValidate ? especifica el control a
validar (ageTextBox) - errorMessage ? el texto de error a visualizar
- enableClientScript ? genera JavaScript si el
cliente lo permite - display ? los controles de validación son
invisibles por defecto, static crea espacio para
visualizar el error - Si cualquier validación es falsa asigna el valor
false a IsValid.
61Validaciones Complejas
- Mediante RegularExpressionValidator y
CustomValidator - RegularExpressionValidator tiene la propiedad
ValidationExpression donde colocaremos una
expresión regular - Podemos crear nuestra propia función de
validación con CustomValidator - Habrá que codificarla en JavaScript y añadirla
como un elemento script de HTML - Propiedad esencial ClientValidationFunction
62Validaciones Complejas
- ltscriptgt
- //Función de validación a medida
- function VerificaMeses(source, arguments)
-
- if (arguments.Value gt 6
- arguments.Value lt24
- arguments.Value6 0)
- arguments.IsValid true
- else
- arguments.IsValid false
63Configurando y Customizando las aplicaciones
ASP.NET I
- ASP.NET provee un sistema de configuración
jerárquico que permite a un administrador definir
datos de configuración en los siguientes niveles
a través del fichero Web.config - Aplicación
- Sitio
- Nivel de máquina
- Dentro de ASP.NET se pueden especificar ficheros
de configuración en subdirectorios - El sistema de configuración de ASP.NET es parte
de la infraestructura de configuración global de
.NET. Para configurar http//server/app/dir/page.
aspx, se aplican las configuraciones en el
siguiente orden - C\WINNT\Microsoft.NET\Framework\ltversióngt\CONFIG\
machine.config para la máquina - C\Inetpub\wwwroot\web.config ? para el sitio
- C\app\web.config ? configuraciones específicas
de la aplicación - C\app\dir\web.config ? configuraciones
específicas del subdirectorio
64Configurando y Customizando las aplicaciones
ASP.NET II
- Las siguientes configuraciones son posibles
- Instalación de manejadores de HTTP ISAPI
- Implementar seguridad y login
- Especificar timeout de sesión
- Soportar LOCALEs alternativos
- Configurar el debugeo de aplicaciones
65Creando un Módulo HTTP Propietario I
- Antes de que una petición sea procesada por un
ASP.NET es posible pre-procesarla por medio de
un módulo HTTP - Para crear un módulo HTTP propietario lo
siguiente es necesario - Crear una clase que implemente los métodos
definidos por la interfaz IHttpModule, compilarla
y dejarla en el directorio bin de la aplicación
web - Init recibe como argumento un HttpApplication
que define los siguientes eventos - BeginRequest
- AcquireRequestState
- EndRequest
- Dispose se puede eliminar información aquí
- Para instalarlo hay que añadir una entrada a la
sección httpmodules al web.config - ltconfigurationgt
- ltsystem.webgt
- lthttpModulesgt
- ltadd name"Request Counter Module"
- type"CustHttpModules.RequestCounter
Module, custhttpmodules"/gt - lt/httpModulesgt
- lt/system.webgt
- lt/configurationgt
66Creando un Módulo HTTP Propietario II
- // file custhttpmodules.cs
- // compile csc /tlibrary custhttpmodules.cs
- using System
- using System.Web
- using System.Web.SessionState
- namespace CustHttpModules
- public class RequestCounterModule IHttpModule
- public void Init(HttpApplication ha)
- ha.AcquireRequestState new
EventHandler(gotState) -
- public void Dispose()
- // perform any necessary cleanup here
-
- private void gotState(object sender,
EventArgs e) - HttpApplication ha (HttpApplication)sender
- HttpSessionState s ha.Session
- if (s"numRequests" null)
- s"numRequests" 1
67Creando un Módulo HTTP Propietario III
- lt!-- dumpreqs.aspx --gt
- lt_at_ Page Language"C" Debug"true"gt
- ltscript runat"server"gt
- private void dumpReqs()
- string s "Number of Requests "
Session"numRequests" - Response.Write(s)
-
- lt/scriptgt
- lthtmlgtltheadgtlttitlegtHTTP Request
Countlt/titlegtlt/headgt - ltbodygt
- lth1gtHTTP Request Countlt/h1gt
- lt dumpReqs() gt
- lt/bodygt
- lt/htmlgt
68Creando un Módulo HTTP Propietario IV
69Creando un Manejador HTTP I
- A diferencia de un módulo HTTP, un HTTP handler
está diseñado para procesar la petición
completamente, y devolver un resultado al
navegador - Información extra sobre HTTP Modules y Handlers
puede encontrarse en http//support.microsoft.com
/default.aspx?scidkbEN-US3079852 - Necesario crear una clase que implementa la
interfaz IHttpHander - Para instalar el HttpHandler usar las siguientes
sentencias en el web.config - ltconfigurationgt
- ltsystem.webgt
- lthttpHandlersgt
- ltadd verb"" path"hellohandler.aspx"
type"CustomHttpHandlers.HelloHandler,
custhttphandlers" /gt - lt/httpHandlersgt
- lt/system.webgt
- lt/configurationgt
70Creando un Manejador HTTP II
- // file custhttphandlers.cs
- // compile csc /tlibrary custhttphandlers.cs
- using System.Web
- namespace CustomHttpHandlers
- public class HelloHandler IHttpHandler
- public void ProcessRequest(HttpContext hc)
- hc.Response.Write("Hello, World!")
-
- public bool IsReusable
- get
- return true
-
-
-
71Creando un Manejador HTTP III
72Haciendo Debugging de Aplicaciones ASP.NET
- Para encontrar problemas en el código de un
ASP.NET, éste ofrece dos niveles de testeo - Page-level tracing
- Utiliza la siguiente directiva lt_at_ Page
LanguageC Tracetruegt - Para insertar tus propios fragmentos de trace
usar las sentencias - Trace.Write y Trace.Warn
- Application-level tracing, modificando web.config
73Tracing a Nivel de Página I
- lt!-- traceform.aspx --gt
- lt_at_ Page Language"C" Trace"True" gt
- ltscript runat"server"gt
- // greet the user...
- private void greetHandler(object sender,
EventArgs e) - Trace.Warn(" Entering greetHandler ")
- firstNameTextBox.Text firstNameTextBox.Text.
Trim() - Trace.Warn(" First Name '"
- firstNameTextBox.Text "' ")
- if (firstNameTextBox.Text "")
- // no name, so no greeting...
- greetingLabel.Text ""
- Trace.Warn(" No greeting ")
- else
- // greet the user...
74Tracing a Nivel de Página II
- lthtmlgtltheadgtlttitlegtHello Web Formlt/titlegtlt/headgt
- ltbodygt
- lth1gtHello Web Formlt/h1gt
- ltform action'helloform.aspx' method'POST'
runat'server'gt - ltasplabel text"What's Your First Name?"
runat"server"/gt - ltasptextbox id"firstNameTextBox"
runat"server"/gt - ltaspbutton
- id"greetButton"
- text"Greet"
- OnClick"greetHandler"
- runat"server"/gt
- ltpgtltasplabel id"greetingLabel"
runat"server"/gtlt/pgt - lt/formgt
- lt/bodygt
- lt/htmlgt
75Tracing a Nivel de Página III
76Tracing a Nivel de Aplicación I
- ltconfigurationgt
- ltsystem.webgt
- lttrace enabled"true"
- localOnly"true
- pageOutput"false
- requestLimit"10
- traceMode"SortByTime"/gt
- lt/system.webgt
- lt/configurationgt
- enabled ? para activar/desactivar el tracing
- localOnly ? hacer tracing sólo en localhost
- pageOutput ? true si se pone la información de
debugging al final de cada página, o en false en
el fichero trace.axd - requestLimit ? cuántos traces de peticiones a
guardar - traceMode ? si se ordenan por tiempo (SortByTime)
o categoría (SortByCategory)
77Objetos principales de una aplicación ASP.NET
- Response (HttpResponse)
- Write()
- WriteFile()
- BinaryWrite()
- Redirect()
- Request (HttpRequest)
- Request y Response tienen la propiedad Cookies
que es una colección - QueryString
- ServerVariables
- Files ? ficheros enviados desde el cliente (file
uploads) - BinaryRead()
- SaveAs()
- Application (HttpApplicationState)
- Session (HttpSession)
78Estado de Aplicación en Global.Asax
- Los objetos de aplicación son compartidos por
todas las sesiones y viven la duración completa
de una aplicación - Se crean e inicializan en el fichero global.asax
- La principal ventaja de los objetos a nivel de
aplicación es que una vez que ocurre la primera
petición, todas las aplicaciones tienen acceso al
objeto - Como puede haber acceso concurrente a los datos,
si hay necesidad de cambiarlos hay que usar
Locks - Application.Lock()
- ApplicationsomeVar someVal
- Application.UnLock()
79Global.Asax
- lt_at_ Import Namespace"System.Data" gt
- lt_at_ Import Namespace"System.Data.SqlClient" gt
- ltscript language"C" runat"server"gt
- // global.asax methods...
- private void Application_Start(object sender,
EventArgs e) - SqlConnection con
- new SqlConnection("serverltserver-namegtdatabase
pubsuidsapwdltpasswordgt") -
- string sql
- SqlDataAdapter com
- DataSet ds new DataSet()
- sql "SELECT COUNT() from titles"
- com new SqlDataAdapter(sql, con)
- com.Fill(ds, "NumTitles")
80dumpTitles.aspx I
- lt!-- dumptitles.aspx --gt
- lt_at_ Page Language"C" Debug"true"gt
- ltscript runat"server"gt
- private void dumpTitles()
- string s "Num Titles "
Application"NumTitles" "ltbr/gt" - Response.Write(s)
-
- lt/scriptgt
- lthtmlgtltheadgtlttitlegtApplication Statelt/titlegtlt/head
gt - ltbodygt
- lth1gtApplication Statelt/h1gt
- lt dumpTitles() gt
- lt/bodygt
- lt/htmlgt
81dumpTitles.aspx II
82Gestionando la Sesión I
- Session es una propiedad pública de
System.Web.UI.Page y System.Web.Services.WebServic
e - Guardamos y recuperamos estado de sesión como
sigue - int numRequests (int)SessionnumRequests
- ...
- SessionnumRequests numRequests
- Una sesión comienza cuando un usuario visita la
aplicación y acaba cuando la sesión expira
83Gestionando la Sesión II
- ltconfigurationgt
- ltsystem.webgt
- ltsessionState modeInProc
- cookielesstrue
- timeout20
- stateConnectionString
- sqlConnectionString/gt
- lt/system.webgt
- lt/configurationgt
- El significado de estos atributos es el
siguiente - mode ? Off para no permitir sesiones, InProc para
guardar la información de sesión en el mismo
proceso, StateServer remotamente o SqlServer en
una BD - cookieless ? true para sesiones sin cookies,
añadiría identificador de usuario a URL - timeout ? minutos que una sesión estará inactiva
hasta que es abandonada - stateConnectionString ? por ejemplo
127.0.0.142424 - sqlConnectionString ? el string de conexión de
SQL Server
84Ejemplo Redirect y Session
- Login.aspx
- void Page Load(object sender, EventArgs e)
- if (IsPostBack)
- SessionNombre Nombre.Text
- SessionDirección Direccion.Text
- Response.Redirect(Confirmation.aspx)
-
-
- Confirmation.aspx
- void Page Load(object sender, EventArgs e)
- Response.Write(Activar subscripción
SessionNombre)
85Usando Visual Studio 2005
- Vamos a crear una aplicación web que codifica
strings a Base64 - Lanza Visual Studio.NET y selecciona
FileNewProject Visual C Projects ? ASP.NET
Web Application - Llama a la aplicación BAse64App
- Automáticamente se crea un Directorio Virtual y
se colocarán los ficheros en c\InetPub\wwwroot\Ba
se64App
86Usando Visual Studio 2005
- Visual Studio.NET separa el formulario web y el
código detrás del formulario - Lo hace a través del atributo CodeBehind
- lt_at_ Page language"c" Codebehind"WebForm1.aspx.c
s" AutoEventWireup"false" Inherits"Base64App.Web
Form1" gt - Usamos la ToolBox para generar un formulario como
el que aparece en la siguiente figura - Crea un fichero de configuración especial
denominado Web.config
87Usando Visual Studio.NET III
88Usando Visual Studio.NET IV
- private void EncodeButton_Click(object sender,
System.EventArgs e) -
- if (base64TextBox.Text "")
-
- this.EncodedLabel.Text ""
-
- else
-
- System.Text.ASCIIEncoding ascii new
System.Text.ASCIIEncoding() - byte b ascii.GetBytes((string)base64Text
Box.Text) - this.EncodedLabel.Text "ENCODED "
Convert.ToBase64String(b) -
-
- private void DecodeButton_Click(object sender,
System.EventArgs e) -
- if (base64TextBox.Text "")
-
- this.DecodedLabel.Text ""
89Usando Visual Studio.NET V
90Creando Manualmente Formularios con Code Behind I
- lt!-- behindform.aspx --gt
- lt_at_ Page Language"C" Inherits"BehindForm"
Src"behindform.cs" gt - lthtmlgtltheadgtlttitlegtHello Web Formlt/titlegtlt/headgt
- ltbodygt
- lth1gtHello Web Form (Code-Behind Version)lt/h1gt
- ltform action'behindform.aspx' method'POST'
runat'server'gt - ltasplabel text"What's Your First Name?"
runat"server"/gt - ltasptextbox id"firstNameTextBox"
runat"server"/gt - ltaspbutton
- id"greetButton"
- text"Greet"
- OnClick"greetHandler"
- runat"server"/gt
- ltpgt
- ltasplabel id"greetingLabel" runat"server"/gt
- lt/pgt
91Creando Manualmente Formularios con Code Behind II
- // file behindform.cs
- using System
- using System.Web.UI
- using System.Web.UI.WebControls
- public class BehindForm Page
- protected TextBox firstNameTextBox
- protected Label greetingLabel
- // greet the user...
- protected void greetHandler(object sender,
EventArgs e) - firstNameTextBox.Text firstNameTextBox.Text.
Trim() - if (firstNameTextBox.Text "")
- // no name, so no greeting...
- greetingLabel.Text ""
- else
- // greet the user...
92Creando Manualmente Formularios con Code Behind
III
93Creando gráficos on-the-fly
- lt_at_ Page Language"C" gt
- lt_at_ Import Namespace"System.Drawing" gt
- lt_at_ Import Namespace"System.Drawing.Imaging" gt
- ltscript runat"server"gt
- void Page_Load(object sender, EventArgs e)
-
- // Creamos el bitmap y obtenemos el objeto
Graphics asociado - Bitmap Grafico new Bitmap(400, 200,
PixelFormat.Format32bppRgb) - Graphics Superficie Graphics.FromImage(Grafico
) -
- // Dibujamos un rectángulo, un óvalo y un texto
sobre él - Superficie.FillRectangle(Brushes.Red,
Superficie.ClipBounds) - Superficie.FillEllipse(Brushes.Blue, 10, 10,
380, 180) - Superficie.DrawString("Distributed.NET", new
Font("Courier New", 18, FontStyle.ItalicFontStyle
.Bold), Brushes.White, 20, 80) -
- // Lo pasamos como respuesta
- Grafico.Save(Response.OutputStream,
ImageFormat.Jpeg) -
- lt/scriptgt
94Creando gráficos on-the-fly
95Ejemplo ASP.NET con ADO.NET(Access)
- // examples\ADOAccessASPX
- public class WebForm1 System.Web.UI.Page
-
- private void Page_Load(object sender,
System.EventArgs e) -
- OleDbConnection conexion new
OleDbConnection("ProviderMicrosoft.Jet.OLEDB.4.0
""Data SourceF\\Deusto\\Distributed.NET\\exam
ples\\ado.net\\pubs.mdb") - OleDbCommand comando new
OleDbCommand("SELECT FROM TITLES", conexion) - OleDbDataAdapter adaptador new
OleDbDataAdapter(comando) - DataSet conjunto new DataSet()
- adaptador.Fill(conjunto, "Publicaciones")
- Response.Write("Hay " conjunto.Tables"Pub
licaciones".Rows.Count " filasltbr/gt") - foreach (DataRow fila in conjunto.Tables"Pu
blicaciones".Rows) -
- Response.Write(fila"title_id" " - "
fila"title" "ltbr/gt") -
-
96Componentes ASP específicos de Datos
- Cualquier control puede tomar valores de un BBDD
mediante la expresión - ltaspcontrol propiedad'lt expresion gt'gt
- ltaspcontrolgt
- Otros controles más sofisticados tienen la
propiedad DataBindings - Vamos a extender el ejemplo anterior para
rellenar una Label con valores de una BBDD - Es necesario invocar al método DataBind() de Page
- Colocar un Label con la ayuda de Visual
Studio.NET y asociar a la propiedad DataBindings,
la expresión - Conjunto.Tables"Publicaciones".Rows0."Titulo"
97Listas, cuadrículas y plantillas
- Vamos a ver como asociar fuentes de datos a
controles con capacidad para visualizar múltiples
filas - ListBox
- DropDownList
- CheckBoxList
- DataGrid
- Repeater
- DataList
- A través de las propiedades DataSource y
DataMember podemos asociar una tabla o vista - ListBox, DropDownList y CheckBoxList asocian los
valores de una misma columna en distintas filas - Tienen las propiedades DataTextField y
DataValueField - Repeater y DataList se basan en la repetición de
plantillas de elementos - ltItemTemplategtlt DataBinder.Eval(Container.DataIt
em, "Title") gtlt/ItemTemplategt
98Paginación
- Los controles Repeater y DataList no ofrecen
paginación de serie - Se debe implementar bien manualmente o a través
del componente PagedDataSource - El control DataGrid se apoya en PagedDataSource
para automatizar la paginación - Dando True a AllowPaging activamos la paginación
- Debemos gestionar el evento PageIndexChanged,
donde asociaremos el DataGrid al origen de datos
99Seguridad en ASP.NET
- Intervienen 3 níveles
- La comunicación entre un navegador y el motor
ASP.NET se produce a través de un servidor web,
IIS - El primer nivel de seguridad radica en el
filtrado de peticiones que se puede efectuar por
el IIS - El segundo escalón de seguridad es el impuesto
por ASP.NET - La información de seguridad global y local se
guarda en los ficheros Web.config - El tercer nivel de seguridad viene dado por NTFS
100Configuración de IIS
- Con la ayuda del inetmgr podemos configurar
- Un sitio web completo
- Carpeta virtual asociada a una aplicación
- Una de sus subcarpetas
- Archivo individual
- Normalmente tendremos marcada la opción Acceso
anónimo - Si queremos identificar individualmente a un
usuario usaríamos desactivaríamos el acceso
anónimo - Tendríamos Autenticación de Windows Integrada ?
adecuada para intranets - Podríamos seleccionar Autenticación Básica
- Para instalar soporte de ASP.NET en IIS ejecutar
el comando - aspnet_regiis -ir -enable
101Configuración de IIS
102Seguridad y NTFS
- Una vez que IIS haya identificado adecuadamente
al usuario, anónimo o específico, delegará a NTFS - La combinación de permisos asignados a un
fichero, mediante el Explorador de Windows, junto
con la identidad asignada al usuario que efectúa
la solicitud por IIS determinará si el documento
solicitado puede devolverse - Hasta este punto el motor ASP.NET no habrá
intervenido.
103El Archivo de Configuración Web.config
- Para una app de uso en Intranet la configuración
de IIS y autorización de acceso a los archivos
será suficiente - Para acceso vía Internet es mejor configurar IIS
con acceso anónimo y delegar la autenticación en
ASP.NET - Muchos aspectos del funcionamiento de ASP.NET
están establecidos en - Los varios ficheros Web.config
- Machine.config, sus parámetros afectan
globalmente al funcionamiento de ASP.NET
104Configuración de Seguridad en Machine.config
- En mi sistema este fichero se encuentra en
C\WINDOWS\Microsoft.NET\Framework\v1.1.4322\CONFI
G - Su contenido principal en cuanto a seguridad está
dividido en tres apartados, que indicar cómo
identificar usuarios, la representación del
usuario y su autorización - ltauthentication mode"Windows"gt
- ltforms name".ASPXAUTH" loginUrl"login.aspx"
protection"All" timeout"30" path"/"
requireSSL"false" slidingExpiration"true"gt - ltcredentials passwordFormat"SHA1"gt
- lt/credentialsgt
- lt/formsgt
- ltpassport redirectUrl"internal"/gt
- lt/authenticationgt
- ltidentity impersonate"false" userName""
password""/gt - ltauthorizationgt
- ltallow users""/gt
- lt/authorizationgt
105Métodos de Identificación
- El elemento authentication establece el método de
identificación que usará ASP.NET - None ? acceso abierto
- Windows ? ASP.NET utilizará la identificación
integrada de Windows - Forms ? prescinde de la autorización de Windows y
utiliza un formulario web para identificar al
usuario - Passport ? ASP.NET utilizará el SDK de Windows
Passport
106Autorización de Acceso
- Se configura a través del elemento authorization
- Por cada documento solicitado se comprobará una
lista de concesiones y negaciones representadas
por los elementos allow y deny. - Cada elemento allow o deny consta de los tres
atributos siguientes - users enumerará los usuarios a los que se otorgo
o deniega la autorización de acceso - roles con este atributo se autoriza o deniega el
acceso a perfiles, grupos de usuarios
representados por un nombre - verbs permite indicar el método de solicitud GET
o POST
107Representación del Usuario
- Los atributos del elemento identity determinarán
qué personalidad de qué usuario deberá tomar
ASP.NET - impersonate indica si ASP.NET (true) debe o NO
(false) debe representar al usuario - userName el nombre de la cuenta a usar
- password la contraseña del userName
108La interfaz IPrincipal
- Cuando se produce la identificación de un
usuario, ASP.NET crea un objeto que implementa
Iprincipal - WindowsPrincipal y GenericPrincipal son dos
implementaciones de esta interfaz - La interfaz IPrincipal expone dos miembros
- Identity
- IsInRole
109Ejemplo SecurityExample
- Revisarlo en examples/SecurityExample
- Este ejemplo presenta al usuario un formulario de
login y le redirecciona a la página del portal
cuando el login es correcto - Se han utilizado contraseñas en plano
- passwordFormat podría tener el formato MD5 y SHA1
- Podríamos obtener sus valores a
FormsAuthentication.PasswordForStoringInConfigFile
()
110Seguridad en ASP.NET
- http//msdn.microsoft.com/library/default.asp?url
/library/en-us/dnnetsec/html/secnetlpmsdn.asp
111ASP.NET 2.0