April 2008 - Artículos

http://msdn.microsoft.com/en-us/rampup/default.aspx
Siguiendo con la línea de otra entrada en mi blog:
- Manuales, libros, enlaces sobre ASP.NET 2.0 (recopilación...)
Parece que existe este programa desde hace varios meses, pero recién hoy me entere y así que lo comparto.
Para los que necesitan empezar o darle un empujón al camino del desarrollo en .NET, existe un programa de estudio llamado MSDN Ramp Up. Interesante porque no es un solo temario para todos sino que dependiendo de nuestros conocimientos armamos (ya viene predefinido) el contenido.
No tienes tiempo? Completa los cursos cuando tu puedas...
No sabes por dende empezar? definite en que estado actual estas y selecciona el track que mas te ayude...
Pero esto no es solo aprendizaje, también al final, en nuestra graduación ;) tenemos importantes "descuentos"
Los premios (un valor para tu esfuerzo), que vienen de la mano de descuento en certificaciones o cursos de e-learning...
Especialmente diseñado en base nuestras habilidades actuales (para no aburrir con el contenido).
Si eres un aspirante a desarrollador (principiante), ya tienes conocimientos en Java, VB6 o incluso .NET 2002/2003... tienes un programa especial
Utilizando laboratorios y cursos que teníamos disponible en www.microsoftelearning.com, nos guía en adquirir nuevas habilidades....
Ejemplo del track para los que están con VB6 y quieren empezar "El camino de la fuerza..."

