miércoles, 10 de diciembre de 2014

MVC como asegurarse de que los cuadros de dialogo de JQuery respeten el alto asignado en la propoedad Height

Tenía el siguiente problema:

 

Cuando levantaba un cuadro de dialogo, para crear un nuevo concepto de la funcionalidad que estaba administrando, la primera vez, el cuadro de dialogo salía del tamaño apropiado, pero las siguientes veces, el alto iba disminuyendo hasta convertirse en un problema, como se evidencia en las imágenes:

Primera vez:

1

Segunda vez:

2

 

Lo cual generaba un problema, a la hora de mostrar los mensajes de validación:

3

Esto se arregló asegurandose de colocar los campos de captura de información , contenidos en la etiqueta

<fieldset>

<fieldset>
    <div class="form-group">
        <label for="caso" class="col-sm-3 control-label" style="margin-left:10px;margin-top:10px;"> @Views.Labels.EtiquetaDenominacionDelito</label>
        <div class="col-sm-8" style="margin-top:10px;">
            @Html.TextBoxFor(model => model.Nombre, new { id = "txtDelito", @class = "form-control" })
            @Html.ValidationMessageFor(model => model.Nombre)
        </div>

    </div>

</fieldset>

 

martes, 9 de diciembre de 2014

MVC asegurarse de que la validación de campos funcione en formas que cargan en cuadros de dialogo de JQuery

Cuando se ejecutan las pantalla desde fuentes, usando Visual Studio, para que salgan los mensajes de validación sobre los campos, es suficiente con colocar una expresión del tipo:

$('#frmDelito').valid()

Para activar el plug in de validación y que los mensajes se muestren.

Pero esto no funciona, cuando el sitio se despliega en un host.

Para que funcione la validación en dicho caso, es decesario, hacer el llamado al método valid de la forma, de esta manera:

var $form = $('#frmDelito');
$.validator.unobtrusive.parse($form);
if ($form.valid()) {

 

Technorati Tags: ,,

MVC formas de hacer un llamado para la ejecución de una operación asíncrona

Este post es para indicar la forma de hacer llamados a operaciones asincronas en MVC por medio de JavaScript o JQUERY y de esta forma darle dinamismo a tus aplicaciones.

 

1. Funciona solo en navegadores Microsoft de nueva generación y garantiza el funcionamiento entre sitios o Cross Site.

                                         var ua = window.navigator.userAgent;
                                         var msie = ua.indexOf("MSIE ");
                                         if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)){
                                             // Use Microsoft XDR
                                             var params = "";
                                             var xdr = new XMLHttpRequest();
                                             var data = "?nombre=" + nombreDespacho + "&tipo=" + tipoDespacho + "&ubicacion=" + ubicacionDespacho  + "&direccion=" + direccionDespacho + "&telefono=" + telefonoDespacho;
                                             var url;
                                             var pathArray = window.location.pathname.split('/');
                                             if (pathArray[1].toLowerCase() == "procesos") {
                                                 url = "/procesos/AddDespachoUsingAttributes" + data;
                                             } else {
                                                 url = "/" + pathArray[1] + "/procesos/AddDespachoUsingAttributes" + data;
                                             }
                                             xdr.open("GET", url, true);
                                             xdr.setRequestHeader("Access-Control-Allow-Origin", "*");

                                             xdr.onload = function () {
                                                 var JSON = $.parseJSON(xdr.responseText);
                                                 CrearDespacho(JSON);
                                             };

                                             xdr.onreadystatechange = function () {
                                                 if (xdr.readyState == 4 && xdr.status == 200) {
                                                     //obj.innerHTML = XMLHttpRequestObject.responseText;
                                                 }
                                             }
                                             xdr.send(null);
                                         }

Es muy importante, la determinación del URL, si el sitio se ejecuta desde fuentes, en el URL no está el nombre del sitio, mientras que se si se ejecuta desde un despliegue, si hay nombre de sitio.

2.Usando la función de JQuery $.Ajax, que tiene los beneficios de usarla, pudiendo hacer uso de más parámetros como la configuración del manejo de caché, si es requerido:

var url;
var pathArray = window.location.pathname.split('/');
if (pathArray[1].toLowerCase() == "procesos") {
    url = "/procesos/AddDespachoUsingAttributes";
} else {
    url = "/" + pathArray[1] + "/procesos/AddDespachoUsingAttributes";
}
$.ajax({
    url: url,
    data: { nombre: nombreDespacho, tipo: tipoDespacho, ubicacion: ubicacionDespacho, direccion: direccionDespacho, telefono: telefonoDespacho },
    type: "GET",
    dataType: "json",
    success: function (despachosData) {
        CrearDespacho(despachosData);
    },
    cache: false
});

 

3. Usando la función de  JQuery $.getJSON:

