Evento de lanzamiento de la Comunidad .NET D.F. y Developers Dot Net
08 May 08 06:58 AM | Misael Monterroca

La Comunidad .NET de la Ciudad de México y DevelopersDotNet te invitan al evento de Lanzamiento.

Fecha:
13 de Mayo

Hora:
11 a.m. – 7.p.m

Lugar:
ITAM

Dirección:

Río Hondo # 1
Col. Progreso Tizapán
C.P. 01080 Del. Álvaro Obregón
México D.F.

Agenda:

11:00 a 12:30
Héctor Obregón -Interoperabilidad entre Código Nativo en C++ (con MFC), Windows Forms y WPF

12:30 a 2:00
Misael Monterroca - Silverlight 2.0 Beta 1

2:00 a 3:00
Tiempo disponible para salir a comer.

3:00 a 4:30
Miguel Ángel Moran - Nuevos elementos sintácticos con C# 3.0 y VB 9.0

4:30 a 5:45
Alfredo Ceballos – Experiencias de Usuario Enriquecidas en Web y Windows.

5:45 a 7:00
Raúl Guerrero –  SQL Server 2008

Mapa:

http://www.itam.mx/es/ubicacion/riohondo1.html
http://www.itam.mx/es/ubicacion/riohondo2.html

Compartiendo forms autentication entre diferentes aplicaciones web
25 February 08 08:36 AM | Misael Monterroca

Introducción

Asp.net permite incorporar de una manera muy rápida la autenticación vía Forms Autentication, en este articulo veremos como configurar dos o más aplicaciones web diferentes para compartir el mismo token de autenticación generado.

 

Prerrequisitos

  • Contar con una aplicación web configurada correctamente con Forms autentication
  • Tener una segunda aplicación web en donde se necesite tener el mismo token de autentificación (es decir, no volverse a firmar nuevamente)

Escenario

Existe una aplicación web funcionando con Forms Autentication  (www.sitiowebficticio.com) , por cuestiones de diseño se decide separar dicha aplicación en dos diferentes sitios web mediante directorios virtuales  www.sitiowebficticio.com/App1 y www.sitiowebficticio.com/App2

El objetivo es que ambas aplicaciones web compartartan el mismo token de autenticacion generado por Forms Autentication, de esta manera el usuario solo tendría que escribir sus credenciales una sola vez.

 

Manos a la obra

En App1 y App2 abrir el web.config, debería tener algo similar a lo siguiente (asumiendo que ya se encuentra configurado Forms Autenticacion):

 

   1: <connectionStrings>
   2:     <add name="MembershipCS" connectionString="Data Source=(local);Initial Catalog=kpmg;Integrated Security=true;"/>
   3: </connectionStrings>
   4: <system.web>        
   5:     <!--
   6:         The <authentication> section enables configuration 
   7:         of the security authentication mode used by 
   8:         ASP.NET to identify an incoming user. 
   9:     -->
  10:     <authentication mode="Forms"/>    
  11: <membership defaultProvider="SqlProv">
  12:         <providers>
  13:             <add name="SqlProv" type="System.Web.Security.SqlMembershipProvider,System.Web, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" 
  14:          connectionStringName="MembershipCS" 
  15:          enablePasswordRetrieval="false" 
  16:          enablePasswordReset="true" 
  17:          requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="10" passwordStrengthRegularExpression=""/>
  18:         </providers>
  19:     </membership>

Suponiendo que dentro de app1 y app2 existen dos folders en donde se le niega el acceso a usuarios anónimos el path seria el siguiente:

  1. Usuario accede a www.sitiowebficticio.com/App1/CarpetaSegura/PaginaSegura.aspx, forms autentication redirecciona a login.aspx para que el usuario ingrese sus credenciales
  2. El usuario ingresa sus credenciales, MemberShipProvider valida y login.aspx redirecciona a www.sitiowebficticio.com/App1/CarpetaSegura/PaginaSegura.aspx
  3. El usuario ahora quiere ingresar a App2, www.sitiowebficticio.com/App2/CarpetaSegura2/otrapaginasegura.aspx, forms autentication redirecciona a login.aspx pero de App2

¿Por que sucede este comportamiento si en ambas aplicaciones web tenemos exactamente la misma configuración?

Este comportamiento se debe a que el cookie que genera asp.net está encriptado y para generar la encriptación / des encriptación asp.net utiliza los valores especificados en los elementos validationKey y decryptionKey. Asp.net por defecto genera esas claves a nivel aplicación  de manera automatica, es por eso que cuando el usuario pasa de App1 a App2 el cookie no puede ser leio de manera correcta ya que las claves de encriptación son diferentes y por ende, se solicita nuevamente la autenticación ya que Forms Autentication toma ese cookie como invalido al no poderlo desencriptar

 

