miércoles, 1 de septiembre de 2010

Evitar redondeo automático en SQL

Últimamente he tenido un problema con el redondeo utilizando el operador división (/) en una consulta de SQL, para el origen de datos de un informe en un proyecto Microsoft Access Project (.adp)

El problema es que al dividir dos enteros me trunca de forma automática el resultado. La explicación al problema esta en http://technet.microsoft.com/en-us/library/ms175009.aspx. Básicamente es que cuando el divisor y el dividendo son enteros el resultado lo convierte a entero.

La solución es sencilla, convertir uno de los dos operando a float o a real con CAST para que el operador “/” no convierta el resultado a entero. La conversión  hay que hacerla de uno de los operandos y no del resultado, ya que la división ya lo devuelve truncado y aunque lo conviertas no va a haber cambios

Información sobre CAST en http://technet.microsoft.com/en-us/library/aa226054(SQL.80).aspx

Por ejemplo. Si tenemos una tabla tbventas con una columna impVenta  y otra nArtículos de tipo entero si queremos que nos devuelva los decimales tendría que ser así:
Select CAST(impVenta as float)/cArticulos as valorMedio
from tbventas

viernes, 18 de junio de 2010

Problema con los nulos en campos image de SQL con ASP.NET

Voy a explicar primero en que escenario me estoy moviendo y los pasos que he dado para solucionar los problemas para almacenar un valor nulo en un campo del tipo image en una base de datos SQL.

En la base de datos SQL tengo una tabla con un campo del tipo image que admite nulos.
En esta misma base de datos creo un procedimiento almacenado para insertar y actualizar la tabla

Desde .NET creo un Data Set con tipo donde creo un DataTable con los campos de la tabla de SQL y le asigno a cada campo su tipo de datos. En el caso del campo Imagen le asigno el tipo de datos de .Net System.byte(). Utilizo este DataTable para cargar la información de campos de varias tablas de la base de datos SQL.

A la hora de llamar al procedimiento almacenado desde .NET le indico los parámetros en un objeto sqlCommand y lo ejecuto como ExecuteNonQuery.


A primera vista todos los pasos funcionan correctamente y no tengo ningún error de compilación.

Primer error que me sucede al intentar guardar un valor nulo en el campo imagen


Por el punto donde da el error es en la clase que genera automáticamente a partir del DataSet. Esta dando en la columna imagen en el DataTable que he creado. Se produce porque al crear el campo Imagen he dejado indicado en las propiedades que genere una excepción si se encuentra con nulos.

Veo dos opciones para evitar este error

  • La primera es modificar la propiedad NullValue del campo Image para que en vez de generar una excepción cuando contienen nulos, que no haga nada (es una opción del desplegable de ese campo)

  • La segunda es modificar el código donde añado el parámetro @Imagen. En vez de utilizar un IIF abreviado donde se evalúan las dos partes (y ahí salta el error), utilizar un If por separado, de tal manera que si la imagen es nulo, no se llegue a evaluar.
Parece que todo va bien, pero cuando volvemos a ejecutar nos encontramos con otro error.
En este caso se genera el error cuando se ejecuta el command del procedimiento almacenado. Lo primero que llama la atención es que en el error habla del tipo de datos nvarchar, que no hemos utilizado en ningún momento.
Si ponemos un punto de ruptura y miramos el parámetro imagen que enviamos al procedimiento almacenado nos encontramos con la sorpresa que el tipo de datos que estamos enviando es un nVarchar (propiedad sqlDbType).

Esto pasa porque al añadir el parámetro al command no le indicamos ningún tipo de datos, sino que solo pasamos el nombre del parámetro y el valor

La solución viene por indicar en el parámetro del command que el tipo de datos sql es un Image

Por lo que si volvemos a repetir la ejecución podemos comprobar en la inspección del parámetro @imagen del command que ha desaparecido el tipo nvarchar por el image y funciona todo correctamente


miércoles, 9 de junio de 2010

Algunos adjuntos no llegan cuando se envían desde Exchange 2007

He estado una temporada con un problema de los que se podía catalogar de "fantasma". Al enviar un correo con un adjunto desde MS Outlook a través de un servidor Exchange Server,  a determinadas direcciones de correo que utilizaban directamente Outlook express, pasaba que se recibía el correo pero no el adjunto. En cambio, si enviabas el mismo adjunto pero desde una dirección de hotmail, gmail, etc, llegaba sin problemas tanto el correo como el adjunto.

Después de revisar tema de virus tanto en los equipos que enviaban el correo, como en los que supuestamente lo recibían y de verificar que el antivirus del ISP no lo cortaba, estaba igual que al principio.
Me pasaba en cuentas de correo que estaban dadas de alta en Exchage como Contactos.

El recorrido del correo era desde el cliente Outlook --> Servidor Exchange Interno --> Redirección al ISP--> Outlook Express.