var url;
var pathArray = window.location.pathname.split('/');
if (pathArray[1].toLowerCase() == "procesos") {
    url = "/procesos/AddDespachoUsingAttributes";
} else {
    url = "/" + pathArray[1] + "/procesos/AddDespachoUsingAttributes";
}
$.getJSON(url, { nombre: nombreDespacho, tipo: tipoDespacho, ubicacion: ubicacionDespacho, direccion: direccionDespacho, telefono: telefonoDespacho },
              function (despachosData) {
                  var select = $("#ddlDespacho");
                  select.children('option:not(:first)').remove();
                  $.each(despachosData, function (index, itemData) {
                      var isItemSelected = seleccionarOpcionDespacho(itemData.Value);
                      select.append($('<option/>', {
                          value: itemData.Value,
                          text: itemData.Text,
                          selected: isItemSelected
                      }));

                  });

              });

 

sábado, 22 de noviembre de 2014

Problema Java.Lang.ClassNotFoundException con Xamarine.Forms Plataforma Android

Para comentar en esta entrada el problema que tuve haciendo el Hello World de Xamarine.Forms para Android.

Sale el problema:

Java.Lang.ClassNotFoundException: android.animation.ValueAnimator in loader dalvik.system.PathClassLoader[/data/app/HelloXamarineFormsWorld.Android-1.apk]

 

Esto me salió para el emulador:

MonoForAndroid_API_10

Busqué en Internet, pero no pude encontrar una solución.

Así que intenté elegir otro emulador, pero solo tenía 2 opciones, en el Visual Studio:

6

Y el otro no corresponde a un teléfono sino a una Tablet.

Intenté crear otros emuladores, por la opción Create.., pero los aparatos que elegía, unos no tenían asociada CPU o la CPU no era adecuada.

7

Me di cuenta, al entrar a la administración del SDK de Android:

8

4

Que faltaban unos paquetes para instalar.

Y los instalé:

5

Cuando hice esto, pude crear un nuevo emulador así:

9

Observar que no se eligió Device.

Al cerrar el Visual Studio y volver a cargarlo, aparece el nuevo emulador:

10

Al hacer el Deploy a este emulador, el aplicativo funciona:

11

 

Es decir, se puede decir que es un error asociado al emulador seleccionado, luego la solución es usa otro emulador.

sábado, 4 de octubre de 2014

Visual Studio 2012 Backup and Restore bases de datos

 

Este post será de utilidad para aquellos que como yo, no pueden contar con SQL Server Management Studio en su ambiente de Windows 8 y Visual Studio 2012 instalados. Al intentar instalar el SQL Server Management Studio, sale un error, durante el proceso de instalación, donde se indica que se debe activar la característica de Windows asociada al ASP:NET 3.5. Traté muchas cosas y no pude realizar la instalación. Cabe anotar que mi Windows 8 está en una máquina virtual, por lo que las soluciones que publican en Internet es posible que nunca me funcionen.

La idea o problema que tengo, afortunadamente, no es que deba instalar el SQL Server Management Studio, mi problema es interactuar con la instancia de SQLEXPRESS que sí pude instalar. Lo que deseo es probar un despliegue de una aplicación MVC. Desde fuentes funciona bien porque se conecta a la Base de datos que hay en el servidor de desarrollo LocalDB, nuevo concepto en Visual Studio 2012, para permitir la interación con datos. Sin embargo, en el despliegue, no se reconoce el Servidor asociado a LocalDB, por lo cual la necesidad es instalar la BD en la instancia de SQLEXPRESS a donde si se puede conectar la aplicación, en el despliegue realizado.

La idea entonces es pasar la BD que hay en la LocalDB de Visual Studio 2012 a la instancia de SQLEXPRESS.

Encontré la forma y es:

1. Sacar un backup de la Base de datos que nos interesa, usando la instrucción:

use IURIS
GO
BACKUP DATABASE IURIS TO DISK = 'C:\Dirtrab\Temp\IURIS.bak'
GO

Este comando se ejecuta, en la ventana de new query, asociada al menú SQL –> Transact-SQL Editor –> New query

2, Conectarse usando Visual Studio 2012 a la instancia de SQLEXPRESS

VS2012BackRestore1

Nos conectamos a la BD master´.

Seleccionamos la conección y de nuevo elegimos una ventana asociada a New Query:

VS2012BackRestore2

3. Ejecutamos el comando Restore de esta forma:

RESTORE FILELISTONLY FROM DISK = 'C:\Dirtrab\Temp\IURIS.bak'
GO

RESTORE DATABASE IURIS FROM DISK = 'C:\Dirtrab\Temp\IURIS.bak'
WITH
   MOVE 'IURIS' TO 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\IURIS.mdf',
   MOVE 'IURIS_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\IURIS.ldf'
GO

martes, 16 de septiembre de 2014

Profiler al estilo Oracle

 

 

Bueno aunque no es un buen título para el post, esa es la idea.

La idea es recordar esta sentencia de Oracle que permite obtener la información de las sentencias que se ejecutan en una base de datos Oracle. Ello sirve para rastrear y buscar posibles problemas con nuestras aplicaciones, verificar como se ejecutan las sentencias o como son traducidas estas, pues recordemos que muchas veces usamos lenguajes de manipulación de objetos como LinQ.