Lo que haremos será especificar dichas claves, para ello crearemos una aplicación de consola que generara dichas claves criptograficas:

   1: using System.Security.Cryptography;
   2:  
   3: namespace GenerarClavesAspNet
   4: {
   5:     class Program
   6:     {
   7:         static void Main()
   8:         {
   9:             string decryptionKey = CrearClave(System.Convert.ToInt32(24));
  10:             string validationKey = CrearClave(System.Convert.ToInt32(64));
  11:  
  12:             Console.WriteLine("<machineKey validationKey=\"{0}\" decryptionKey=\"{1}\" validation=\"SHA1\"/>", validationKey, decryptionKey);
  13:  
  14:             Console.ReadKey();
  15:  
  16:         }
  17:  
  18:         static String CrearClave(int numBytes)
  19:         {
  20:             RNGCryptoServiceProvider service = new RNGCryptoServiceProvider();
  21:             byte[] buff = new byte[numBytes];
  22:  
  23:             service.GetBytes(buff);
  24:             return ConvertirString(buff);
  25:         }
  26:  
  27:         static String ConvertirString(byte[] bytes)
  28:         {
  29:             StringBuilder cadena = new StringBuilder(64);
  30:  
  31:             for (int counter = 0; counter < bytes.Length; counter++)
  32:             {
  33:                 cadena.Append(String.Format("{0:X2}", bytes[counter]));
  34:             }
  35:             return cadena.ToString();
  36:         }
  37:  
  38:     }
  39: }

 

Al ejecutar la aplicación obtedremos un resultado similar al siguiente (las claves son generadas aleatoriamente)

   1: <machineKey 
   2: validationKey="3E622C9B81A29248B61C4A7863F9632ED1A98574741D77954E7A3643F8FFAC84F11ED1D62B9D3A9813389FB969AEFBE95BCFFD46D50840E67A167AA987DDE2DB" 
   3: decryptionKey="5950EB5459814355C270F07761331247D83723D0701EBF21" validation="SHA1"/>

 

Nota: Los valores aceptados para decryptionKey es de 8 a 24 bytes (en el ejemplo se usan 24) y para validationKey es de 20 a 64 bytes ( en el ejemplo se usa el nivel mas alto 64 bytes)

El resultado lo incorporaremos en ambas aplicaciones de está manera el token será compartido por ambas aplicaciones, el código en ambos web.config deberia de quedar similar al siguiente:

 

   1: <connectionStrings>
   2:         <add name="MembershipCS" connectionString="Data Source=(local);Initial Catalog=kpmg;Integrated Security=true;"/>
   3:     </connectionStrings>
   4:     <system.web>        
   5:         <!--
   6:             The <authentication> section enables configuration 
   7:             of the security authentication mode used by 
   8:             ASP.NET to identify an incoming user. 
   9:         -->
  10:         <authentication mode="Forms"/>    
  11:     <membership defaultProvider="SqlProv">
  12:             <providers>
  13:                 <add name="SqlProv" type="System.Web.Security.SqlMembershipProvider,System.Web, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" 
  14:              connectionStringName="MembershipCS" 
  15:              enablePasswordRetrieval="false" 
  16:              enablePasswordReset="true" 
  17:              requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="10" passwordStrengthRegularExpression=""/>
  18:             </providers>
  19:         </membership>
  20:  
  21:     <machineKey validationKey="3E622C9B81A29248B61C4A7863F9632ED1A98574741D77954E7A3
  22: 643F8FFAC84F11ED1D62B9D3A9813389FB969AEFBE95BCFFD46D50840E67A167AA987DDE2DB" 
  23:   decryptionKey="5950EB5459814355C270F07761331247D83723D0701EBF21" validation="SHA1"/>

 

De esta manera el path queda de la siguiente manera:

 

Conclusión

Asp.Net permite configurar de una manera muy rápida el compartir un token de autentificación entre diferentes aplicaciones web.

Invitaciones enviadas
19 February 08 10:43 PM | Misael Monterroca

Las invitaciones para la clínica 70-536 ya fueron enviadas (perdón por el día de retraso)  en total se enviaron 551 invitaciones, por favor verifiquen la recepción del correo electrónico.

 

De nuevo, gracias por su interés

 

Saludos, Misael.

¡PodWorx!
14 February 08 11:59 AM | Misael Monterroca

¡Esta es nuestra semana de lanzamientos! El día de hoy le toco a nuestro podcast aka "PodWorx", más información aqui y aqui

 

 

