<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Juan Carlos Ruiz Pacheco</title>
    <description>The latest articles on DEV Community by Juan Carlos Ruiz Pacheco (@juankruiz).</description>
    <link>https://dev.to/juankruiz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F200942%2Fe0134e9e-c7b1-402c-ad34-464e8965994b.jpg</url>
      <title>DEV Community: Juan Carlos Ruiz Pacheco</title>
      <link>https://dev.to/juankruiz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/juankruiz"/>
    <language>en</language>
    <item>
      <title>Publicar aplicaciones de Office 365 (M365)</title>
      <dc:creator>Juan Carlos Ruiz Pacheco</dc:creator>
      <pubDate>Tue, 07 Jan 2020 18:25:45 +0000</pubDate>
      <link>https://dev.to/juankruiz/publicar-aplicaciones-de-office-365-m365-2fo7</link>
      <guid>https://dev.to/juankruiz/publicar-aplicaciones-de-office-365-m365-2fo7</guid>
      <description>&lt;p&gt;Como partners de Microsoft podemos publicar aplicaciones entorno a la plataforma de M365 (Office 365), esto incluye aplicaciones como&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Office add-ins&lt;/li&gt;
&lt;li&gt;SharePoint solutions&lt;/li&gt;
&lt;li&gt;Power BI visual&lt;/li&gt;
&lt;li&gt;Teams Apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Al publicar estas Apps, ellas aparecen como aplicaciones disponibles en los public Marketplace de Microsoft para cada uno de estos servicios.&lt;/p&gt;

&lt;p&gt;Para ello debemos cumplir con los siguientes requisitos&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tener una cuenta de partner en el Partner Center&lt;/li&gt;
&lt;li&gt;Registrarse con una cuenta de desarrollador de M365&lt;/li&gt;
&lt;li&gt;Completar el perfil de partner desarrollador&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tener una cuenta de partner en el Partner Center
&lt;/h2&gt;

&lt;p&gt;No profundizaré mucho en esta, hay que ir al &lt;a href="https://partner.microsoft.com/" rel="noopener noreferrer"&gt;Partner Center&lt;/a&gt; y registrarse, sobra decir que debes ser una empresa constituida legalmente para ello.&lt;/p&gt;

&lt;h2&gt;
  
  
  Registrarse con una cuenta de desarrollador de M365
&lt;/h2&gt;

&lt;p&gt;Ya estando registrado cómo partner debes inscribirte cómo desarrollador de M365.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inicia sesión en el &lt;a href="https://partner.microsoft.com/" rel="noopener noreferrer"&gt;Partner Center&lt;/a&gt; con las credenciales de partner.&lt;/li&gt;
&lt;li&gt;En otra pestaña Inicia sesión en el &lt;a href="https://developer.microsoft.com/en-us/store/register" rel="noopener noreferrer"&gt;Portal De Registro Como Developer&lt;/a&gt; si te pregunta por credenciales &lt;strong&gt;utiliza un personal liveID&lt;/strong&gt; NO cuentas corporativas, es decir &lt;strong&gt;NO tu cuenta de partner.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Una vez allí selecciona la opción de Office&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1zx9z3b441qx3ij0k4xd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1zx9z3b441qx3ij0k4xd.png" alt="Opción de Office" width="447" height="326"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lo cual te lleva a esta pantalla, das click en &lt;em&gt;Sign up now&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcwgo1o7604dbetcld5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcwgo1o7604dbetcld5g.png" alt="Sign up now" width="485" height="385"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Y diligencias el formulario&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2armoztkqdpdmg39hf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2armoztkqdpdmg39hf7.png" alt="Get Started" width="600" height="552"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Al hacer esto te trae de vuelta al Partner Center, donde notarás que se habilita el módulo de &lt;em&gt;Office Store&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jo5twlkdrcc7q8c2je5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jo5twlkdrcc7q8c2je5.png" alt="Get Started" width="269" height="558"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Qué pasa sino me registro como developer de M365
&lt;/h3&gt;

&lt;p&gt;Lo que sucederá es que no te aparecerá el modulo de Office Store, no tendrás forma de publicar una de las Apps listadas al inicio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Completar el perfil de partner desarrolador
&lt;/h2&gt;

&lt;p&gt;Esto es muy importante y muchas veces se pasa por alto, sino completas este proceso no podrás publicar ninguna aplicación por lo que es importante avanzar en este tema en tanto continuas con el desarrollo o antes de iniciarlo.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Desde el &lt;a href="https://partner.microsoft.com/" rel="noopener noreferrer"&gt;Partner Center&lt;/a&gt; vas a la configuración (engine en la parte superior izquierda) y seleccionas &lt;a href="https://partner.microsoft.com/en-us/dashboard/account/management" rel="noopener noreferrer"&gt;Developer Settings&lt;/a&gt; (también vas directo dando clic en el vínculo anterior)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgv55s76pu1uoh08zqd1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgv55s76pu1uoh08zqd1f.png" alt="Developer Settings" width="306" height="326"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Te aparecerá un panel como este, donde verás "Verification Status: Pending"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F783oh1fvpsqotzaythab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F783oh1fvpsqotzaythab.png" alt="Developer Status Pendiente" width="369" height="548"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Debes completar la información en cada una de las etapas, y usar tus credenciales de partner. Si uno de los pasos no tiene una verificación exitosa recibirás una alerta como esta: "Verification Status: Rejected", que impedirá que tu cuenta sea verificada hasta no hacer las correcciones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firdsiqgeeplrcn1aiuwn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firdsiqgeeplrcn1aiuwn.png" alt="Developer Status Inválido" width="448" height="591"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Una vez completas todos los pasos tu cuenta queda verificada. "Verification Status: Authorized"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67s3lwyfpx5z9dyg2e16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67s3lwyfpx5z9dyg2e16.png" alt="Developer Status Authorized" width="327" height="462"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Qué pasa si trato de publicar una aplicación y mi cuenta no está verificada?
&lt;/h3&gt;

&lt;p&gt;Esto pasa, pero el mensaje no saldrá hasta que no des click en publicar, por lo que no te hagas falsas ilusiones si el botón te sale habilitado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0zkj68igu27hmu2z0zl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0zkj68igu27hmu2z0zl.png" alt="Consecuencias de no verificar la cuenta" width="452" height="303"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Estás listo para publicar aplicaciones de M365 como Partner de Microsoft. 😊&lt;/p&gt;

</description>
      <category>m365</category>
      <category>microsoft</category>
      <category>partner</category>
    </item>
    <item>
      <title>Añadir tracking de consumo en despliegues ARM</title>
      <dc:creator>Juan Carlos Ruiz Pacheco</dc:creator>
      <pubDate>Tue, 31 Dec 2019 23:12:35 +0000</pubDate>
      <link>https://dev.to/juankruiz/anadir-tracking-de-consumo-en-despliegues-arm-2c86</link>
      <guid>https://dev.to/juankruiz/anadir-tracking-de-consumo-en-despliegues-arm-2c86</guid>
      <description>&lt;p&gt;Título Alterno:&lt;/p&gt;

&lt;h2&gt;
  
  
  Atribución del consumo de Azure de nuestros clientes
&lt;/h2&gt;




&lt;p&gt;He invitado a co-escribir este artículo a mi buen amigo y colega Juan Carlos Sosa, quien trabaja como Ingeniero en Habilitas.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://habilitas.com/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4flroruwfck3ky6s5b4w.png" alt="Empresa Habilitas" width="300" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Habilitas es una empresa Costarricense que genera productos para el sector financiero, más abajo en el capítulo Caso Real de implementación Habilitas nos describe el caso particular de su compañia y como el tracking de consumo los beneficia en el proceso de implementación de su solución.&lt;/p&gt;

&lt;p&gt;Pueden seguir a Juan Carlos Sosa en Dev.to&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__312003"&gt;
    &lt;a href="/jcgerarsr" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F312003%2F21dfc728-7623-4327-a643-a8c05675467b.jpg" alt="jcgerarsr image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/jcgerarsr"&gt;Juan Carlos G. Sosa Rivas&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/jcgerarsr"&gt;Lead en Habilitas Team, Sr. Software Dev, Geek.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;Cuando trabajamos &lt;strong&gt;&lt;a href="https://partner.microsoft.com/" rel="noopener noreferrer"&gt;como partners&lt;/a&gt;&lt;/strong&gt; de Microsoft (por ejemplo ISVs) tenemos control de cuanto es el consumo de Azure de nuestras soluciones, esto es relativamente fácil cuando nuestro software es un SaaS (Software As A Service). Sin embargo en ocasiones los requerimientos de nuestros clientes implican que algo, o toda, nuestra aplicación se despligue en la infraestructura de ellos.&lt;/p&gt;