La sentencia es la siguiente:

SELECT           
S.LAST_ACTIVE_TIME,    
S.MODULE,
S.SQL_TEXT,
S.SQL_PROFILE,
S.EXECUTIONS,
S.LAST_LOAD_TIME,
S.PARSING_USER_ID,
S.SERVICE                                                                      
FROM
SYS.V_$SQL S,
SYS.ALL_USERS U
WHERE
S.PARSING_USER_ID=U.USER_ID
AND UPPER(U.USERNAME) IN ('GTC')  
and  S.LAST_ACTIVE_TIME >  to_date('2014-09-16 09:25:17','yyyy-MM-dd HH24:MI:SS')
ORDER BY S.LAST_ACTIVE_TIME desc;

 

Se puede modificar la fecha, para traer solo la información que nos interesa, también se debe modificar el usuario de base datos que estemos usando.

miércoles, 28 de mayo de 2014

Trucos de Servicio Windows. Como lograr que, tras correr el setup de instalación, aparezca el servicio en la consola de servicios de Windows.

 

Para lograr esto se debe hacer este truco, sobre el proyecto de instalación del servicio Windows, dar click derecho, seleccionar View y luego Custom Actions:

1

 

En la ventana que aparece, se elige la raiz de las Custom Actions, se da click derecho y a continuación la opción de Agregar la CustomAction.

2

3

 

En el desplegable asociado a Look in, elegir Application Folder y presionar el botón OK:

4

5

 

Listo, cuando se genera el setup y se ejecuta en Windows, cuando se va a al consola de servicios de Windows, aparece el nombre del servicio.

domingo, 16 de marzo de 2014

Cápsula Windows Phone 8. Cajas Herramientas. ColorPicker y ColorSlider

 

En esta cápsula se explican los controles: ColorPicker y ColorSlider de la caja de herramientas Coding4Fun.

Espero que les guste.

 

viernes, 7 de marzo de 2014

Solución al problema: No se ha podido inscribir en una transacción distribuida.

 

Bueno, debido a que me costó muchas horas de esfuerzo, el ver como solucionar este problema. He decidio postear la solución.

Lo primero que hay que decir es que la causa de este problema es simplemente, que se alcanza el tiempo máximo para la completación del código en que la transacción está activa.

Por ejemplo en tu código tienes un bloque enmarcado en una transacción:

using (TransactionScope transaccion = new TransactionScope())
{


}

El proceso que se realice dentro del bloque de transacción debe demorarse máximo un tiempo dado. Si se demora más se genera la excepción:

No se ha podido inscribir en una transacción distribuida

Cuando no se encuentra en nuestras manos hacer que disminuya el tiempo del proceso, por ejemplo cuando llamamos a servicios y dependemos de que éstos nos entreguen sus respuestas. Es necesario, de común acuerdo con los responsables del tiempo de respuesta de dichos servicios, definir un tiempo máximo para que las transacciones permanezcan activas y modificar e incrementar en este caso el valor por defecto establecido.

Se encuentra que lo que se debe hacer para aumentar, este tiempo por defecto máximo, en que las transacciones se encuentren activas es:

1. Modificar el TimeOut asociado al MSDTC que por defecto está en 60 segundos (1 minuto). Esto es configuración de sistema operativo.

Aca como se hace en Windows 7.

Ir a la ruta:

Control Panel\System and Security\Administrative Tools\Component Services\Computers\My Computer y en MyComputer, click derecho y propiedades:

Repetidos2

En la Pantalla que sale, en el Tab Options:

Repetidos3

2. Modificar el código para especificar al TransactionScope un tiempo máximo para que la transacción permanezca activa.

            using (TransactionScope transaccion = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0,5,0)))