.danza :D

Filed under: ,
Mas recursos
13 February 08 03:05 PM | Misael Monterroca

Como muy bien Rocky lo comento en su post de "como ser mejor desarrollador" una buena manera de lograrlo es viendo webcast,  MSDN Media Center es un recurso de medios en español en donde existe bastante contenido, WebCast, ScreenCast y PodCast

Y para muestra, falta un botón  mi buen amigo Haaron Gonzalez estará dando dos webcast sobre VSTO y Flujos de trabajo sobre Sharepoint, altamente mente recomendables

 

Salu2

Filed under: ,
Invitaciones a clínica en línea
13 February 08 03:20 AM | Misael Monterroca

Hemos tenido una excelente respuesta para la clínica que impartiremos en línea, al momento hemos recibido más de 150 solicitudes de invitación (muchas gracias por su interés),  dicha invitación será enviada el próximo lunes 18 de febrero ya que  estamos realizando los últimos ajustes a nuestro portal. Aún cuando el curso es en línea será necesario establecer un limite, crearemos varios grupos con la finalidad de poder brindarles una mejor atención.

 

La invitación enviada los llevara a una forma de registro que les pedirá la siguiente información básica:

    • Nombre Completo
    • País (hemos recibido invitaciones de varios países)
    • Edad
    • Comunidad (en el caso de que pertenezcas a alguna)
    • Url personal (blog)
    • Nivel de conocimientos en .Net
      • 100 - Básico
      • 200 - Medio
      • 300  - Avanzado
      • 400  - Experto

 

Está información es necesaria para poder crear grupos con perfiles afines.

 

Nuevamente, gracias por su interés.

Clínica gratuita para certificación
12 February 08 01:56 PM | Misael Monterroca

El próximo lunes 3 de marzo daremos inicio a una clínica online  gratuita de entrenamiento enfocada a presentar el examen de certificación 70-536, la clínica tendrá una duración aproximada de 2 meses.

 

Si quieres inscribirte u obtener más información visita la página o envíanos un correo a learningcenter (arroba ) devworx.com.mx con el título "Clinica certificación 70-536)

 

http://learning.devworx.com.mx/certificaciones/70-536/default.aspx

DevWorx Learning Center
12 February 08 12:42 PM | Misael Monterroca

Como bien ya lo menciono Rocky estamos estrenando nuestro DevWorx Learning Center en el cual estaremos generando contenido gratuito sobre la plataforma Microsoft.

 

Estamos comenzando a generar contenido para:

El curso se dividira en varias secciones (el esqueleto ya esta generado en cada uno de los sitios) pronto habilitaremos una sección de notificación de contenido vía rss o email para que puedan estar enterados cada vez que haya nuevo material. Esperamos que está iniciativa sea de mucha utilidad para ustedes.

 

Si quieren que abordemos un tema en particular no duden en mandarnos un correo.

 

Saludos!

New transaction cannot enlist in the specified transaction coordinator.
08 February 08 04:55 PM | Misael Monterroca

Escenario:

Servidor 1:

  • Windows Server 2000 SP4
  • Sql Server 2000 SP4

Servidor 2

  • Windows Server 2003 SP2
  • BizTalk Server 2006
  • SQL Server 2005 SP2

 

Servidor 2 tiene una orquestación en Biztalk la cual necesita persistir información en una base de datos localizada en el servidor 1, cuando biztalk intenta crear la transcacción dentro de SQL Server 2000 da el siguiente error: "New transaction cannot enlist in the specified transaction coordinator."

 

Utilizando la herramienta DTCTester se obtiene el siguiente resultado:

 

   1: Executed: dtctester
   2: DSN:  test
   3: User Name: sa
   4: Password: sa
   5: tablename= #dtc8346
   6: Creating Temp Table for Testing: #dtc8346
   7: Warning: No Columns in Result Set From Executing: 'create table #dtc8346 (ival int)'
   8: Initializing DTC
   9: Beginning DTC Transaction
  10: Enlisting Connection in Transaction
  11: Error:
  12: SQLSTATE=25S12,Native error=-2147168219,msg='[Microsoft][ODBC SQL Server Driver]Distributed transaction error'
  13: Error:
  14: SQLSTATE=24000,Native error=0,msg=[Microsoft][ODBC SQL Server Driver]Invalid cursor state
  15: Typical Errors in DTC Output When
  16: a.  Firewall Has Ports Closed
  17: -OR-
  18: b.  Bad WINS/DNS entries
  19: -OR-
  20: c.  Misconfigured network 
  21: -OR-
  22: d.  Misconfigured SQL Server machine that has multiple netcards.
  23: Aborting DTC Transaction
  24: Releasing DTC Interface Pointers
  25: Successfully Released pTransaction Pointer.

 