&lt;p&gt;Algunos casos comunes en los que se requiere el despliegue de infraestructura en suscripciones de Azure de los clientes son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bases de datos: por regulación o políticas internas los datos deben quedarse bajo el completo control del cliente&lt;/li&gt;
&lt;li&gt;Web App / Virtual Machine: El cliente requiere una 'máquina dedicada' donde se reduzca en su totalidad el riesgo de compartir datos en memoria, archivos y otros recursos con otras organizaciones y requiere ser el administrador de esa infraestructura.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Estos y otros escenarios comunes son perfectamente realizables gracias a la flexibilidad que nos brinda la nube, sin embargo hay otros desafíos que no siempre son detectables a simple vista.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entre más exitosa es tu solución más Azure consumes
&lt;/h2&gt;

&lt;p&gt;Conforme tu solución SaaS es adoptada por tus clientes, tu consumo de servicios en la nube tiende a subir, por ello en la medida en que seas exitoso Microsoft es exitoso también. Desde luego entre más consumo de Azure se genere por el éxito de tu negocio más visibilidad tienes con el equipo comercial de Microsoft y eso abre las puertas a otras oportunidades de ofertas, ventas conjuntas, entrenamientos y otros beneficios más para los partners.&lt;/p&gt;

&lt;p&gt;Justo allí es donde surgen algunas preguntas importantes.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué pasa cuando debo hacer despliegue de infraestructura en las suscripciones de mis clientes?
&lt;/h3&gt;

&lt;p&gt;Cuando despliegas la infraestructura de tu aplicación en las suscripciones de tus clientes los consumos de Azure generados &lt;em&gt;son sus consumos&lt;/em&gt; y ellos cubren esos gastos. Ese consumo es derivado de la aplicación que les vendiste, pero normalmente no tienes forma de saber de saber cual es el consumo de esos servicios ni forma de incluirlos en tus reportes y por ende no puedes recibir crédito por el consumo que has influenciado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo puedo medir ese consumo de servicios de Azure que mi empresa (el partner) ha generado de manera indirecta?
&lt;/h3&gt;

&lt;p&gt;Hay que &lt;strong&gt;&lt;em&gt;marcar&lt;/em&gt;&lt;/strong&gt; la infraestructura desplegada en tus clientes, para hacerlo &lt;strong&gt;debes desplegar esa infraestructura por medio de un &lt;em&gt;template ARM&lt;/em&gt;&lt;/strong&gt; y en dicho template agregar algunos atributos que te permitan a ti y a Microsoft tener un adecuado seguimiento de los consumos de Azure derivados de esos servicios.&lt;/p&gt;




&lt;p&gt;A continuación revisaremos cómo inyectar los atributos de seguimiento en un template ARM y dónde podemos seguimiento a dichos consumos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alerta de Privacidad&lt;/li&gt;
&lt;li&gt;Perfil de partner en el "Microsoft Partner Center"&lt;/li&gt;
&lt;li&gt;Registrar el Guid en el Partner Center&lt;/li&gt;
&lt;li&gt;Adicionar el Tracking Guid a los ARM&lt;/li&gt;
&lt;li&gt;Verificar el Tracking de Consumo en Reportes&lt;/li&gt;
&lt;li&gt;Caso Real de implementación Habilitas&lt;/li&gt;
&lt;li&gt;Notas importantes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Alerta de Privacidad
&lt;/h2&gt;

&lt;p&gt;Los datos recolectados por Azure y la plataforma de Partners de esta manera son cobijados por las &lt;a href="https://www.microsoft.com/trustcenter" rel="noopener noreferrer"&gt;políticas de privacidad de Microsoft&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;De igual manera, como partner, es tu responsabilidad notificar a tus clientes al respecto de que haces seguimiento de los consumos derivados de los consumos de servicios de tu aplicación.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perfil de partner en el "Microsoft Partner Center"
&lt;/h2&gt;

&lt;p&gt;Lo se, parece un poco obvio pero es mejor aclararlo, este mecanismo esta diseñado para partners de Microsoft y para ser partner debes tener tu empresa registrada en el &lt;a href="https://partner.microsoft.com/" rel="noopener noreferrer"&gt;Partner Center&lt;/a&gt;, si aún no lo has hecho puedes iniciar &lt;a href="https://partner.microsoft.com/en-us/dashboard/account/v3/enrollment/introduction/azureisv" rel="noopener noreferrer"&gt;aquí tu registro como partner/ ISV&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generar un Guid para el seguimiento
&lt;/h2&gt;

&lt;p&gt;Para realizar el tracking debes tener un Guid (Globally Unique Identifier) el cual debes asocial al template ARM y también en tu cuenta del Partner Center.&lt;/p&gt;

&lt;p&gt;Hay 3 formas principales de crear este Guid&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utilizando el &lt;a href="https://forms.office.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR3i8TQB_XnRAsV3-7XmQFpFUMVRVVFFLTDFLS0E2QzNYSkFZR1U3WVJCTSQlQCN0PWcu" rel="noopener noreferrer"&gt;Formulario de generación de GUID&lt;/a&gt; : &lt;strong&gt;Esta opción es la recomenda&lt;/strong&gt; aunque no es requerida.&lt;/li&gt;
&lt;li&gt;Usando PowerShell: Basta con ejecutar &lt;code&gt;New-Guid&lt;/code&gt; y la consola nos devuelve un Guid con el formato requerido.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;PS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;New-Guid&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;----&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;0352&lt;/span&gt;&lt;span class="n"&gt;cf0f-2e7a-4aee-801d-7f27f8344c77&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Cualquier otro mecanismo con el que estés familiarizado siempre y cuando retorne un Guid con el formato requerido&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Registrar el Guid en el Partner Center
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Una vez generado el Guid es necesario registrarlo en el Partner Center, para ello vamos a &lt;a href="https://partner.microsoft.com/en-us/dashboard/account/management" rel="noopener noreferrer"&gt;Account Settings&lt;/a&gt; o siguiendo los pasos de la imagen (si, Developer Settings)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5z6ks5hvffe71vya89x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5z6ks5hvffe71vya89x.png" alt="Acceder a Account Settings" width="554" height="329"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Una vez allí hacemos scroll down hasta encontrar &lt;strong&gt;Tracking GUIDs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzugc8wtph8wk9qa9cq6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzugc8wtph8wk9qa9cq6n.png" alt="Tracking GUIDs" width="372" height="115"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Damos click en "Add Tracking GUID" y diligenciamos el formulario con el Id generado en la sección anterior y una descripción. Puedes generar IDs por cliente, por ambiente, por aplicación, en escencia por cada cosa que desees, por eso es conveniente usar una descripción que se adapte a tus necesidades.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyy6tehhlsvq75b6rwu3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyy6tehhlsvq75b6rwu3.png" alt="Add Tracking GUID" width="540" height="167"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Una vez hecho esto el Guid aparece en la lista, podemos agregar todos lo que se consideren necesarios.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Adicionar el Tracking Guid a los ARM
&lt;/h2&gt;

&lt;p&gt;Teniendo registrado el Guid en el Partner Center es hora de incluirlos en el/los template ARM que usaremos para desplegar la infraestructura.&lt;/p&gt;