{

Nota: para mi necesidad particular se hizo la modificación para 5 minutos (300 segundos).

Nota importante: Para que el cambio del tiempo máximo en las transacciones tenga efecto, se deben hacer los pasos 1 y 2, sino se hacen los 2, se sigue obteniendo el problema de transacción distribuida.

lunes, 24 de febrero de 2014

Cápsula Windows Phone 8. Cajas Herramientas. SuperSlider y ColorHexagonPicker

 

En esta cápsula se explican los controles: SuperSlider y ColorHexagonPicker de la caja de herramientas Coding4Fun.

Espero que les guste.

 

Explicación de controles SuperSlider y ColorHexagonPicker

Trucos de los servicios Windows

 

El objetivo de este post es simplemente mostrar algunas cosas que es necesario realizar, para poder contar efectivamente con un servicio Windows.

1. Creamos un servicio windows a partir de una plantilla de Visual Studio.

4

2. El código generado incluye un archivo de servicio que hereda de ServiceBase. En este archivo colocamos el código que queremos se ejecute en el servicio windows.

5

3. Si creamos un proyecto de Setup e instalamos el servicio windows. En la consola de los servicios de Windows, no aparecerá el nombre de nuestro servico. Debemos asociarle a nuestro servicio un instalador.

En la vista de diseño de nuestro servicio, damos click derecho y elegimos Agregar instalador.

6

4. Esta acción crea un nuevo archivo que hereada de Instaler:

7

El código por defecto generado es este:

namespace PruebaCronTriggerServicioWindos
{
    [RunInstaller(true)]
    public partial class ProjectInstaller : System.Configuration.Install.Installer
    {
        public ProjectInstaller()
        {
            InitializeComponent();
        }
    }
}

Entonces, se modifica para definir las condiciones de instalación del servicio en la consola de servicios de Windows:

namespace PruebaCronTriggerServicioWindos
{
    [RunInstaller(true)]
    public partial class ProjectInstaller : System.Configuration.Install.Installer
    {
        /// <summary>
        /// Objeto que permite la instalación del servicio
        /// </summary>
        private ServiceInstaller _serviceInstaller;
        /// <summary>
        /// Proceso para la instalación del servicio de órdenes
        /// </summary>
        private ServiceProcessInstaller _serviceProcessInstaller;
        public ProjectInstaller()
        {
            _serviceProcessInstaller = new ServiceProcessInstaller();
            _serviceInstaller = new ServiceInstaller();

            _serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
            _serviceInstaller.StartType = ServiceStartMode.Automatic;
            _serviceInstaller.ServiceName = "Prueba CronTrigger Service";

            Installers.Add(_serviceProcessInstaller);
            Installers.Add(_serviceInstaller);
        }
    }
}

4. El instalador que creamos en el punto 3, tampoco se ejecuta automáticamente, cuando instalamos a través del Setup el servicio Windows.

Esta vez cuando instalamos el servicio windows, en la ruta de instalación, donde el ejecutable queda:

8

Usamos la consola de DOS y ejecutamos como Administrador y utilizamos el comando:

installutil.exe MyNewService.exe

De esta forma podremos ver el servicio en la consola de Windows.

Para desinstalar el servicio, se usa este comando:

InstallUtil.exe /u MyNewService.exe

Configuración de expresiones en Quartz

 

Quartz es un framework o librería que podemos utilizar para indicar, de una manera fácil, cada cuanto queremos que se ejecute un proceso determinado.

Se debe usar Quartz en conjunto con Spring. Es a través de Spring como se logra injectar a través de configuración los objetos, que realizan la ejecución del proceso determinado.

Lo que hace Quartz es posibilitar la configuración de expresiones o la indicación por medio de propiedades de la periodicidad con que se ejecutará el proceso definido y es en últimas el encargado de la ejecución periodica. Haciendo uso de Quartz ya no es necesario, utilizar cosas como Timers y manejarlas nosotros mismos, por lo cual nos vuleve más productivos.

A continuación  un ejemplo de consola, pero antes una breve explicación, del conflicto de versiones de asemblies que se les puede presentar, como de hecho se me presentó a mi.

Se deben usar los asemblies de Spring:

Spring.Aop.dll

Spring.Core.dll

Spring.Data.dll

Spring.Scheduling.Quartz.dll

También se requiere usar la librería:

Common.Logging.dll ( que viene en la distribución o download de las librerías de Spring).

Finalmente, se debe referenciar el Assembly de Quartz:

Quartz.dll

Aca lo importante, para evitar conflictos, es fijarse en las versiones. En mi caso, cuando por fin logré superar el conflicto de versiones, estas son las versiones de los assemblies:

Assemblies de Spring, versión 1.3.1.40711.

Assemblie Common.Logging, versión 1.2.0.0

Assemblie Quartz, versión 1.0.3.3

Teniendo esto claro, ahora así el ejemplo de consola:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Presione enter para ingresar el número a través del servicio");
        Console.ReadKey();

      
try
       
{
            XmlApplicationContext ctx = new XmlApplicationContext("spring-objects.xml");
            Console.WriteLine("Spring configuración exitosa, qurtz jobs running");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            Console.Out.WriteLine("---Presione enter para salir---");
            Console.ReadLine();
        }

        Console.Out.WriteLine("---Presione enter para salir---");
        Console.ReadLine();

    }
}

El programa consiste entonces en usar la clase XmlApplicationContext de Spring, para ejecutar en dicho contexto, los objetos configurados declarativamente en el archivo spring-objects.xml.

El archivo de objetos, en este caso, posee la siguiente declaración de objetos:

<?xml version="1.0" encoding="utf-8" ?>
<
objects xmlns="http://www.springframework.net"
xmlns:aop="http://www.springframework.net/aop"
xmlns:db="http://www.springframework.net/database"
xmlns:tx="http://www.springframework.net/tx">
<!--
Scheduling Task -->
<
object name="MyJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
<
property name="JobType" value="PruebaCronTrigger.MyJob, PruebaCronTrigger"/>
<
property name="JobDataAsMap">
<
dictionary>
<
entry key="UserName" value="Ingecaam"></entry>
</
dictionary>
</
property>
</
object>