Posibles soluciones:

    1. Firewall Has Ports Closed, No existe ningún software que se encuentre bloqueando ningún puerto
    2. Bad WINS/DNS entries, EL dns se encuentra correctamente configurado, utilizando DTCPING el servidor responde correctamente
    3. Misconfigured network, Descartado, misma solución que el punto anterior
    4. Misconfigured SQL Server machine that has multiple netcards, Ambos servidores tienen dos tarjetas de red, se dejo habilitada 1 y el problema persistia.

Solución

  1. En servidor 1, localizar la entrada del registro HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\Security (si no existe, crearla)
  2. Crear una entrada del tipo DWORD con el nombre NetworkDtcAccessTip con el valor 1, (Cero deshabilita el acceso vía TIP) Mas información
  3. En el servidor 2, habilitar entrar a  Component Services -> Computers -> My Computer -> Boton Derecho Properties  Ir a MSDTC Tab - > Habilitar Enable Transaction Internet Protocol (TIP) Transactions
  4. En ambos servidores  reiniciar MSDTC  net stop msdtc , net start msdtc
  5. Probar nuevamente :D

Si obtienen un resultado similar a la siguiente imagen, es que todo está funcionando perfectamente

ScreenCast : WCF Exponiendo un servicio
06 February 08 07:12 AM | Misael Monterroca

Este screencast es la continuación de WCF Introducción

 

En este screencast veremos como exponer un WCF Service Library, los temas que son tratados son:

  • EndPoint
  • Bindings
  • Host
  • Medatada

Url WMV para descarga (mejor definición)
Url Flash para ver Online

Filed under: , , ,
ScreenCast : WCF Introducción
05 February 08 07:30 AM | Misael Monterroca

Hola!

 

Les dejo este primer screencast de Windows Communication Foundation en donde veremos como crear un WCF Service Library

 

Url WMV para descarga (mejor definición)
Url Flash para ver Online

Filed under: , ,
Windows Server 2008 RTM
04 February 08 09:13 PM | Misael Monterroca

Una imagen dice mas que mil palabras...

 

WinServer 2008 RTM

ScrenCast : Intro Ajax ControlToolkit en VS2008
31 January 08 07:21 AM | Misael Monterroca
Les dejo este screencast nivel 100 en donde veremos como Instalar, Configurar  y utilizar Ajax ControlToolkit dentro de Visual Studio 2008
 
 
 
 
Nota: Tuve un problema ligero problema con el audio y en ocasiones se escuchan unos picos de ruido, por eso es mejor reproducirlo a un nivel de audio moderado.
La perdida de un amigo
29 January 08 09:49 PM | Misael Monterroca

Hoy me acabo de enterar de la perdida de un estimado amigo, Fernando Alvarez Buylla Aka Kuriaki  lo conozco desde hace casi 10 años cuando comencé a participar en las comunidades Microsoft él siempre fue una persona admirada, respetada y querida por todos. Tuve la suerte de conocerlo personalmente el año pasado en un MVP Round Table en México DF aun  recuerdo muy bien el abrazo que nos dimos después de únicamente mantener una "relación" electrónica. El día de ayer lamentablemente murió de cáncer lo cual es una gran tristeza para la comunidad informática que seguía con frecuencia su post en los foros de microsoft.

¡Suerte y éxito en donde quiera que sigas amigo!

Filed under:
Métodos del Runtime en Workflow Foundation
29 January 08 09:26 PM | Misael Monterroca

 

En este articulo profundizaremos un poco más acerca de los métodos disponibles en el Runtime, su sintaxis y su uso en Workflow Foundation.

La clase WorkflowRuntime

El runtime del flujo de trabajo es el intermediario entre la aplicación host y las instancias del flujo de trabajo. Aunque el flujo de trabajo es una parte muy importante de Windows Workflow Foundation, el runtime juega un papel muy importante en el ciclo de vida de los flujos de trabajo. La clase System.Workflow.Runtime.WorkflowRuntime representa el runtime del flujo de trabajo y proporciona una gran funcionalidad para manejar el ambiente del runtime. Utilizando esta clase, se tiene control absoluto de la ejecución de las instancias del flujo de trabajo y del runtime mismo. La clase System.Workflow.Runtime.WorkflowRuntime es responsable de varias tareas que son muy importantes. Una de ellas es la de el manejo de eventos del runtime que acabamos de ver en la sección anterior. Otra de ellas es la gestión del Runtime.