&lt;p&gt;Para ello lo que se hace es agregar un nuevo recursos a la lista y este recurso tiene nuestro Guid con el prefijo &lt;code&gt;pid-&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Dentro del ARM ubicamos la sección de recursos que viene con esta estructura, usualmente entre el 1ro y el 3er miembro de la lista.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;recurso&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;recurso&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;recurso&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;N...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Justo arriba del primer recurso adicionamos el siguiente recurso, fíjate en el atributo &lt;code&gt;"name"&lt;/code&gt; allí encuentras el prefijo &lt;code&gt;pid-&lt;/code&gt; seguido del Guid registrado en el Partner Center, en este caso &lt;code&gt;0352cf0f-2e7a-4aee-801d-7f27f8344c77&lt;/code&gt;. Atentos con la &lt;code&gt;,&lt;/code&gt; al final, es una lista de objetos JSON por lo que sino pones la &lt;code&gt;,&lt;/code&gt; arruinarás la estructura.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"apiVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2018-02-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pid-0352cf0f-2e7a-4aee-801d-7f27f8344c77"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Resources/deployments"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Incremental"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"contentVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;El archivo JSON queda más o menos así&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"apiVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2018-02-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pid-0352cf0f-2e7a-4aee-801d-7f27f8344c77"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Resources/deployments"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Incremental"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"contentVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;recurso&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;recurso&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;recurso&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;N...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Ahora es tiempo de hacer el despliegue ARM template y una vez hecho procedemos a verificar que los recursos hayan quedado marcados de correctamente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verificar el Guid
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Primero asegúrate de tener instalado el módulo de Azure para PowerShell, puedes instalarlo de cualquiera de estas formas según lo que requieras.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;PS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Install-Module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Az&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-AllowClobber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scope&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CurrentUser&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;PS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Install-Module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Az&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-AllowClobber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scope&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;AllUsers&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Ahora asegúrate de tener en PowerShell iniciada la sesión en tu suscripción de Azure. Si manejas más de una suscripción debes hacer comandos adicionales que encuentras en la &lt;a href="https://docs.microsoft.com/en-us/powershell/azure/?view=azps-2.8.0&amp;amp;viewFallbackFrom=azps-1.2.0" rel="noopener noreferrer"&gt;documentación de Azure Power Shell&lt;/a&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;PS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ConnectAzAccount&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Una vez instalado ya puedes verificar que los ítems hayan quedado marcados para tracking. Es sencillo ejecutando este script de PowerShell, mi recomendación es que lo guardes en un archivo &lt;code&gt;armtagverifier.ps1&lt;/code&gt; y lo ejecutes por consola.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="kr"&gt;Param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;GUID&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Mandatory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;$true&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="nv"&gt;$guid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Mandatory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;$true&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="nv"&gt;$resourceGroupName&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Get the correlationId of the pid deployment&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nv"&gt;$correlationId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-AzResourceGroupDeployment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$resourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pid-&lt;/span&gt;&lt;span class="nv"&gt;$guid&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;correlationId&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Find all deployments with that correlationId&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nv"&gt;$deployments&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Get-AzResourceGroupDeployment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$resourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;correlationId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-eq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$correlationId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Find all deploymentOperations in a deployment by name&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# PowerShell doesn't surface outputResources on the deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# or correlationId on the deploymentOperation&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;foreach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$deployment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$deployments&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Get deploymentOperations by deploymentName&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# then the resourceId for any create operation&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$deployment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;Get-AzResourceGroupDeploymentOperation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
            &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provisioningOperation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-eq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Create"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="o"&gt;-and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;targetResource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resourceType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-ne&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Resources/deployments"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;targetResource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Al ejecurtarlo te pedirá el Guid y el nombre del grupo de recursos en el que se realizó el despliegue.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Supply&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;following&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parameters:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;guid:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0352cf0f-2e7a-4aee-801d-7f27f8344c77&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;resourceGroupName:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nombreResourceGroup&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Y el resultado es una lista de los recursos que han quedado marcados con el despliegue&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;/subscriptions/adcbda71-......uank/config/web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;/subscriptions/adcbda71-......uank/hostNameBindings/testjuank.azurewebsites.net&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;/subscriptions/adcbda71-......uank&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Verificar el Tracking de Consumo en Reportes
&lt;/h2&gt;

&lt;p&gt;Habiendo configurado el traking de consumo en el despliegue de infraestructura utilizando el Guid, la plataforma de Azure comienza a buscar correlación entre los datos de consumo de las suscripciones y los Guid registrados en la plataforma de partners.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Para visualizar dicha información hay que dirigirse al &lt;strong&gt;Partner Center&lt;/strong&gt;, módulo de &lt;strong&gt;MPN&lt;/strong&gt; y la opción de &lt;strong&gt;Analize&lt;/strong&gt;. Es importante notar esto, ya que dependiendo el tipo de partner y los servicios que ofrezca tu empresa puedes tener otros módulos cada uno con su propia opción de &lt;strong&gt;Analize&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh9gly50ukq1hm6rmx90g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh9gly50ukq1hm6rmx90g.png" alt="Módulos de Analize en Partner Center" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En el módulo de &lt;strong&gt;Analize&lt;/strong&gt; vamos a &lt;strong&gt;Cloud product Performance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1kye8xo6aptyy2uxoanj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1kye8xo6aptyy2uxoanj.png" alt="Cloud product Performance" width="270" height="420"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Allí vamos a la pestaña "Microsoft Azure" y en el combo "Partner Association Type" seleccionamos "Customer Usage Attribution". Allí ya podemos ver el resultado del consumo de Azure que hemos generado por cada tracking (Guid) que hemos registrado en el portal. El reporte se despliega en el dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fso4e98rb42atfcld7pjd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fso4e98rb42atfcld7pjd.png" alt="Dashboard de Reporte" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Caso Real de implementación &lt;a href="http://habilitas.com/" rel="noopener noreferrer"&gt;Habilitas&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;by &lt;a href="https://dev.to/jcgerarsr"&gt;Juan Carlos Sosa&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como empresa nos enfocamos totalmente hacia el desarrollo orientado a la nube (Específicamente Microsoft Azure) mediante tecnologías Microsoft, nuestro ámbito principal es la generación de soluciones que se integran con las aplicaciones de línea de negocio de las compañías. Trabajamos bajo la modalidad software como servicio (SaaS), infraestructura como servicio (IaaS) y plataforma como servicio (PaaS), todo esto dependiendo de cada caso cubierto y de las especificaciones y restricciones que cada cliente pueda tener.&lt;/p&gt;

&lt;p&gt;Con el tiempo hemos ido creciendo en cuanto a tecnologías y servicios que prestamos a los clientes, así como también en modalidades y niveles de servicio disponibles, todo esto ha implicado ir adaptándonos a requerimientos y políticas internas de cada organización, las cuales son cada vez más estrictas. Muchos de nuestros clientes hacen parte del sector financiero. &lt;/p&gt;

&lt;p&gt;Actualmente la evolución de la empresa nos ha impulsados a dos nuevos escenarios de cambio y adaptación:&lt;/p&gt;

&lt;h3&gt;
  
  
  Escenario 1: Restricciones de negocio
&lt;/h3&gt;

&lt;p&gt;En nuestros recientes proyectos hemos trabajado con entidades que requieren que sus servicios corran total o parcialmente en sus propias suscripciones de Azure, esto debido a que deben seguir algunas restricciones legales o de operación, relacionadas con la custodia de la infraestructura o los datos que recolectan.&lt;/p&gt;

&lt;p&gt;Esto nos genera dificultades para rastrear el consumo que generan nuestras aplicaciones dado que todo el consumo que estamos influenciando se ha quedado sin tracking alguno, ni de nuestro lado ni del lado de Microsoft.&lt;/p&gt;

&lt;h3&gt;
  
  
  Escenario 2: Delegación de control
&lt;/h3&gt;

&lt;p&gt;En ocasiones los clientes quieren delegar el control de su infraestructura en el proveedor de la solución(nosotros) y en ocasiones requerimos delegar el control de dicha infraestructura en el cliente, por diversos motivos.&lt;/p&gt;

&lt;p&gt;Actualmente contamos con infraestructura en la nube que está cubriendo las necesidades de nuestros clientes, aunque estos recursos actualmente se encuentran bajo nuestra cuenta de azure principal queremos reorganizarlos para permitirle al cliente tener el control de las mismas en sus propias suscripciones.&lt;br&gt;
Aunque este escenario nos resulta conveniente - en la medida que delegamos el control de esa infraestructura - , no nos resulta tan favorable de cara a medir nuestro impacto como partner en el ecosistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remediación
&lt;/h3&gt;

&lt;p&gt;En primer lugar: la implementación del tracking de consumo en las plantillas ARM nos proporcionará dos oportunidades de mejora: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;La posibilidad de organizar, automatizar y poder replicar a futuro nuestros despliegues mediante plantillas. Esta posibilidad de replicación nos permitirá tener despliegues más confiables y propiciará la exactitud de la replicación entre los diferentes ambientes a utilizar (en nuestro caso por lo general Desarrollo, QA y Producción).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mediante la utilización de la plantilla ARM podremos adicionar el GUID para hacer tracking de nuestra solución. De esta forma tenemos visibilidad del acumulado de consumo de Azure de nuestra solución en Azure en nuestros clientes, lo cual a su vez nos permite tener mayor relevancia y oportunidades de beneficios dentro del programa de Partners de Microsoft.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Notas importantes
&lt;/h2&gt;