<
object id="JobService" type="PruebaCronTrigger.JobService, PruebaCronTrigger">
<
property name="UserName" value="Ingecaam"/>
</
object>

<
object id="jobDetail" type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz">
<
property name="TargetObject" ref="JobService" />
<
property name="TargetMethod" value="DoJobWork" />
<
property name="Concurrent" value="false" />
</
object>

<
object id="JobSimpleTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz">
<
property name="jobDetail" ref="jobDetail" />
<
property name="startDelay" value="5s" />
<
property name="repeatInterval" value="5s" />
</
object>

<
object id="JobCronTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz">
<
property name="jobDetail" ref="MyJob" />
<
property name="cronExpressionString" value="0/20 * * * * ?" />
</
object>

<
object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
<
property name="triggers">
<
list>
<
ref object="JobCronTrigger" />
<!--
<ref object="JobSimpleTrigger" />-->
</
list>
</
property>
</
object>
</
objects>

Aquí, hay varias cosas a explicar:


1. Lo que hace Quartz es ejecutar las tareas que se le definan, las tareas se le definen en el objeto SchedulerFactoryObject:

<object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
<
property name="triggers">
<
list>
<
ref object="JobCronTrigger" />
<!--
<ref object="JobSimpleTrigger" />-->
</
list>
</
property>
</
object>
En el ejemplo, solo se le define la tarea asociada a un objeto del tipo CronTriggerObject.

2. Las tareas que se definen pueden ser de 2 tipos CronTriggerObject y SimpleTriggerObject.


SimpleTriggerObject

<object id="JobSimpleTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz">
<
property name="jobDetail" ref="jobDetail" />
<
property name="startDelay" value="5s" />
<
property name="repeatInterval" value="5s" />
</
object>

CronTriggerObject

<object id="JobCronTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz">
<
property name="jobDetail" ref="MyJob" />
<
property name="cronExpressionString" value="0/20 * * * * ?" />
</
object>

Como vemos, al utilizar un SimpleTriggerObject podemos de una manera sencilla configurar por medio de propiedades (startDelay y repeatInterval) la periodicidad con la que queremos que se ejecute la tarea, en el caso del ejemplo cada 5 segundos.


No obstante también disponemos del CronTriggerObject que es más robusto y nos permite por medio de expresiones, definir una periodicidad basada en calendario, se pueden especificar periodicidades como: todos los viernes al mediodía", o "todos los días laborables y de 9:30 am", o incluso "cada 5 minutos 09 a.m.-10 a.m. todos los lunes, miércoles y viernes durante enero".


3. En la propiedad ref de ambos tipos de tarea, se indican los objetos donde se configuran los objetos y métodos que ejecutan las tareas dadas.


Por ejemplo, para el SimpleTriggerObject tenemos:

<object id="jobDetail" type="Spring.Scheduling.Quartz.MethodInvokingJobDetailFactoryObject, Spring.Scheduling.Quartz">
<
property name="TargetObject" ref="JobService" />
<
property name="TargetMethod" value="DoJobWork" />
<
property name="Concurrent" value="false" />
</
object>

Como se puede ver, se configura el objeto y el método que se ejecuta periodicamente. El método es el DoJobWork y el objeto es el que se configura en este otro objeto declarado de Spring:

<object id="JobService" type="PruebaCronTrigger.JobService, PruebaCronTrigger">
<
property name="UserName" value="Ingecaam"/>
</
object>

Aca sí se configura el objeto y además se le puede asignar valor a una de sus propiedades, el objeto JobService en este caso es el del siguiente código:

namespace PruebaCronTrigger
{
public class JobService
{
private string _username;

public string Username
{
get { return _username; }
set { _username = value; }
}

public void DoJobWork()
{
Console.WriteLine("{0} DoJobWork llamado, user name: {1}", DateTime.Now, _username);
}
}
}

Vemos como posee la propiedad UserName, el método DoJobWork  y el nombre de su namespace es PruebaCronTrigger.


Cuando en la lista de las tareas, solo se configura el SimpleTriggerObject:

<object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
<
property name="triggers">
<
list>
<!--
<ref object="JobCronTrigger" />-->
<
ref object="JobSimpleTrigger" />
</
list>
</
property>
</
object>

La salida del programa es:


1


Para el caso del CronTriggerObject el objeto que se referencia es:

<object name="MyJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
<
property name="JobType" value="PruebaCronTrigger.MyJob, PruebaCronTrigger"/>
<
property name="JobDataAsMap">
<
dictionary>
<
entry key="UserName" value="Ingecaam"></entry>
</
dictionary>
</
property>
</
object>

Y en este caso, el objeto con nuestro código que hará el proceso que se realizará periodicamente, es el siguiente:

namespace PruebaCronTrigger
{
public class MyJob : QuartzJobObject
{
private string _userName;

public string UserName
{
get { return _userName; }
set { _userName = value; }
}

protected override void ExecuteInternal(Quartz.JobExecutionContext context)
{
Console.WriteLine("{0}: ExecuteInternal llamado, user name:{1}, next fire time {2}", DateTime.Now, _userName, context.NextFireTimeUtc.Value.ToLocalTime());
}



}
}