Al final hablando con el servicio técnico del ISP (donde está alojado el dominio de correo) y analizando las cabeceras de los correos vimos que además del adjunto, Exchange añadía un archivo Winmail.dat al correo y que el cliente no lo sabía interpretar y por eso no mostraba los adjuntos.

Este archivo, Winmail.dat se añade por defecto si el cliente final no puede recibir correos con texto enriquecido (RTF), pero puede que como en mi caso el cliente lo vea como un archivo binario y fastidie el correo

La solución vino a través de un artículo de Microsoft Cómo impedir que se envíe el archivo Winmail.dat a otros usuarios en Internet donde se explica los motivos por los que se puede añadir este correo y los pasos para evitarlo.

En mi caso, al utilizar Exchange 2007 server había alguna pequeña diferencia con respecto a lo que se indica en el artículo, pero la esencia era la misma
  • Desde la consola de administración de Exchange
  • En configuración de destinatarios
  • Contactos de correo
  • En la ventana de propiedades
  • Indicar "Nunca" en el desplegable de "Enviar formato de texto enriquecido MAPI"


viernes, 28 de mayo de 2010

Error No se permite el verbo HTTP POST accediendo a una página html

Este error puede dar por varios motivos, pero me voy a centrar cuando se genera al intentar acceder a una página Html utilizando la propiedad PostBackUrl de un control button, imagebutton o linkbutton en ASP.NET.

Normalmente lo que se pretende, es ir de una página a otra al pulsar un botón. Poniendo en la propiedad PostBackUrl del control el nombre de la página de destino funciona, salvo que pongamos como destino una página html en vez de una aspx.

Esto tiene que ver con cross-page posting de .NET ( que nos permite acceder desde una página a los controles de la página de origen). Las páginas html no pueden procesar un formulario enviado con HTTP post y cuando producimos un postback (petición al servidor) por defecto se envía el form a la página de destino.

Hay varias formas para solucionar este problema
  1. Cambiar el botón por un hiperenlace a la página de destino (lo que puede hacer que el diseño de la página cambie demasiado)
  2. Programar el evento clic del botón indicando en response.redirect  la página de destino y quitar el valor de la propiedad PostBackURL
En el caso de un botón HTML (input type="button") podemos programar el evento onclic con javascript en el cliente

En el caso de un control button de asp.net la programación la haríamos en el fichero de código
 Algunos enlaces para saber más sobre este tema:

miércoles, 26 de mayo de 2010

Transformar una página HTML a ASPX

En más de una ocasión necesitamos añadir controles .net a una página web estática en HTML. Para poder hacer esto, necesitamos transformar esta página HTML en ASPX y si es necesario vincularla con una página de código en Visual Basic o C#

1 Realizamos una copia de la página HTML y renombramos la extensión a ASPX.

2 Añadimos la directiva @Page al principio del código.

3 Añadimos dentro de las etiquetas Body un formulario con la propiedad runat=server, que contenga los controles existentes en la página




A partir de aquí ya tenemos una página aspx totalmente operativa en la que se pueden utilizar controles de asp .net.

Si además queremos utilizar programación en Visual Basic o C# tenemos que hacer algún paso más.

1 Añadir al proyecto un nuevo elemento de tipo Clase (desde agregar nuevos elementos) y ponerle como nombre el de la página aspx y como extensión aspx.vb para Visual Basic o aspx.cs para C#.


Por defecto pregunta si queremos guardar este nuevo archivo en la carpeta APP_Code, ya que detecta que es un archivo de código, a lo que podemos responder que no y así lo anida debajo del archivo aspx que hemos creado en el paso anterior
2 Modificar la clase del fichero de código aspx.vb/ aspx.cs indicando que es una clase parcial y que hereda las propiedades de la clase Pages





3 Indicar a la página aspx, cual es el fichero de código asociado y su clase. Para esto modificamos la directiva @page añadiendo los parámetros CodeFile y ClassName



A partir de este momento ya tenemos la página totalmente transformada y operativa para trabajar tanto con controles .net como para utilizar código ( en este ejemplo) de Visual Basic o de C#

Antes
Despues

viernes, 7 de mayo de 2010

Abrir documentos docx de Word 2007 desde Word 2003

Con el cambio de versión de Office 2003 a Office 2007 de Microsoft han venido los problemas de compatibilidad con los documentos de Word, Excel, etc. Básicamente estos problemas vienen porque en la versión 2007 almacena la información de una forma muy distinta a como lo hacía en las versiones anteriores. La extensión que utiliza ahora es docx para Word, xlsx para Excel y unas distintas si tienen macros, frente a las extensiones doc y xls de la versión 2003.

Microsoft saco un complemento que se puede descargar gratuítamente desde su centro de descargas Complemento compatibilidad para Office 2003 junto con una página muy completa explicando los detalles del tema Información Microsoft

Hay que instalar el complemento en los ordenadores en los que queramos abrir documentos guardados con el formato 2007 y a partir de ese momento, los podremos tratar sin ningún problema (al menos los relacionados con la versión).