Necesite reutilizar un UserControl dentro de un controlador HTTP, pero me di cuenta que no puede realizar una referencia a mi UserControl como lo hacemos en las paginas .aspx, es decir no tenia forma de definir el tipo de control como para luego acceder a sus propiedades.
Veamos algo como veníamos utilizando al UserControl....
Cuando en una pagina .aspx normal (por llamarla de alguna manera) necesitamos utilizar un UserControl, lo arrastramos hacia ella y listo.
Se nos registra con la directiva @Register el UC para poder utilizarlo, junto con el Tagname y el TagPrefix
@Register:
Crea una asociación entre un prefijo de etiqueta y un control personalizado, lo que proporciona a los desarrolladores una forma concisa de hacer referencia a controles personalizados en un archivo de aplicación ASP.NET (incluidos páginas Web, controles de usuario y páginas principales).
Cuando necesitamos utlizarlo en algun propiedad o llamarlo desde el codigo debemos, podemos hacer uso de la directiva @Reference, para que se compile y agregue la referencia (es como registrar las antiguas DLL's...)
Asi podremos utilizar la referencia al objeto externo compilado y a sus miembros públicos desde el archivo actual.
@ Reference:
Indica que otro control de usuario, archivo de código fuente de página o archivo arbitrario que se encuentra en alguna ruta de acceso virtual debe compilarse dinámicamente y vincularse al archivo ASP.NET actual (página Web, control de usuario o página principal) en el que se declara esta directiva.
Y en el HTTPHandler (.ashx) ??
Aquí no tenemos estas directivas u opciones...
La forma que encontré es mediante Reflection, obteniendo el tipo
Dim miCtrl As UserControl = pagina.LoadControl("~/modulos/ucEjemplo.ascx")
Dim tipoControl As Type = miCtrl.GetType
Y luego mediante esta formidable clase.. puedo Obtener una propiedad y setearla
Dim propiedadExpedienteId As System.Reflection.PropertyInfo = tipoControl.GetProperty("ExpedienteId")
Dim valor As Int32 = 4442
propiedadExpedienteId.SetValue(miCtrl, valor, Nothing)
Luego ejecuto la pagina que tengo como ayuda (que me permitió cargar el control con LoadControl) y lo guardo en un StringWriter
Dim wr As System.IO.StringWriter = New System.IO.StringWriter()
HttpContext.Current.Server.Execute(pagina, wr, False)
Aquí esta el código completo del ejemplo:
Public Class Ejemplo : Implements IHttpHandler
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Response.Clear()
context.Response.ContentType = "text/html"
context.Response.Write(ObtenerContenido)
context.Response.End()
End Sub
Private Function ObtenerContenido() As String
Dim pagina As Page = New Page()
Dim miCtrl As UserControl = pagina.LoadControl("~/modulos/ucEjemplo.ascx")
Dim tipoControl As Type = miCtrl.GetType
'Ejemplo: valor 4442
tipoControl.GetProperty("ExpedienteId").SetValue(miCtrl, 4442, Nothing)
pagina.Controls.Add(miCtrl)
Dim wr As System.IO.StringWriter = New System.IO.StringWriter()
HttpContext.Current.Server.Execute(pagina, wr, False)
Dim cadenaSalida As String = wr.ToString()
wr.Close()
Return cadenaSalida
End Function
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Enviar el contenido de un UserControl por WebService
Idem a lo anterior:
<WebMethod()> _
<System.Web.Script.Services.ScriptMethod()> _
Public Function Actuaciones(ByVal contextKey As String) As String
Dim pagina As Page = New Page()
Dim miCtrl As UserControl = pagina.LoadControl("~/modulos/Ejemplo.ascx")
Dim tipoControl As Type = miCtrl.GetType
Dim propiedadExpedienteId As System.Reflection.PropertyInfo = tipoControl.GetProperty("ExpedienteId")
Dim valor As Int32 = Convert.ToInt32(contextKey)
propiedadExpedienteId.SetValue(miCtrl, valor, Nothing)
pagina.Controls.Add(miCtrl)
Dim wr As System.IO.StringWriter = New System.IO.StringWriter()
HttpContext.Current.Server.Execute(pagina, wr, False)
Dim cadenaSalida As String = wr.ToString()
wr.Close()
Return cadenaSalida
End Function
Este webmethod es especial por el parámetro que recibe, ya que lo utilizo dentro de un TabPanel para obtener los datos dinámicamente...
En este ejemplo seteo la propiedad DynamicContextKey con un valor para test, la idea es que luego se establezca por código cuando se carga la pagina.
<cc2:TabPanel ID="TabPases" runat="server"
HeaderText="Historial de Pases"
DynamicContextKey="4442"
DynamicServiceMethod="Pases"
DynamicServicePath="/servicios/expedientesWS.asmx">
<ContentTemplate>
</ContentTemplate>
Enlaces
- @ Register
Crea una asociación entre un prefijo de etiqueta y un control personalizado, lo que proporciona a los desarrolladores una forma concisa de hacer referencia a controles personalizados en un archivo de aplicación ASP.NET (incluidos páginas Web, controles de usuario y páginas principales).
- @ Reference
Indica que otro control de usuario, archivo de código fuente de página o archivo arbitrario que se encuentra en alguna ruta de acceso virtual debe compilarse dinámicamente y vincularse al archivo ASP.NET actual (página Web, control de usuario o página principal) en el que se declara esta directiva.
- Introducción a los controladores HTTP
- IHttpHandler (Interfaz)
Define el contrato que ASP.NET implementa para procesar de forma sincrónica las solicitudes Web HTTP mediante controladores HTTP personalizados.
- Object.GetType (Método)
Obtiene el objeto Type de la instancia actual.
- Type (Clase)
Representa declaraciones de tipo: tipos de clase, tipos de interfaz, tipos de matriz, tipos de valor, tipos de enumeración, parámetros de tipo, definiciones de tipo genérico y tipos genéricos construidos abiertos o cerrados.
- Type.GetProperty (Método)
Obtiene una propiedad específica del objeto Type actual.
- PropertyInfo (Clase)
Descubre los atributos de una propiedad y proporciona acceso a los metadatos de la misma.
- PropertyInfo.SetValue (Método)
Establece el valor de propiedad del objeto especificado en el valor indicado.
Preguntaron en los grupos de noticias de asp.net, como obtener la cultura del browser del cliente.
(y como tenia en el tintero/borrador este articulo.. complete con algunos enlaces.. y a publicarlo)
El primer ejemplo:
CultureInfo.CurrentCulture.Name()
Nos devuelve la cultura actual del proceso (Thread) actual, pero no del navegador del cliente.
Posible y "tentativa" solución
Una solución de ejemplo podría ser leyendo la propiedad UserLanguages del Request:
Private Function ObtenerCultura() As String
Dim culInfo As System.Globalization.CultureInfo
culInfo = System.Globalization.CultureInfo.CreateSpecificCulture(HttpContext.Current.Request.UserLanguages(0))
Return culInfo.ToString
End Function
Como la propiedad UserLanguages devuelve un arreglo de idiomas (cadena de caracteres) del cliente.. seleccionamos el primer item, y armamos nuestra cultura
Luego tendríamos que asignarla si queremos que sea la cultura por defecto para por ejemplo manipular fechas, presentar recursos.
En el ejemplo anterior habría que agregar esta línea:
Thread.CurrentThread.CurrentCulture = culInfo
Aquí como se dice, estamos "explicitando" la cultura a utilizar en base al lenguaje del cliente (que leímos del browser)
Solución en NET 2.0
Hace un par de meses nos comentaba esto José M. Alarcón en un articulo:
- Cambio automático de cultura en ASP.NET 2.0 (by José M. Alarcón)
Como y donde podemos cambiar?
- Por Pagina

Pero podemos hacer que sea automático que capture el valor del cliente
- Toda la aplicación:
Donde si no es en el web.config...

O automáticamente...

- Por código... como ya lo implementamos en el ejemplo mas arriba
Como lo probamos?
En el IE7 tenemos la posibilidad de cambiar el idioma de preferencia....
Tools >> Internet Options >> General >> Button Languages
Si ahora navegamos por el sitio podemos obtener, mediante el código detallado mas arriba:
- CultureInfo.CurrentCulture.Name(): es-AR
- ObtenerCultura(): fr-FR
Por si queda algo en el tintero... CurrentCulture/CurrentUICulture ??
(from MSDN...)
CurrentCulture:
La propiedad CultureInfo.CurrentCulture es una configuración de cada subproceso que determina los formatos predeterminados para la fecha, hora, moneda y números, el criterio de ordenación de texto, las comparaciones de cadenas y la distinción entre mayúsculas y minúsculas. La propiedad CurrentCulture no es una configuración de idioma. Sólo contiene datos relacionados con la configuración estándar para una región geográfica.
Nota: Aquí la palabra clave seria Internacionalización, donde se puede visualizar un dato sensible (por ejemplo la fecha) en forma correcta dependiendo de la cultura.
CurrentUICulture:
La propiedad CultureInfo.CurrentUICulture es una configuración para cada subproceso que devuelve la referencia cultural de la interfaz de usuario actual. La clase ResourceManager utiliza esta propiedad para buscar recursos específicos de la referencia cultural en tiempo de ejecución.
Nota: La palabra clave aquí es la Localización de los recursos
Casi siempre debería ser igual ambas, pero hay momentos que no poseemos por ejemplo al paquete de idioma (Language Pack) de NET 2.0 (que es un paquete de localización para el idioma español por ejemplo)
Y allí la UI no queda con el idioma para por ejemplo traducir los mensajes de algunos webcontrol que definimos, porque "físicamente" no esta instalado.
No queda muy claro? y no... aquí un muy buenos articulo de
Enlaces
En una pregunta de hoy en los foros de MSDN el tema era como tener mas de un DefaultButton por formulario, ya que queria que en un UserControl de Busqueda sea un boton el que se ejecute al presionar Enter sobre el texbox de busqueda, y tambien otra parte de la pagina funcione similarmente pero con otros controles.
Para refrescar la memoria podemos decir que por formulario en paginas ASP.NET podemos tener un DefaultButton, algo así:
<body>
<form id="Form1"
defaultbutton="Boton1"
defaultfocus="TextBox1"
runat="server">
...
Pero aquí lo que buscamos es tener mas de un botón...y no uno general (y por que no incluso un DefaultControl...! lo dejo para pensar)
La idea es algo así... que dependiendo en que Textbox estoy presionando ENTER se realiza el postback de un botón determinado
Hoy encontré en este articulo, interesante para la ultima opción
OPCION 1: Simple JS
EJEMPLO 1.1
Los controles:
<asp:TextBox ID="txtBusqueda" runat="server" />
<asp:Button id="btnBusqueda" runat="server" />
En el codebehind:
txtBusqueda.Attributes.add("onkeypress", "PresionTeclaBusqueda();")
El JS:
<script type="text/javascript">
function PresionTeclaBusqueda(){
if (event.keyCode==13){
document.getElementById('<%=btnBusqueda.ClientId%>').click();
}
}
</script>
EJEMPLO 1.2
Algo mas general seria enviar el ID del botón a realizar el click:
txtBusqueda.Attributes.add("onkeypress", "ClickBoton('" & btnBusqueda.ClientId & "');")
El código de script del lado del cliente
<script type="text/javascript">
function ClickBoton(botonId){
if (event.keyCode==13){
document.getElementById(botonId).click();
}
}
</script>
OPCION 2: Función para asignar botón por defecto al un control
Como ya comente mas arriba, aqui encontre una funcion muy sencilla, general y mas completa que la opcion 1.
Es un método que escribe en la pagina un script (si ya no esta registrado, para no escribirlo dos veces), y asigna un boton por defecto
La idea es enviarle a cada control su "boton por defecto"
SetDefaultButton(Me.Page, TextBox1, Button1)
SetDefaultButton(Me.Page, TextBox2, Button2)
SetDefaultButton(Me.Page, TextBox3, Button3)
Aquí el código en VB.NET para ASP.NET 2.0 (en el articulo original es para C#, y para ASP.NET 1.1)
Private Sub SetDefaultButton(ByVal pagina As Page, ByVal textControl As TextBox, ByVal botonPorDefecto As Button)
'Armando script
Dim script As New Text.StringBuilder
script.Append("<SCRIPT language=""javascript"" type=""text/javascript"">" & vbCrLf)
script.Append("<!--" & vbCrLf)
script.Append("function fnTrapKD(btn, event){" & vbCrLf)
script.Append("" & vbCrLf)
script.Append(" if (document.all){" & vbCrLf)
script.Append(" if (event.keyCode == 13){" & vbCrLf)
script.Append(" event.returnValue=false;" & vbCrLf)
script.Append(" event.cancel = true;" & vbCrLf)
script.Append(" btn.click();" & vbCrLf)
script.Append(" }" & vbCrLf)
script.Append(" }" & vbCrLf)
script.Append("" & vbCrLf)
script.Append(" else if (document.getElementById){" & vbCrLf)
script.Append(" if (event.which == 13){" & vbCrLf)
script.Append(" event.returnValue=false;" & vbCrLf)
script.Append(" event.cancel = true;" & vbCrLf)
script.Append(" btn.click();" & vbCrLf)
script.Append(" }" & vbCrLf)
script.Append(" }" & vbCrLf)
script.Append("" & vbCrLf)
script.Append(" else if(document.layers){" & vbCrLf)
script.Append(" if(event.which == 13){" & vbCrLf)
script.Append(" event.returnValue=false;" & vbCrLf)
script.Append(" event.cancel = true;" & vbCrLf)
script.Append(" btn.click();" & vbCrLf)
script.Append(" }" & vbCrLf)
script.Append(" }" & vbCrLf)
script.Append("}" & vbCrLf)
script.Append("// -->" & vbCrLf)
script.Append("</SCRIPT>" & vbCrLf)
'Registrando script
pagina.ClientScript.RegisterStartupScript(pagina.GetType(), "FUNCIONBOTONDEFECTO", script.ToString)
'Asignando evento funcion al evento onkeydown
textControl.Attributes.Add("onkeydown", "fnTrapKD(" + botonPorDefecto.ClientID + ",event)")
End Sub
Aquí la AppWeb con la opcion 2
Enlaces
[Para mis amigos diseñadores y amantes de la creatividad]
Al mejor estilo de "Evangelización por video" nos brinda programas de TV para todo tipo de perfil Fotógrafos, Diseñadores, Editores de Video, Desarrolladores
http://tv.adobe.com
Podremos visualizarlo por tema/perfil
Ya teníamos varios en YouTube para nuestro deleite, tutoriales, ejemplos, etc. pero aquí es la misma empresa quien nos ofrece.
Ya que son videos de tutoriales de programas como Lynda.com, Dr. Brown's Photoshop Laboratory (ver enlace Programs en el menú de Adobe TV)
y al mejor estilo y formato podemos visualizarlo (y por supuesto embeberlo o linkearlo)
Pero lo interesante es este enlace
Pero... para Adobe Media Player, necesitamos previamente Adobe AIR (mas adelante puede ser que escriba sobre este tema)
Entonces... descargando 11Mb... :S
Luego instalando...
Y si llego el momento. Instalando el Adobe Media Player... un nuevo reproductor en mi computadora ;(
Una vez instalado el Adobe Media Player, nos pregunta si queremos agregar este programa/video al reproductor... (quien no necesito un administrador parecido pero de YouTube, yo tengo uno instalado como plugin en Firefox)
y ta tenemos no solo el programa/show/video/ en nuestro reproductor
Sino el canal completo con todos sus episodios...
AMP: Adobe Media Player
Para el que lo quiere descargar:
http://get.adobe.com/amp/
Es de 1.4MB ... mmm más 11MB de Adobe Air
Al final la UI como siempre muy buena...sencilla
Que puedo hacer??
Y.. reproducir vídeos
Textual de la ayuda de AMP
(...)In addition to Flash (FLV and FV4) video, Adobe Media Player supports video files containing H.264 and HE-AAC content, including .mov, .mp4, .mp4v, .m4v, .3gp, .3gpp2 and .3g2 video formats, allowing you to effectively view and manage your personal video library through a single application.
Note: These file types can contain media other than H.264 and HE-AAC formats or encodings of H.264 or AAC that aren't compatible with Flash and Adobe Media Player. Adobe Media Player will do its best to play back files of these types, but only files ending with FLV and F4V are guaranteed to play.(...)
me gusto reproducir .FLV
Importar otros formatos
No encontré la forma de exportar otros formatos...
En la ayuda online de AMP
Videos online
Y claro... necesitaba también Adobe un reproductor de video/televisión como
Así que también tenemos un catalogo online
Pero son programas grabados (no es en vivo ) ... o no encontré.
Sugerencia de podcast de video
Anteriomente los videos "by Adobe", me los descargaba como podcast de video desde iTunes
Mediante la interfaz de iTunes podremos buscar podcast de video sobre estos temas.. y se descargan automáticamente en nuestro reproductor preferido ;)
Ejemplos
El único que encontré de .NET en el directorio de podcast de iTunes
http://www.dotnetrocks.com/

Justamente me acaban de preguntar como utilizar estos lenguajes de este modo. Este articulo lo escribí en Septiembre de 2006, y lo había colgado de otro en MisTrucos.NET, en mi Space.
Aquí en Geeks.ms ya lo comento José M. Alarcón, en base a cualquier lenguaje:
Quise postearlo aquí para que quede en el historial ;)
Aquí va...
Bueno he de aquí que por las cosas de la vida y componentes que reutilice y falta de tiempo necesite utilizar clases en VB.NET y C# dentro de la carpeta APP_CODE en un proyecto web en VS2005..
Coloque mis clases Clase1.vb y Clase2.cs en la carpeta y genero el siguiente error:
Exception Details: System.Web.HttpException: The files '/WebSite1/App_Code/Clase2.cs' and '/WebSite1/App_Code/Clase1.vb' use a different language, which is not allowed since they need to be compiled together.
Pero no creí que tuviera esta limitación así que me dedique a verificar como seria el proceso de indicarle el tipo de lenguaje que se utiliza en la famosa carpeta... por defecto el directorio APP_CODE puede contener clases del mismo lenguaje, pero se puede agregar subdirectorios e indicar a ASP.NET que los compile separadamente.
Cual es el proceso?....
- Primeramente insertar en la seccion de <compilation> del webconfig estas lineas que agregan un coleccion de subdirectorios que asp.net debe compilar en forma separada, o mejor dicho de forma agrupada por estos directorios...
<codeSubDirectories>
<add directoryName="App_Code_VB"/>
<add directoryName="App_Code_CS"/>
</codeSubDirectories>
- Luego tendías que crear estos directorios
/App_Code/App_Code_VB
/App_Code/App_Code_CS
- Y llegando al final, distribuir nuestras clases de VB.NET dentro de la carpeta correspondiente App_Code_VB, y las de C# en la carpeta App_Code_CS
Algunos datos interesantes (desde los enlaces a MSDN):
- El orden de generación se deduce del orden descendente de la colección codeSubDirectories.
- El directorio App_Code se genera en último lugar.
- Los subdirectorios se muestran en el orden en el que se debe compilar el código para cumplir sus dependencias, pero...
- No existen dependencias de orden de generación, lo que significa que este orden no es significativo.
- No hay ningún elemento codeSubDirectories predeterminado configurado para ASP.NET.
- Puede haber cualquier número de subdirectorios
Enlaces:
La pregunta de "Donde obtengo el ID del Usuario?"...(para un amigo que esta migrando aplicaciones de ASP Clásico) pero para todo que se inicia, ...aquí una pequeña ayuda.
Si vemos que nos brinda ASP.NET 2.0 con el espacio de nombre My.User
Vemos que el famoso USERID que tanto nos gusta y requerimos no lo tenemos a alcance de la mano...
Como Obtenerlo?
Aquí hacemos uso clases Membership y MembershipUser para obtener el usuario y luego preguntar por su ProviderUserKey
Ejemplo
Dim usuario As MembershipUser = Membership.GetUser
Dim usuarioID As String = usuario.ProviderUserKey.ToString
Dim usuario2 As MembershipUser = Membership.GetUser(My.User.Name)
Dim usuarioID2 As String = usuario2.ProviderUserKey.ToString
Y como estamos en este tema...Hace unos días coloque mi granito de arena para Dot Net Tip of the Day (este mismo articulo) , y parece que muchos lo hicieron ya que da un servicio de los tips que van acumulando de la comunidad...
.NET Tips & Tricks Community (ALPHA)
http://dotnettipoftheday.org/SuggestedTips.aspx
Enlaces