En este caso, lo que se ejecuta periodicamente, es lo que se coloqué en la sobreescritura del método ExecuteInternal. La periodicidad se define por medio de una expresión en la propiedad cronExpressionString del objeto CronTriguerObject.

<object id="JobCronTrigger" type="Spring.Scheduling.Quartz.CronTriggerObject, Spring.Scheduling.Quartz">
<
property name="jobDetail" ref="MyJob" />
<
property name="cronExpressionString" value="0/20 * * * * ?" />
</
object>

En este caso la expresión configurada de periodicidad es esta:


0/20 * * * * ?


Lo que significa cada 20 segundos, por tanto, si en la lista de tareas solo se configura la tarea asociada al CronTriggerObject:

<object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
<
property name="triggers">
<
list>
<
ref object="JobCronTrigger" />
<!--
<ref object="JobSimpleTrigger" />-->
</
list>
</
property>
</
object>

La salida del programa es:


2


Adicionalmente, podemos configurar varias tareas para ejecutar en difentes momentos y las podemos conbinar de los 2 tipos. Esto da aún más flexibilidad y nos ayuda a contruir aplicaciones, donde debemos lanzar procesos de forma periodica.


Por ejemplo, al configurar ambas tareas, la del BasicTriggerObject y la del CronTriggerObject:









<object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
  <
property name="triggers">
    <
list>
      <
ref object="JobCronTrigger" />
      <
ref object="JobSimpleTrigger" />
    </
list>
  </
property>
</
object>


La salida del programa es esta:


3


Nota: para que el ejemplo te funcione, asegurate que el archivo spring-objects.xml tenga definido el BuildAction a Content.


La expresión de periodicidad usada en este ejemplo es:


0/20 * * * * ?


Esto significa cada 20 segundos. Es importante, entonces, a la hora de necesitar configurar una periodicidad conocer muy bien como se construyen este tipo de expresiones. A continuación, una guía.


Expresiones Cron


Las expresiones Cron se utilizan para configurar las instancias de CronTrigger. Son cadenas que en realidad están hechas de siete sub-expresiones, que describen los detalles particulares de la programación. Estas sub-expresiones se separan por un espacio en blanco, y representan:

1. Segundos

2. Minutos

3. Horas

4. Día del mes

5. Mes

6. Día de la semana

7. Año (campo opcional)

Un ejemplo de una cron-expresión completa es la cadena "0 0 12 * WED" - que significa "todos los miércoles a las 12:00:00 pm".

Las sub-expresiones individuales pueden contener rangos y / o listas. Por ejemplo, el campo asociado al día de la semana en el ejemplo anterior (que se lee "WED") podría sustituirse por "MON-FRI", "MON, WED, FRI", o incluso "MON-WED, SAT".

Caracteres comodín (el *) se puede utilizar para decir "todo" posible valor de este campo. Por lo tanto, el carácter * en el campo "Mes" del ejemplo anterior simplemente significa "cada mes". Un '*' en el campo el día de la semana por lo tanto, obviamente, significa "todos los días de la semana".

Todos los campos tienen un conjunto de valores válidos que se pueden especificar. Estos valores podrían ser bastante obvios - como los números de 0 a 59 para el segundo y minutos, y los valores de 0 a 23 por hora. Día de mes puede ser cualquier valor de 1 a 31, pero hay que tener cuidado con la cantidad de días hay en un mes!. Los meses se pueden especificar como valores de entre 0 y 11, o mediante el uso de las cadenas JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV y DEC. Los días de la semana se puede especificar como valores entre 1 y 7 (1 = domingo) o mediante el uso de las cadenas SUN, MON, TUE, WED, THU, FRI y SAT.

El carácter '/' se puede utilizar para especificar incrementos en los valores. Por ejemplo, si pones ‘0 / 15’ en el campo de los minutos, que significa “cada 15 minutos de la hora, a partir del minuto cero”. Si se usa '3 / 20 'en el campo Minutos, significaría “cada 20 minutos de la hora, a partir del minuto 3” - o en otras palabras, es lo mismo que especificar '3, 23,43' en el campo Minutos. Tenga en cuenta la sutileza al usar estas expresiones; ‘/ 35’ no quiere decir "cada 35 minutos" - significa "cada 35 minutos de la hora, a partir de minuto cero" - en otras palabras, lo mismo que especificar '0, 35 '.

El '?' carácter está permitido para los campos de día de la semana y día de mes. Se utiliza para especificar "sin valor específico". Esto es útil cuando tiene que especificar algo en uno de los dos campos, pero no a la inversa. Vea los ejemplos a continuación para aclaración.