&lt;p&gt;Aunque esta funcionalidad es muy buena, no es perfecta y hay algunas restricciones que debes tener en cuenta&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si haces un nuevo despliegue por ARM Template en el mismo grupo de recursos bien sea utilizando el mismo Guid o uno nuevo, el tracking anterior desaparece. Es decir siempre se tiene en cuenta solo el último despliegue.&lt;/li&gt;
&lt;li&gt;Si adicionas nuevos servicios al grupo de recursos estos servicios no se encontrarán marcados con el Guid, por lo que no puedes trackear el consumo de los nuevos servicios aunque estén en el mismo grupo de recursos.&lt;/li&gt;
&lt;li&gt;Debes tratar la infraestructura de tu aplicación como un todo, cada adición o eliminación de un servicio supone que hagas un nuevo despliegue. Esto podría ser engorroso por lo que te sugiero implementar "&lt;strong&gt;Infraestructura como Código&lt;/strong&gt;" en tus pipeline de DevOps. Los templates ARM son una muy buena forma de hacerlo, pero cuentas con otras opciones como las API de ARM o Terraform.&lt;/li&gt;
&lt;li&gt;⚠ Este blog post esta basado, en buena parte, en la documentación oficial de Microsoft: &lt;a href="https://docs.microsoft.com/en-us/azure/marketplace/azure-partner-customer-usage-attribution" rel="noopener noreferrer"&gt;"Azure partner customer usage attribution"&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>azure</category>
      <category>devops</category>
      <category>arm</category>
      <category>partner</category>
    </item>
    <item>
      <title>Autenticación de Bots con Azure Active Directory</title>
      <dc:creator>Juan Carlos Ruiz Pacheco</dc:creator>
      <pubDate>Fri, 27 Dec 2019 00:50:09 +0000</pubDate>
      <link>https://dev.to/juankruiz/autenticacion-de-bots-con-azure-active-directory-3dn1</link>
      <guid>https://dev.to/juankruiz/autenticacion-de-bots-con-azure-active-directory-3dn1</guid>
      <description>&lt;p&gt;Adicionar autenticación usando Azure AD es &lt;em&gt;'relativamente'&lt;/em&gt; sencillo.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;'Relativamente'&lt;/em&gt;?, si relativamente porque aunque el concepto de como hacer una integración con el directorio activo es ámpliamente conocido, los detalles para hacer dicha integración no suelen ser tan obvios.&lt;/p&gt;

&lt;p&gt;Para poder usar de manera intuitiva Azure AD sería necesario tener algunos conocimientos previos de los flujos de autenticación modernos (OAuth principalmente), y admitámoslo ese no es el caso la mayoría de las veces así que hay que darse unas cuentas vueltas a la documentación y hay que reconocer que muchas veces eso tampoco es suficiente.&lt;/p&gt;

&lt;p&gt;En esta entrada de blog me enfocaré en como realizar integración de un bot creado con &lt;strong&gt;Bot Framework&lt;/strong&gt; y por extensión hospedado en  &lt;strong&gt;Azure Web App Bot&lt;/strong&gt; (o corriendo localmente).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;lo sé, suena redundante, pero me gusta decir: "mejor que so-sobre y no que fa-falte"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Resumen
&lt;/h2&gt;

&lt;p&gt;Hay un conjunto de pasos para realizar la integración y en algunos casos no importa el orden en que los realices por ejemplo podrías crear el Web App Bot primero, pero hay una razón por la cual es mucho mejor leer esta entrada de blog que seguir el pie de la letra la documentación. Si sigues estos pasos no habrá lugar a confusiones, en especial en escenarios corporativos cuando es posible que te encuentres con ambientes de Azure con múltiples suscripciones o AD tenants.&lt;/p&gt;

&lt;p&gt;Si, ya he llorado lagrimas y no quiero que te pase lo mismo, así que aquí te presento una serie de pasos en los que tienes que seguir el orden propuesto para obtener los resultados deseados, rápidamente y sin confusiones.&lt;/p&gt;

&lt;p&gt;Con el propósito de enfocarnos en la integración y no en el desarrollo del bot vamos a utilizar la librería de ejemplos del Bot Framework y con uno de ellos probaremos que la integración ha funcionado de manera exitosa.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Registrar el Bot en Azure AD&lt;/li&gt;
&lt;li&gt;Configuración de la App Registrada&lt;/li&gt;
&lt;li&gt;Crear y configurar un Web App Bot en Azure&lt;/li&gt;
&lt;li&gt;Configuración de la solución en Visual Studio&lt;/li&gt;
&lt;li&gt;Configuración del emulador&lt;/li&gt;
&lt;li&gt;Prueba de Autenticación con Azure AD&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Registrar el Bot en Azure AD
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Registro inicial de la aplicación
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;En el &lt;a href="https://portal.azure.com" rel="noopener noreferrer"&gt;portal de Azure&lt;/a&gt; vamos al Directorio Activo, puedes hacerlo como quieras, a mi en particular me gusta usar la barra de búsqueda así&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsz9frnbb59csebc3qypn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsz9frnbb59csebc3qypn.png" alt="Barra de búsqueda" width="653" height="423"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Una vez en el Azure AD vamos a 'App Registrations' y damos click en 'New Registration'&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2iey92l7ep3wg76g35q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2iey92l7ep3wg76g35q.png" alt="app registrations" width="672" height="478"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En la ventana emergente le ponemos nombre al bot y en "Supported account types" nos aseguramos de seleccionar la indicada, dado que los bots la mayoría de las veces son para atender incluso a gente fuera de nuestra organización se recomienda que usemos la 2 opción, si nuestro bot requiere autenticación de otras plataformas con Microsoft ID como cuentas de outlook o de Xbox podríamos usar la 3ra.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F935ean5qk5jlpteym14r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F935ean5qk5jlpteym14r.png" alt="Register application" width="542" height="405"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Un poco más abajo del paso anterior encontramos "Platform configuration" y está marcado como opcional. Puedes dejarlo en blanco si quieres, en mi caso lo marcaré con la primera opción ya que , por supuesto, el Bot es una parte aplicación web y otra cliente móvil.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjllyufr20hl4n3exvxyg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjllyufr20hl4n3exvxyg.png" alt="Platform configuration" width="540" height="214"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click en "Register" y esperamos unos segundos&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Y listo! ... por ahora, porque antes otra explicación.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ahora que tenemos registrada la aplicación necesitamos entender la mecánica básica del flujo de autenticación.&lt;/p&gt;