Gestión del Runtime

La clase WorkflowRuntime expone dos métodos públicos que se relacionan con la gestión del runtime del flujo de trabajo: StartRuntime y StopRuntime.

El método StartRuntime permite que se ejecuten dos importantes acciones. Primero, existen servicios base del runtime que siempre deben existir en un flujo de trabajo del runtime: un servicio de transacción del flujo de trabajo y un servicio planificador del flujo de trabajo. Cuando se llama a este método, se realice una validación para revisar si alguno de estos dos servicios ha sido añadido manualmente al runtime. Si no, el runtime crea instancias de default para cada tipo de servicio. La clase por default del servicio de transacción es DefaultWorkflowTransactionService, y la clase por default del servicio de planificación es DefaultWorkflowSchedulerService. Después de que los servicios se agregaron e instanciaron exitosamente al runtime, cada servicio es iniciado con el método Start. Adicionalmente a la configuración de los servicios que ocurre durante el proceso de arranque del runtime, a la propiedad IsStarted del runtime se le da el valor true, y se genera el evento Started Started.

Llamar al método StopRuntime tiene el efecto contrario. Se detienen todos los servicios, se descargan todas las instancias de flujos de trabajo, a la propiedad IsStarted se le da el valor false, y se genera el evento Stopped event. La Tabla 2 nos muestra los diferentes métodos de trabajo existentes en el workflow Runtime:

Método

Descripción

CreateWorkflow

Crea una instancia del flujo de de trabajo utilizando los parámetros especificados.

GetAllServices

Regresa todos los servicios que han sido agregados al engine del runtime del flujo de trabajo que derivan del tipo especificado.

GetLoadedWorkflows

Obtiene una colección que contiene todas las instancias de flujos de trabajo actualmente cargadas en memoria.

GetService

Obtiene un servicio del engine del runtime del flujo de trabajo que usa el tipo especificado.

GetWorkflow

Obtiene las instancia del flujo de trabajo que tiene el Guid especificado.

RemoveService

Quita el servicio especificado del engine del runtime del flujo de trabajo.

StartRuntime

Inicia el engine del runtime del flujo de trabajo y los servicios del engine del runtime del flujo de trabajo.

StopRuntime

Detiene el engine del runtime del flujo de trabajo y los servicios del engine del runtime del flujo de trabajo.

Tabla 2. Métodos del Workflow Runtime

Iniciar y manejar instancias del Workflow

Una de las tareas más importantes que el runtime puede realizar es iniciar instancias del flujo de trabajo. Adicionalmente a iniciar las instancias, el runtime expone la funcionalidad para manejarlos. Para manejar una instancia del flujo de trabajo, simplemente hay que llamar el método CreateWorkflow de la instancia WorkflowRuntime. Existen muchas formas de llamar a este método, pero el más comúnmente usado es el que usa una instancia Type, que representa el tipo de la clase de flujo de trabajo. Por ejemplo:

//MiWorkflow es la definición de clase del workflow                 
 
Type workflowType = typeof(MiWorkflow);     
 
// usa el runtime del workflow runtime para crear una instancia de MiWorkflow 
 
WorkflowInstance workflowInstance = 
 
theRuntimeInstance.CreateWorkflow(workflowType);

Aunque el código anterior crea una instancia del flujo de trabajo, en realidad no inicia el flujo de trabajo. El método Start method de la clase WorkflowInstance es la que lo hace, como se puede ver en el siguiente código:

// inicia la instancia del flujo de trabajo 
 
workflowInstance.Start(); 

 

En el siguiente ejemplo podemos ver la ejecución de los métodos StartRuntime y StopRuntime del WorkFlowRuntime junto con el método Start para la instancia del flujo de trabajo:

Main() 
 
{ 
 
string connectionString = "Initial Catalog=SqlPersistenceService;Data Source=localhost;Integrated Security=SSPI;"; 
 
 
 
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime()) 
 
{ 
 
ExternalDataExchangeService dataService = new ExternalDataExchangeService(); 
 
workflowRuntime.AddService(dataService); 
 
dataService.AddService(expenseService); 
 
 
 
workflowRuntime.AddService(new SqlWorkflowPersistenceService(connectionString)); 
 
workflowRuntime.StartRuntime(); 
 
 
 
workflowRuntime.WorkflowCompleted += OnWorkflowCompleted; 
 
workflowRuntime.WorkflowTerminated += OnWorkflowTerminated; 
 
 
 
Type type = typeof(EjemploWorkflow1); 
 
WorkflowInstance workflowInstance = workflowRuntime.CreateWorkflow(type);