El carácter 'L' se permite para los campos de día de la semana y día de mes. Este caracterer es la manera corta de indicar “last”, pero tiene un significado diferente en cada uno de los campos. Por ejemplo, el valor "L" en el campo día de mes significa "el último día del mes" - día 31 de enero, el día 28 de febrero en años no bisiestos. Si se utiliza en el campo de día de la semana solo sin estar precedido por ningún valor, simplemente significa "7" o "SAT". Pero si se utiliza en el campo el día de la semana después de otro valor, significa "el último día del mes xxx" - por ejemplo, "6L" o "FRIL" significa tanto "el último viernes de cada mes". También puede especificar un desplazamiento desde el último día del mes, como "L-3", lo que significaría el tercer al último día del mes calendario. Cuando se utiliza la opción 'L', es importante que no se especifique listas o rangos de valores, ya que se pueden obtener resultados confusos o inesperados.

La 'W' se utiliza para especificar el día de la semana (lunes a viernes) más cercano al día. Por ejemplo, si usted tuviera que especificar "15W" como valor para el campo del día de mes, el significado es: "el día de la semana más cercano al día 15 del mes".

El "#" se utiliza para especificar "el enésimo" XXX día de la semana del mes. Por ejemplo, el valor del "6 # 3" o "FRI # 3" en el campo el día de la semana significa "el tercer viernes de cada mes".

He aquí unos cuantos ejemplos de expresiones y sus significados.

 

Ejemplo de expresiones Cron


Ejemplo CronTrigger 1 - expresión para crear un disparador (Trigger) que simplemente se dispara cada 5 minutos

"0 0/5 ***?"

CronTrigger Ejemplo 2 - expresión para crear un disparador que se activa cada 5 minutos, a los 10 segundos después del minuto (es decir, 10:00:10 am, 10:05:10 am, etc.)

"10 0/5 ***?"

Ejemplo CronTrigger 3 - expresión para crear un disparador que se activa a las 10:30, 11:30, 12:30 y 13:30, todos los miércoles y viernes.

"0 30 10-13? * WED,FRI"

CronTrigger Ejemplo 4 - expresión para crear un disparador que se activa cada media hora entre las horas de 8 am y las 10 am los días 5 y 20 de cada mes. Tenga en cuenta que el disparador no se dispara a las 10:00 am, justo a las 8:00, 08:30, 09:00 y 09:30

"0 0/30 8-9 5,20 *?"

CronTrigger Ejemplo 5.

Expresión para cumplir con el requerimiento:

Ejecutar el trabajo de lunes a viernes a las 6 am y 2 pm.

"0 0 6,14 * * MON, TUE, WED, THU, FRI"

CronTrigger Ejemplo 6.

Expresión para cumplir con el requerimiento:

Ejecutar el trabajo los sábados: a las 6 am y 10 am.

"0 0 6,10 * * SAT"

Tenga en cuenta que algunos de los requisitos de programación son demasiado complicados para expresarlos con un solo trigger - por ejemplo, "cada 5 minutos 09 a.m.-10 a.m., y cada 20 minutos 13:00-22:00". La solución en este caso es simplemente crear dos disparadores, y registrar los dos para ejecutar el mismo trabajo.

lunes, 10 de febrero de 2014

Cápsula Windows Phone 8. Cajas Herramientas. OpacityToggleButton, RoundToggleButton y RoundButton

 

En esta cápsula se explican los controles: OpacityToggleButton, RoundToggleButton y RoundButton de la caja de herramientas Coding4Fun.

Espero que les guste.

 

Controles OpacityToggleButton, RoundToggleButton y RoundButton

domingo, 26 de enero de 2014

Cápsula Windows Phone 8. Cajas Herramientas. PasswordInputPrompt, AppBarPrompt y ToastPrompt

 

En esta cápsula se explican los controles: PasswordInputPrompt, AppBarPrompt y ToastPrompt de la caja de herramientas Coding4Fun.

Espero que les guste.

Controles: PaswordInputPrompt, AppBarPrompt y ToastPrompt

viernes, 24 de enero de 2014

Trucos para NotePad++

 

1. Reemplazar un texto por la nueva linea. Se coloca el texto en el Find What y \n en Replace Width. Asegurandose de tener elegido la opción Regular Expression.

2. Colocar un texto al principio de cada línea.

Se buscó por el Replace y se encontró que colocando en el Find what ^ y el texto que se desea colocar al principio en el Replace Width y marcando la opción Regular Expression, al dar Replace, efectivamente lo que se coloca en el Replace Width queda al principio de la línea.

sin embargo, no se puede usar el Replace All, pues sale el error:

The regular expression to search is formed badly

Lo que se tuvo que hacer, fue:

Colocar el cursor al principio de la primera línea, presionar Alt + Shift y con la tecla del teclado (down – flecha abajo) seleccionar todas las líneas que queramos que tengan un determinado texto al principio, en este caso no es sino digitar el texto y el texto se aplicará a todas las líneas seleccionadas.

3. Colocar un texto al final de cada línea.

Se buscó por el Replace y se encontró que colocando en el Find what $ y el texto que se desea colocar al final en el Replace Width y marcando la opción Regular Expression, al dar Replace, efectivamente lo que se coloca en el Replace Width queda al final de la línea.