&lt;p&gt;En corto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La aplicación se presenta ante en Azure AD, para ello demuestra su identidad con un &lt;strong&gt;ID&lt;/strong&gt; (llamado Client ID) y un &lt;strong&gt;Password&lt;/strong&gt; (llamado Secret)&lt;/li&gt;
&lt;li&gt;Si el directorio la conoce le devuelve un token que debe usar en cualquier transacción que requiera hacer con el AD&lt;/li&gt;
&lt;li&gt;Cuando un usuario inicia sesión desde la aplicación, la aplicación usa una URL provista por el Azure AD en la que el usuario puede ingresar sus datos de acceso de manera segura&lt;/li&gt;
&lt;li&gt;Al iniciar de manera exitosa el usuario es redirigido a una &lt;strong&gt;URL de la aplicación&lt;/strong&gt; (Redirect URL) incluyendo en los datos del request (URL, Headers o a veces body) un token de acceso para el usuario y otros metadatos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;He resaltado tres componentes, al lado de cada uno una breve explicación&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client ID&lt;/strong&gt;: Es único por cada aplicación&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret&lt;/strong&gt;: Pueden haber varios, desaparecen una vez generados, así que es mejor copiarlos, usarlos y olvidarse de ellos. Si se requiere de nuevo en ese caso mejor generar uno nuevo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redirect URL&lt;/strong&gt;: Pueden ser varias, son las URL &lt;strong&gt;&lt;em&gt;autorizadas&lt;/em&gt;&lt;/strong&gt; de la aplicación, donde está puede analizar los contenidos del request (redirect) que le hicieron y extraer el token del usuario y los metadatos que lo acompañan.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configuración de la App Registrada
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;En el Azure AD vamos a la App Registrada&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9yfa3oehxr1k258o9guv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9yfa3oehxr1k258o9guv.png" alt="App Registrada" width="616" height="453"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En Overview logramos identificar dos datos muy importantes, que para facilidad vale la pena que guardes para más adelante. El primero de ellos es el Client ID y el segundo Tenant ID que no es otra cosa que el ID del directorio Activo donde se registró la aplicación.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4yem8aj2vklbkxtorm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4yem8aj2vklbkxtorm7.png" alt="Overview" width="752" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Id&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Client ID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;da2e26d8-a9c9-442a-8831-c972fe6f281a&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tenant ID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bcc54888-4288-4bbd-c041-3225637c7154&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En el panel de la izquierda navegamos hasta "Authentication" y allí damos click en "Add a platform"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdzm2wyqkpu696flxnzh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdzm2wyqkpu696flxnzh.png" alt="Add a platform" width="652" height="424"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;En el panel emergente damos click en el botón 🌐 Web&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En Redirect URIs colocamos &lt;code&gt;https://token.botframework.com/.auth/web/redirect&lt;/code&gt; todo lo demás lo dejamos tal como está. Damos click en "Configure"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fywmq5y275qalbi55lugn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fywmq5y275qalbi55lugn.png" alt="Redirect Uri" width="380" height="449"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A continuación navegamos a "Certificates &amp;amp; Secrets" en el sidebar y damos click en "New client secret"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsd43klb7s97kcfzxxws6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsd43klb7s97kcfzxxws6.png" alt="New client secret" width="602" height="515"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En la ventana emergente ponle un nombre que te ayude a recordar a quien o para que usaste ese secreto de la aplicación, selecciona el tiempo de expiración que desees para el secreto, en este caso he seleccionado "Never" pero en cada compañía manejan políticas diferentes para ello. Click en "Add".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3wtwrowfaga33ohxzl7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3wtwrowfaga33ohxzl7.png" alt="Agregar secreto" width="277" height="312"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Una vez creado &lt;strong&gt;copia de inmediato el secreto&lt;/strong&gt;, una vez generado, cuando regreses a esta ventana, ya no lo podrás recuperar. Les muestro el mio porque igual solo existirá mientras creo este artículo.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Expires&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;juankbot&lt;/td&gt;
&lt;td&gt;12/26/2020&lt;/td&gt;
&lt;td&gt;&lt;code&gt;j32e5fbN@lk[Su0oZXmLFnazaPgt@uv_&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Con esto terminamos nuestra configuración en el Azure AD, los datos relevantes que debemos llevarnos son&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Client ID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;da2e26d8-a9c9-442a-8831-c972fe6f281a&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tenant ID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bcc54888-4288-4bbd-c041-3225637c7154&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secret&lt;/td&gt;
&lt;td&gt;&lt;code&gt;j32e5fbN@lk[Su0oZXmLFnazaPgt@uv_&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Permisos en el Microsoft Graph (opcional en este momento)
&lt;/h3&gt;

&lt;p&gt;Ya tenemos nuestra aplicación registrada en el Azure AD y tenemos los datos para el acceso, pero a ¿Qué cosas le vamos a dar acceso?.&lt;/p&gt;

&lt;p&gt;Podemos dar acceso a infinidad de cosas de Productos de Microsoft, del Microsoft Graph e incluso de aplicaciones de terceros o propias.&lt;/p&gt;

&lt;p&gt;Hay 2 tipos de permisos, delegados y de aplicación.&lt;/p&gt;

&lt;p&gt;Hablamos de "Permisos de aplicación" cuando la aplicación corre como un servicio en segundo plano sin que ningún usuario deba iniciar sesión.&lt;/p&gt;

&lt;p&gt;Como nuestro bot necesita actuar en nombre de un usuario (usualmente para conectarse con aplicaciones o servicios a los cuales el usuario tiene acceso completo o limitado) necesitamos permisos delegados.&lt;/p&gt;

&lt;p&gt;Por el momento solo nos interesa autenticarnos e iniciar sesión, así que debemos conceder los siguientes permisos cuando se acceda desde  nuestra aplicación.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;profile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openid&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;offline_access&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para hacerlo debemos seguir los siguiente pasos en el Azure AD.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navegar hasta el registro de la aplicación, ingresar en el registro&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Navegar en el sidebar hasta "API Permissions" y dar click en "Add a permission"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyf9g1evgdzx9ojxv7cst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyf9g1evgdzx9ojxv7cst.png" alt="Azure AD permisos de aplicación" width="588" height="388"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En el panel emergente seleccionamos "Microsoft Graph"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd6508vpq8tif6l1mz92l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd6508vpq8tif6l1mz92l.png" alt="Microsoft Graph" width="400" height="306"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Seguidamente damos click en "Delegated permissions" y usando la barra de búsqueda, buscamos y seleccionamos &lt;code&gt;profile&lt;/code&gt;,&lt;code&gt;openid&lt;/code&gt;,&lt;code&gt;offline_access&lt;/code&gt;, damos click en "Add permissions"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxaq5uba4jchru2wq43qz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxaq5uba4jchru2wq43qz.png" alt="Microsoft Graph" width="516" height="576"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Una vez hecho podemos dejar 'pre-autorizados' estos permisos para todos los miembros de la organización, sino lo hacemos cuando cada usuario inicie sesión se le preguntará si desea conceder estos permisos a la aplicación.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Esperamos unos segundos y damos click en "Refresh" de tal manera que el botón "Grant admin consent for..." se active. Le damos click.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En el diálogo emergente iniciamos sesión, se nos preguntará si queremos dar consentimiento para estos permisos en toda la organización, aceptamos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7x5lpnd5src6xe258qar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7x5lpnd5src6xe258qar.png" alt="Consentimiento del administrador" width="404" height="470"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Con esto finalizamos la configuración de permisos en el AD.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crear y configurar un Web App Bot en Azure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creación del Web App Bot en Azure
&lt;/h3&gt;

&lt;p&gt;Ahora crearemos un Azure Web App Bot, que en escencia es el bot que conectaremos con Azure AD.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Creamos un nuevo grupo de recursos y para este caso lo llamaremos &lt;code&gt;juank-rg&lt;/code&gt;, para hacerlo en el home de &lt;a href="https://portal.azure.com" rel="noopener noreferrer"&gt;Azure portal&lt;/a&gt; le damos click en donde indica la siguiente figura.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzk05jhihq97hwc7r11z3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzk05jhihq97hwc7r11z3.png" alt="Nuevo recurso" width="308" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez allí buscamos "Resouce Group", colócale un nombre adecuado, selecciona la región de tu conveniencia y procede a crearlo.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ve al grupo de recursos recién creado, dale click en "Add"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcraubwani2y9r8618jgq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcraubwani2y9r8618jgq.png" alt="Adicionar Recursos" width="403" height="247"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;En el panel de creación busca "Web App Bot" y procede a crearlo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hasta este punto configura la información según consideres pertinente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1bgfnmkknbeq5bmg18yf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1bgfnmkknbeq5bmg18yf.png" alt="configuración básica del servicio de Bot" width="300" height="506"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Selecciona el App Service plan correspondiente, sino tienes un App Service Plan o no sabes qué es, procede a crear uno desde allí mismo. Asegúrate de usar un nombre y región apropiados.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Recomiendo siempre, SIEMPRE, dejar habilitado Application Insights el día que tengas que hacer solución de problemas lo agradecerás. También recuerda configurar una región a apropiada par ti.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffd6o8ynb479rqm48b0aw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffd6o8ynb479rqm48b0aw.png" alt="configuración app service plan" width="304" height="213"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;‼ Hemos llegado al punto importante de la integración con el Azure Active Directory. Haz click en el recuadro justo abajo de la configuración anterior "Microsoft App ID and Password".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6dsn0133kihrlka9u3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6dsn0133kihrlka9u3a.png" alt="Microsoft App ID and Password" width="304" height="266"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ Al momento de escribir este artículo es &lt;strong&gt;&lt;em&gt;MUY MALA IDEA&lt;/em&gt;&lt;/strong&gt; usar la opción de auto-creación, porqué? porque si lo haces de esa manera tendrás que volver al directorio activo y buscar la aplicación que creará automáticamente. Y si de suerte el directorio activo que usas está en otra suscripción de Azure, te harás un enredo que bueno... por eso escribo este artículo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Dale click en "Create New" y pega allí los datos que guardamos anteriormente. Y finaliza dando click en "OK".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuy1uzl1ydd7yv8im47ao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuy1uzl1ydd7yv8im47ao.png" alt="Microsoft App ID and Password" width="623" height="269"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Al finalizar dale click en "Create" y la plataforma procederá a crear el Bot y los demás assets necesarios.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Configuración del Web App Bot
&lt;/h3&gt;

&lt;p&gt;Ahora que hemos creado en el servicio en Azure debemos hacer un par de configuraciones.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;En el bot services vamos a Settings y en el panel de la derecha hacemos scroll hasta la parte inferior buscando "OAuth Connection Settings" Y damos click allí.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosy1cg7sfv614e15cimm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosy1cg7sfv614e15cimm.png" alt="Bot Settings" width="626" height="559"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le colocamos un nombre adecuado a la conexión, ciertamente un Bot podría iniciar sesión contra varios Directorios diferentes, así que aquí debemos configurar nuestro directorio activo. Hay dos formas de hacerlo, con Azure AD v1 y Azure AD v2. Ambas funcionan pero en condiciones normales siempre deberías seleccionar la última versión disponible, en este momento Azure AD v2. Así que seleccionamos ese en la lista de service providers. Inmediatamente aparecen los campos que debemos llenar, para los cuales ya tenemos información. En el campo "Scopes" colocamos los valores que listo a continuación, los cuales indican que necesitamos permiso para iniciar sesión y acceder a la info del usuario. Esta lista puede cambiar dependiendo de que otras cosas queremos acceder del &lt;a href="https://developer.microsoft.com/en-us/graph/" rel="noopener noreferrer"&gt;Microsoft Graph&lt;/a&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Client ID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;da2e26d8-a9c9-442a-8831-c972fe6f281a&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tenant ID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bcc54888-4288-4bbd-c041-3225637c7154&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secret&lt;/td&gt;
&lt;td&gt;&lt;code&gt;j32e5fbN@lk[Su0oZXmLFnazaPgt@uv_&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scopes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;openid profile&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;La lista de scopes es &lt;em&gt;case-sensitive&lt;/em&gt; y debe estar separada por espacios en blanco.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le damos click en "Save" y queda así&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrl53sxgxig4oylvajr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrl53sxgxig4oylvajr2.png" alt="Bot OAuth Settings" width="500" height="162"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Inmediatamente volvemos a abrirla para dar click en "Test Connection" allí debes iniciar sesión, usa tus credenciales para acceder al portal de Azure. Sino has hecho el paso opcional de asignación de permisos en el Azure AD verás una pantalla como está y como  eres admin te dará la opción de consentimiento de estos permisos para todos los usuarios de la organización, si ya habías hecho el paso de los permisos esta pantalla no aparecerá.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpraih1f9wrnuv49f3ihe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpraih1f9wrnuv49f3ihe.png" alt="Auth Permissions" width="396" height="468"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Al autenticarte aparecerá la siguiente pantalla de comprobación donde puedes ver y copiar el token generado. Sino sale o recibes un error deberás revisar la configuración anterior o incluso volver a revisar el registro de la Aplicación en el Azure AD. Guarda y cierra el dialogo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn1oua4py18ixzyff6d9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn1oua4py18ixzyff6d9.png" alt="Token generado" width="428" height="190"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ahora que tenemos la autenticación del servicio configurada y verificada vamos a "Configuration" en el Sidebar y allí encontraremos "Application Settings" y justo en la lista de settings&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MicrosoftAppId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MicrosoftAppPassword&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verificamos que los valores correspondan, pista: siempre corresponden.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ Ten presente que aunque el setting &lt;code&gt;MicrosoftAppId&lt;/code&gt; es editable, cambiarlos por el ID de una nueva aplicación que tengas en el Azure AD no servirá de nada, tu aplicación quedará inútil ya que este valor debe corresponder siempre con el que aparece en "Settings" que como podrás ver es un campo ineditable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F09mshodr1q76b8kf4vp1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F09mshodr1q76b8kf4vp1.png" alt="Bot Config Settings" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhwflgztrjo2jzdbbpkf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhwflgztrjo2jzdbbpkf.png" alt="Settings ineditables" width="574" height="403"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Con esto terminamos la configuración del servicio del Bot. Sin embargo para que el tema siguiente funcione se requiere un paso adicional así que lo haremos de una vez.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;En la configuración agregamos un nuevo setting llamado &lt;code&gt;ConnectionName&lt;/code&gt; y le asignamos el mismo nombre que usamos en la configuración de los "OAuth Settings", en mi caso &lt;code&gt;azure-ad-juank&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frr02p2oke83pa2xoclaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frr02p2oke83pa2xoclaw.png" alt="Setting adicional" width="573" height="391"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Configuración de la solución en Visual Studio
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Como lo mencionamos al inicio, con el ánimo de enfocarnos en la configuración y no en el código, haremos uso de uno de los &lt;a href="https://github.com/Microsoft/BotBuilder-Samples" rel="noopener noreferrer"&gt;ejemplos del Bot Framework&lt;/a&gt;. &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/microsoft" rel="noopener noreferrer"&gt;
        microsoft
      &lt;/a&gt; / &lt;a href="https://github.com/microsoft/BotBuilder-Samples" rel="noopener noreferrer"&gt;
        BotBuilder-Samples
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Welcome to the Bot Framework samples repository. Here you will find task-focused samples in C#, JavaScript/TypeScript, and Python to help you get started with the Bot Framework SDK!
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Usaremos cualquiera de los relacionados con autenticación en el repositorio, las configuraciones que aquí realice aplican para cualquier framework y lenguaje con las variantes normales que correspondan a cada uno.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En ese caso  usaré un ejemplo de C# net Core que se encuentra en "samples/csharp_dotnetcore/", llamado &lt;a href="https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/18.bot-authentication" rel="noopener noreferrer"&gt;"18.bot-authentication"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Te recomiendo que clones el repositorio y que trabajes luego solo en este proyecto de ejemplo de tal forma que en cada compilación no tardes tanto como si tuvieras los más de 45 ejemplos cargados.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Abrimos el archivo de configuración de la solución, el cual en el caso de C# es &lt;code&gt;appsettings.json&lt;/code&gt; allí encontraremos los mismos settings que dejamos configurados en el Web App Bot, para poder probar el bot en el entorno local debemos tener lo settings locales.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"MicrosoftAppId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"da2e26d8-a9c9-442a-8831-c972fe6f281a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"MicrosoftAppPassword"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"j32e5fbN@lk[Su0oZXmLFnazaPgt@uv_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"ConnectionName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"azure-ad-juank"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Eso es todo , el ejemplo va a funcionar.&lt;br&gt;
Si te preguntas cual es el propósito del setting &lt;code&gt;ConnectionName&lt;/code&gt; les el siguiente párrafo.&lt;/p&gt;


&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;Para que el bot pueda mostrar una ventana de login al usuario se requiere que te comuniques con las API de Auth de Azure AD y con el Auth setting que configuraste en el servicio Web App Bot. Y llevar el control de todo el flujo de autenticación por tu cuenta.&lt;/p&gt;

&lt;p&gt;Hacer todo este trabajo manualmente no es imposible, pero si dispendioso, así que existe forma de crear una &lt;a href="https://adaptivecards.io/" rel="noopener noreferrer"&gt;Adaptive Card&lt;/a&gt; para autenticación por OAuth, pero si quieres solucionarlo de manera aún más fácil el SDK de bot Framework, en este caso el SDK para net core, incluye un &lt;code&gt;OAuthPrompt&lt;/code&gt; que internamente -adivino- hace uso de un Adaptive Card y se encarga de toda la lógica del flujo de autenticación.&lt;/p&gt;

&lt;p&gt;Pues bien para que el &lt;code&gt;OAuthPrompt&lt;/code&gt; funcione requiere información relacionada con nuestro Azure AD y nuestra aplicación...&lt;/p&gt;

&lt;p&gt;Claro! el &lt;code&gt;MicrosoftAppId&lt;/code&gt; y &lt;code&gt;MicrosoftAppPassword&lt;/code&gt; son dos de esos datos, pero y todo lo demás?&lt;br&gt;
El tenant Id, los permisos requeridos, las URL de autenticación, las de token, las URL autorizadas en el Azure AD etc, ¿Dónde están?.&lt;/p&gt;

&lt;p&gt;Bueno esos datos los hemos dejado (y otros son resueltos) por el Web App Bot en el Auth Setting (en mi caso &lt;code&gt;azure-ad-juank&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Así que por ello en &lt;code&gt;ConnectionName&lt;/code&gt; hemos dejado el valor del Auth Setting del Web App Bot.&lt;/p&gt;

&lt;p&gt;Dentro de la solución encontramos donde se hace la configuración del AuthPrompt aquí. &lt;code&gt;Dialogs/MAinDialog.cs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MainDialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IConfiguration&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MainDialog&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MainDialog&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"ConnectionName"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;AddDialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;OAuthPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OAuthPrompt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;OAuthPromptSettings&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ConnectionName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConnectionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Please Sign In"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Sign In"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;300000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// User has 5 minutes to login (1000 * 60 * 5)&lt;/span&gt;
        &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Puedes ver claramente como extrae el nombre de la configuración y luego lo pasa al &lt;code&gt;OAuthPromptSettings&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dónde se muestra el &lt;code&gt;OAuthPrompt&lt;/code&gt;? Más abajo justo en este método.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DialogTurnResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;PromptStepAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WaterfallStepContext&lt;/span&gt; &lt;span class="n"&gt;stepContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;stepContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BeginDialogAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OAuthPrompt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ngrok
&lt;/h2&gt;

&lt;p&gt;Ngrok es un proxy que permite que el bot en tu emulador se comporte como si estuviera corriendo desde azure, permitiendo que si es necesario use todos los servicios de azure Bot disponibles en el backend.&lt;/p&gt;

&lt;p&gt;⚠⚠⚠ Debes hacer esto ❗❗❗&lt;br&gt;
No entraré en detalles de como descargarlo y configurarlo, pero los encuentras aquí en &lt;a href="https://blog.botframework.com/2017/10/19/debug-channel-locally-using-ngrok/" rel="noopener noreferrer"&gt;detalles al respecto&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Configuración del emulador
&lt;/h2&gt;

&lt;p&gt;Si ejecutamos la aplicación recién configurada desde Visual Studio o desde el kit de herramientas del Bot Framework tenemos esto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7vu0e42tm3zx7rxb4lmc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7vu0e42tm3zx7rxb4lmc.png" alt="Bot Service Running" width="540" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El Bot ya está corriendo, ahora debemos conectarnos con &lt;a href="https://github.com/microsoft/BotFramework-Emulator/releases" rel="noopener noreferrer"&gt;emulador&lt;/a&gt; y con &lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt;. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;En la configuración del emulador en este ícono parte inferior izquierda ⚙ , encuentras la siguientes opciones de autenticación, ambas son soportadas, sin embargo para efectos de la prueba te recomiendo marcar solo la primera.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvg1c414i94i62t42spxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvg1c414i94i62t42spxd.png" alt="Bot Emulator Config" width="357" height="159"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cuando se configure la conexión con el bot es ⚠ IMPORTANTE configurar el &lt;code&gt;MicrosoftAppId&lt;/code&gt; y &lt;code&gt;MicrosoftAppPassword&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq95aqw2grtyr4iwfdgup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq95aqw2grtyr4iwfdgup.png" alt="Conexión con el bot desde emulador" width="396" height="438"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prueba de Autenticación con Azure AD
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Teniendo la instancia del bot corriendo desde Visual Studio, realizamos la conexión con el emulador. &lt;strong&gt;Si recibes este mensaje&lt;/strong&gt; entonces todo va bien, sino entonces debes revisar nuevamente los &lt;code&gt;MicrosoftAppId&lt;/code&gt; y &lt;code&gt;MicrosoftAppPassword&lt;/code&gt; en &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;la configuración de la conexión en el emulador&lt;/li&gt;
&lt;li&gt;en la solución&lt;/li&gt;
&lt;li&gt;en el Bot Web App&lt;/li&gt;
&lt;li&gt;en el Azure AD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3cve9k925bazw839pqve.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3cve9k925bazw839pqve.png" alt="Bot Service Message" width="433" height="475"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;El bot está diseñado para pedir autenticación con cualquier texto que ingreses, con excepción de que ingreses &lt;code&gt;logout&lt;/code&gt; &lt;code&gt;¯\_(ツ)_/¯&lt;/code&gt; . Así que ingresa cualquier texto como prueba, en este caso ingresé 123. Veras que el bot despliega el &lt;code&gt;OAuthPromt&lt;/code&gt; pidiendo login. Damos click al botón.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6d9bmrgs10ypbsl6hljg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6d9bmrgs10ypbsl6hljg.png" alt="Bot Service Login" width="326" height="261"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Al darle click al enlace el emulador pedirá confirmación. Acéptala.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7zo2l3e5od9ony90mrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7zo2l3e5od9ony90mrk.png" alt="Bot Emulator prompt" width="397" height="237"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Una vez inicies sesión notarás que &lt;strong&gt;no te pide autorizar permisos&lt;/strong&gt; ya que  lo hemos hecho en alguna de las opciones ofrecidas anteriormente. Si iniciaste sesión exitosamente recibirás estos mensajes, dile que sí para que te muestre el token de usuario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcser2g6k2b5oyeoxfqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcser2g6k2b5oyeoxfqt.png" alt="Login exitoso" width="338" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7z6dzxedt81n40ahird.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7z6dzxedt81n40ahird.png" alt="Token de usuario" width="302" height="247"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Eso es todo! hemos conectado un Bot de Microsoft Bot Framework con Azure Active Directory para realizar la autenticación.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>authentication</category>
      <category>azure</category>
      <category>csharp</category>
    </item>
    <item>
      <title>C# - la palabra clave volatile</title>
      <dc:creator>Juan Carlos Ruiz Pacheco</dc:creator>
      <pubDate>Mon, 02 Dec 2019 05:59:38 +0000</pubDate>
      <link>https://dev.to/juankruiz/c-la-palabra-clave-volatile-2ib4</link>
      <guid>https://dev.to/juankruiz/c-la-palabra-clave-volatile-2ib4</guid>
      <description>&lt;p&gt;La palabra clave &lt;code&gt;volatile&lt;/code&gt; es una de esas palabras clave muy pocas veces comprendidas, la documentación permite concluir que hay que utilizarla siempre que se manejen hilos, pero esto no siempre es así.&lt;/p&gt;

&lt;p&gt;Sin embargo lograr identificar que es lo que hace realmente esta palabra clave es una labor complicada así que dedicaré este artículo a explorar esta funcionalidad y a crear un ejemplo práctico que permita entender su verdadera naturaleza.&lt;/p&gt;

&lt;h2&gt;
  
  
  La documentación
&lt;/h2&gt;

&lt;p&gt;En &lt;strong&gt;docs&lt;/strong&gt; encontramos la siguiente definición de la palabra clave &lt;code&gt;volatile&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;La palabra clave volatile indica que varios subprocesos que se ejecutan a la vez pueden modificar un campo. Los campos que se declaran como volatile no están sujetos a optimizaciones del compilador que suponen el acceso por un subproceso único. Esto garantiza que el valor más actualizado está en todo momento presente en el campo&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Revisa acá la &lt;a href="https://docs.microsoft.com/es-es/dotnet/csharp/language-reference/keywords/volatile" rel="noopener noreferrer"&gt;referencia completa&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Debemos resaltar dos aspectos importantes de ese texto:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Se menciona que los campos &lt;code&gt;volatile&lt;/code&gt; no son susceptibles de optimizaciones por parte del compilador. &lt;strong&gt;Cuales optimizaciones?&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Dice que esto garantiza que el valor más actualizado siempre esta presente en el campo. &lt;strong&gt;No se supone que esto es así siempre?&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A continuación revisaremos estas dos preguntas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizaciones del compilador
&lt;/h2&gt;

&lt;p&gt;Siempre que compilamos un programa hecho con C# el compilador se encarga de convertir ese código C# en código de lenguaje &lt;strong&gt;IL&lt;/strong&gt;, bueno realmente en OpCodes de IL.&lt;/p&gt;

&lt;p&gt;Esto es así de sencillo, pero resulta que cuando compilamos nuestro código en la configuración release o más específicamente cuando se marca la casilla de Optimizar código en el proyecto (ver imagen) el  compilador realiza una revisión general del código par determinar que cosas puede hacer funcionar de una manera mejor a la que codificó el programador inicialmente, o incluso como puede cambiar cosas en el ejecutable que no están en manos del programador ni del propio lenguaje para que el programa sea más eficiente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0pdi8qv0l7x0jv8ecygu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0pdi8qv0l7x0jv8ecygu.png" alt="Checkbox Optimizar código" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Usando la línea de comandos podemos también adicionar &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/optimize-compiler-option" rel="noopener noreferrer"&gt;optimize&lt;/a&gt; en los modificadores del compilador.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ejemplo
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;csc t2.cs -optimize&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Estas optimizaciones son calculadas por el compilador haciendo uso de un complejo juego de reglas algunas de las cuales dependen de la arquitectura del procesador ( x86, x64, IA64, etc) y algunas otras del modelo de memoria que se esta trabajando.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Los modelos de memoria son un tema complejo incluso desde sus fundamentos si bien no es algo imposible de aprender, pero quien quiera puede profundizar un poco más al respecto puede leer el libro de &lt;a href="https://amzn.to/33FgYZa" rel="noopener noreferrer"&gt;Sistemas Operativos Modernos de Andrew Tanembaum&lt;/a&gt;  y desde luego buscar referencias adicionales en internet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/Modern-Operating-Systems-3rd-Edition/dp/0136006639/ref=as_li_ss_il?ie=UTF8&amp;amp;linkCode=li3&amp;amp;tag=juank-20&amp;amp;linkId=4cd0a0a2abd986a6d4bc309a4dde322f&amp;amp;language=es_US" rel="noopener noreferrer"&gt;&lt;img src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;ASIN=0136006639&amp;amp;Format=_SL250_&amp;amp;ID=AsinImage&amp;amp;MarketPlace=US&amp;amp;ServiceVersion=20070822&amp;amp;WS=1&amp;amp;tag=juank-20&amp;amp;language=es_US"&gt;&lt;/a&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fir-na.amazon-adsystem.com%2Fe%2Fir%3Ft%3Djuank-20%26language%3Des_US%26l%3Dli3%26o%3D1%26a%3D0136006639" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fir-na.amazon-adsystem.com%2Fe%2Fir%3Ft%3Djuank-20%26language%3Des_US%26l%3Dli3%26o%3D1%26a%3D0136006639" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adicionalmente a las optimizaciones realizadas por el compilador de C# tenemos una segunda etapa de compilación y optimizaciones realizadas por el JIT al momento de ejecutarse el programa, las cuales tiene su propio conjunto de reglas algunas de las cuales también están influenciadas por la arquitectura del procesador y el modelo de memoria.&lt;/p&gt;

&lt;h2&gt;
  
  
  El Valor Actualizado
&lt;/h2&gt;

&lt;p&gt;Parte de las optimizaciones realizadas por el compilador pueden evitar que en algún momento determinado los campos de memoria donde se encuentran las variables no sean actualizados con su valor más reciente, porque?&lt;/p&gt;

&lt;p&gt;Cada vez que el procesador hace una operación necesita colocar el valor de las variables en uno de sus registros, de tal forma que si tenemos por ejemplo un bucle con una suma de esta manera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condicion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El procesador enviaría el valor de &lt;strong&gt;i&lt;/strong&gt; a uno de sus registros y el valor &lt;strong&gt;1&lt;/strong&gt; en otro registro, al obtener el valor de la suma el procesador debe colocar este valor de nuevo en memoria en la variable &lt;strong&gt;i&lt;/strong&gt; de tal forma que al continuar el bucle todo el proceso se repite.&lt;/p&gt;

&lt;p&gt;Esta secuencia sin embargo puede ser optimizada por el compilador ya que se hace innecesario que el valor de &lt;strong&gt;i&lt;/strong&gt; sea copiado de los registros de la CPU a la memoria y viceversa tantas veces como dure el bucle, así que el compilador genera un código ejecutable que permite que los cálculos sean hechos en su totalidad en los registros de la CPU y solo hasta salir del bucle estos datos serian copiados de nuevo a la memoria.&lt;/p&gt;

&lt;p&gt;Este tipo de optimizaciones que usan &lt;strong&gt;cache&lt;/strong&gt;  trae una mejora considerable en la ejecución de procesos intensivos a nivel matemático y funcionan bastante bien en la mayoría de los escenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizaciones de cache y el problema de los hilos
&lt;/h2&gt;

&lt;p&gt;Cuando el compilador esta realizando las optimizaciones analiza todo lo que pueda hacer referencia a las variables en el contexto del &lt;strong&gt;subproceso&lt;/strong&gt; (hilo) actual.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Realmente en la mayoría de sistemas operativos no se ejecutan los procesos sino los subprocesos y se le llama proceso a un grupo de subprocesos que comparten la memoria.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Con base en lo analizado realiza las optimizaciones, por ello el problema surge cuando un hilo ("nuevo") trata de acceder al valor de una variable que esta siendo modificada en un hilo ("inicial") diferente.&lt;/p&gt;

&lt;p&gt;Es posible que el hilo "inicial" se encuentre en  medio de una rutina optimizada para funcionar por &lt;strong&gt;cache&lt;/strong&gt; (en los registros de la CPU) y al no estar copiando el valor de la variable de nuevo en memoria tras cada operación, el hilo "nuevo" no verá los cambios realizados.&lt;/p&gt;

&lt;p&gt;Así que en escenarios donde existan múltiples hilos lo ideal es bloquear este tipo de optimizaciones y estar muy atento a los casos donde no sea conveniente inactivarlas pues hay casos para todo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Código de ejemplo
&lt;/h2&gt;

&lt;p&gt;Bien después de la teoría vamos a la práctica, veremos ejemplos donde &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;volatile&lt;/strong&gt; no sirve para nada y creo que son la mayoría de casos en el mundo real – al menos en CPUs x86 ya que en IA64 al parecer el tema es muy diferente)&lt;/li&gt;
&lt;li&gt;casos que de acuerdo a la teoría que acabamos de ver funciona perfectamente &lt;strong&gt;desde que lo compiles en modo Release y para x86&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Ejemplo 1
&lt;/h3&gt;

&lt;p&gt;Este es el ejemplo típico, donde todos usamos volatile porque así lo dice la documentación pero la realidad es que en estos casos no sirve de NADA.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BackgroundTaskDemo&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//volatile&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;stopping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EfectuarTrabajo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;stopping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Main exit"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EfectuarTrabajo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valor de i="&lt;/span&gt;&lt;span class="p"&gt;+&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"EfectuarTrabajo exit "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podríamos poner a &lt;strong&gt;i&lt;/strong&gt; como &lt;code&gt;volatile&lt;/code&gt; pero no habría diferencia puesto que básicamente el código no necesita ni tiene como ser optimizado. Así que &lt;code&gt;volatile&lt;/code&gt; no bloquearía ninguna optimización.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ejemplo 2
&lt;/h3&gt;

&lt;p&gt;Este es el ejemplo tampoco sirve de NADA, si bien en el bucle se ve la necesidad de optimizar el rendimiento del código evitando que se copie el valor de i o de stopping de los registros de la CPU a la memoria y viceversa.&lt;/p&gt;

&lt;p&gt;Resulta que al convertir &lt;strong&gt;i&lt;/strong&gt; a string estamos forzando al compilador a que no utilice el cache dado que necesita el valor mas reciente de &lt;strong&gt;i&lt;/strong&gt; en la memoria para poder llamar el método &lt;code&gt;ToString()&lt;/code&gt; y al método &lt;code&gt;WriteLine()&lt;/code&gt;.&lt;br&gt;
Adicionalmente al llamar a alguno de esos métodos se requiere colocar en los registros de la CPU los valores necesarios para cambiar de contexto y para poder ejecutar las operaciones internas de dichos métodos, así que no hay manera de optimizar nada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BackgroundTaskDemo&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//volatile&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;stopping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EfectuarTrabajo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;stopping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Main exit"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EfectuarTrabajo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;stopping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++;&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valor de i="&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"EfectuarTrabajo exit "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nuevamente podríamos ponerle a &lt;strong&gt;i&lt;/strong&gt; como &lt;code&gt;volatile&lt;/code&gt; pero no habría diferencia puesto que básicamente el código no necesita ni tiene como ser optimizado. Así que &lt;code&gt;volatile&lt;/code&gt; no bloquearía ninguna optimización.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ejemplo 3
&lt;/h3&gt;

&lt;p&gt;En este si que funcionan las optimizaciones! pero el programa no funcionará ya que ambas variables caen en la optimización.&lt;/p&gt;

&lt;p&gt;El compilador optimizara el uso de &lt;strong&gt;i&lt;/strong&gt; para que se apoye en los registros del procesador de principio a fin, eso es perfecto!.&lt;/p&gt;

&lt;p&gt;Pero por otro lado la variable &lt;strong&gt;stopping&lt;/strong&gt; también es optimizada, trayendo como resultado que siempre este en uno de los registros y por tanto los hilos &lt;em&gt;nunca&lt;/em&gt; se enteren en que momento &lt;strong&gt;stopping&lt;/strong&gt; cambio de valor para que saliera del bucle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BackgroundTaskDemo&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;stopping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EfectuarTrabajo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;stopping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Main exit"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EfectuarTrabajo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valor de i="&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;stopping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valor de i="&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"EfectuarTrabajo exit "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al ejecutar la version &lt;strong&gt;release para x86&lt;/strong&gt; de este programa veremos como, aunque en código parece que todo saldrá bien, al ejecutarse el programa este nunca terminara pues el hilo nunca se entera que &lt;strong&gt;stopping&lt;/strong&gt; cambió su valor. En pantalla veríamos perpetuamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Main Exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y nada más :(.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ejemplo 4
&lt;/h3&gt;

&lt;p&gt;Dado que el ejemplo anterior nos muestra como se activan las optimizaciones de código del compilador, es tiempo de evitarlas haciendo uso de volatile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BackgroundTaskDemo&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;stopping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EfectuarTrabajo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;stopping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Main exit"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EfectuarTrabajo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valor de i="&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;stopping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valor de i="&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"EfectuarTrabajo exit "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora si en pantalla veremos el resultado esperado&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Main Exit
EfectuarTrabajo exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;:D&lt;/p&gt;

&lt;h3&gt;
  
  
  Ejemplo 5
&lt;/h3&gt;

&lt;p&gt;Este es el mismo ejemplo anterior pero un poco mas elaborado haciendo uso de algunas operaciones de System.Math las cuales son suceptibles de optimización por el compilador.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BackgroundTaskDemo&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//volatile&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt;  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;stopping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EfectuarTrabajo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;stopping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Main exit"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EfectuarTrabajo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;stopping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++;&lt;/span&gt;
            &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sin&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;10d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"EfectuarTrabajo exit "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prueba quitando y poniendo volatile y verás la diferencia claramente. &lt;br&gt;&lt;br&gt;
HAS PRUEBAS Y COMPARTE TUS EJEMPLOS&lt;/p&gt;

&lt;p&gt;Hasta la próxima!.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