sin embargo, no se puede usar el Replace All, pues sale el error:

The regular expression to search is formed badly

Lo que se tuvo que hacer, fue:

Colocar el cursor al final de la primera línea, presionar Alt + Shift y con las tecla del teclado (down – flecha abajo) seleccionar todas las líneas que queramos que tengan un determinado texto al final, en este caso no es sino digitar el texto y el texto se aplicará a todas las líneas seleccionadas.

domingo, 19 de enero de 2014

Cápsula Windows Phone 8. Cajas Herramientas. AboutPromt, InputPrompt y MessagePrompt

 

Entre otras Coding4Fun es una caja de herramientas a la que podemos acceder en forma gratuita y que nos permite brindar a nuestras aplicaciones características atractivas, con el mínimo de esfuerzo.

Coding4Fun es un conjunto de librerías Open Source para Windows Phone 7, 8 y Windows Store Apps. Esta caja de herramientas se baja desde CodePlex.

http://coding4fun.codeplex.com/releases/view/109917

También es posible bajar y usar los controles por medio de Nuget:

pm>Install-Package Coding4Fun.Toolkit.Complete

pm>Install-Package Coding4Fun.Toolkit.Controls

pm>Install-Package Coding4Fun.Toolkit.Audio

pm>Install-Package Coding4Fun.Toolkit.Net

pm>Install-Package Coding4Fun.Toolkit.Storage

El creador del ToolKit es Clint Rutkas

Controles del Toolkit:

 

AboutPrompt RoundToggleButton Chat Bubble
InputPrompt RoundButton Chat Bubble TextBox
MessagePrompt Color Hexagon Picker ProgressOverlay
PasswordInputPrompt Color Picker TimeSpanPicker
ToastPrompt Color Slider MemoryCounter
AppBarPrompt TitleImage SuperSlider
Opacity Toggle Button SuperImage LockScreenPreview

Esta cápsula explicará los controles AboutPrompt, InputPrompt y MessagePrompt.

 

Controles AboutPrompt, InputPrompt y MessagePrompt

viernes, 17 de enero de 2014

TFS. Branch y Merge

 

La idea de este post es recordarme a mí mismo, como hice esto:

En la GUI normal que permite hacer Branching y Merging de código fuente, en el Visual Studio, sólo hay la posibilidad de hacer Merge hacia una rama padre o sobre la cual se creó o basó el Branch o una rama hija, es decir, una rama que se crea basada en el propio código de la rama a la que ahora se quiere hacer el proceso de Merge.

Como es demasiado enredado el tema, al leer la descripción en palabras, apoyémonos en imágenes.

La idea, para este ejemplo es:

Del branch GTC.root-LB-INT, se creó el Branch GTC.root-BR-022_20131119, en cuyo caso, en el lenguaje de padres e hijos. GTC.root-LB-INT es padre de GTC.root-BR-022_20131119.

6

Ahora, se tiene el Branch GTC.root-BR-CopiaBranch22, que se creó a partir del Branch GTC.root-BR-022_20131119, en cuyo caso GTC.root-BR-022_20131119 es padre de GTC.root-BR-CopiaBranch22.

7

Cuando se intenta hacer un merge del código de la rama GTC.root-BR-022_20131119, salen la rama padre y la hija.

1

La idea de esta entrada es demostrar, como lograr que aparezca una rama hermana, es decir, otra rama creada a partir de GTC.root-LB-INT.

Se desea que la rama GTC.root-LB-INT-CAM0068 que es hija de GTC.root-LB-INT, aparezca entre las opciones para hacer merge del código de la rama GTC.root-BR-022_20131119.

Así tenemos entonces:

8

Como quien dice se desea poder hacer merge del código de una rama hacia una rama hermana.

Para lograr esto, es necesario usar un comando de consola, que para el caso del ejemplo es:

Tf merge /baseless <<source path>> <<target path>> /recursive

Para el caso en cuestión sería:

Tf merge /baseless D:\dirtrab\pry_GTC\Fuente\GTC.root-BR-022_20131119 D:\dirtrab\pry_GTC\Fuente\GTC.root-LB-INT-CAM0068 /recursive

Este comando se puede ejecutar en la ventana de comandos de Visual Studio.

2

Al dar enter, no reconoció el comando. Entonces, el comando se ejecuta de forma externa a Visual Studio.

3

Luego de un momento, se ejecuta el proceso de Merge. Eso es algo que se debe tener en cuenta, se realiza el proceso de Merge de forma automática, teniendo en cuenta todos los archivos. Por eso es importante, antes de ejecutar el comando, haber obtenido última versión, de las fuentes de las ramas involucradas.

Si hay conflictos, aparece la ventana para su solución:

4

Una vez se solucionan todos los conflictos, se procede a dar check – in y luego si se va de nuevo a la opción de Merge para la rama GTC.root-BR-022_20131119, se encuentra que aparece la rama GTC.root-LB-INT-CAM0068, es decir, la rama hermana.

5