miércoles, 28 de julio de 2010

Error de Collation en SQL Server

Tengo una base de datos con una Collation Modern_Spanish_CI_AI e intento hacer un Join con una tabla que está en una base de datos con la Collation Modern_Spanish_CI_AS. Devolviendome un bonito error de Collation.

Ante eso me voy al Server Management Studio y en las propiedades de la Base de datos, en Options, le intento cambiar el collation… recibiendo un delicioso error. Para el cual la solución es modificar el Restrict Access de MULTI_USER a SINGLE_USER.
image 
Entonces, nos permite cambiar el collation. Y volvemos a MULTI_USER.

Peeeeero (siempre hay uno), me encuentro que el error me continua sucediendo. Por lo cual revisando y Googleando un rato me encuentro es que el cambio de Collation me ha cambiado el de todos los objetos de la BD a excepción del collation de las columnas (pero si cambia el de sus opciones extendidas… esto no hay quien lo entienda).

Para modificar esto podemos, entre otras formas, utilizar un pequeño script que nos haga un ALTER TABLE y que es así:

ALTER TABLE MyTable ALTER COLUMN CharCol
            varchar(10)COLLATE Latin1_General_CI_AS NOT NULL
GO

Lo malo es que hay que repetirlo por CADA columna de cada tabla de la base de datos. Lo cual, en este caso fue posible. Pero en casos más complejos pudiera ser mejor solución restaurar la base de datos con un Collation diferente.

lunes, 19 de julio de 2010

Abrir una nueva ventana desde un botón dentro de Ajax (updatePanel)

Escenario:

“Teniendo un ImageButton dentro de un UpdatePanel, y queriendo abrir una nueva ventana una vez pulsado el mismo:
1. Cómo evitar el error: “ Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled ”.

2. Cómo pasarle parámetros por el querystring.”

Primero y único, en el método onclick del botón se le da de alta el script que ha de lanzarse por medio de la clase de sistema ScriptManager.

protected void imgbCarpetilla_Click(object sender, EventArgs e)
{
string scriptStr = "window.open('informes/Target.aspx?valor=" + valor.ToString() + "');";
ScriptManager.RegisterStartupScript(((Control)sender), typeof(string), "", scriptStr, true);
}


De aquí solamente señalar que el true al final lo que hace es poner “<script>” delante y detrás de nuestro script.



Y con esto podemos olvidar nuestro socorrido Response.Write();

Mayúsculas en el formulario (UpperCase).

Primero señalar mi aversión a JavaScript. Que no es razonables, pero no puedo evitarlo. Siempre que tengo que hacer cosas en JS me encuentro con problemas que me hacen perder demasiado tiempo.

Planteado el problema de que en la aplicación actual TODAS las entradas han de ser en mayúsculas, cómo resolverlo sin mucho lio:

1. Poner todo en mayúsculas pero solamente visualmente. Por medio de CSS en la clase de estilo que utilizo para los textbox.

.input
{
font-family: 'Lucida Sans';
font-size: 12px;
text-transform: uppercase;
}

2. Poner todo realmente en mayúsculas en el cliente, para descargar el servidor y acelerar el temilla. Lo he puesto en una función de una librería .js para poder modificar el comportamiento en un solo punto.


function toUpper(control) {

if (/[a-z]/.test(control.value)) {
control.value = control.value.toUpperCase();
}
}

Esto requiere una pequeñísima explicación. Le tengo que meter el condicional que solamente me ponga en mayúsculas las letras en minúscula ya que, de no hacerlo así, se inutilizan las teclas de flechas y más cosas malas.


3. Por último, en los controles que quiero este comportamiento le añado el evento:


<asp:TextBox ID="TexBo0x1" runat="server" CssClass="input" onKeyUp="toUpper(this)"></asp:TextBox>

Aquí lo único a reseñar es la necesidad de enviarle el propio control a la librería js para que actualice el valor a la letra en Mayúscula.


Funciona hasta  con acentos… :)

jueves, 15 de julio de 2010

Reporting Server. ‘Error RSClientController’ no está definido.

Un bonito error en el Reporting Server cuando intento lanzar un Reporte en el Report Viewer: ‘RSClientController’ no está definido. Y a partir de allí, decenas de errores en cascada.
image

Pidiendo ayuda a Daniel me comenta que le suena que es una configuración de IIS7 y en unos pocos minutos encuentra la solución:

En los Grupos de aplicaciones del II7, el DefaultAppPool tiene, por defecto, el Modo de canalización administrada del tipo Integrada. Hay que cambiarla a Clásica. O cambiar el Grupo de aplicaciones que utiliza nuestro servidor Report a alguno que utilice este modo de canalización.

image 
¿Porqué funciona? Pues tengo que buscarlo porque hay que reconocer que la solución es más bien poquísimo intuitiva.

miércoles, 7 de julio de 2010

Utilizar el Enter como tabulador

Una de las cosas más bonitas de nuestra profesión es que los clientes te piden cosas que no se te hubieran ocurrido ni el mil millones de años. Ayer me pasó a mí al solicitarme el cliente, en una prueba, si podíamos permitir tabular con la tecla Enter.
Ni corto, ni perezoso a San Google me fuí y encontré una solución funcional para IE. También la hay para FireFox, pero en este caso en particular se va a utilizar el navegador de Microsoft.
Si tienes masterpage, estás de enhorabuena porque en el <body> solamente has de escribir:
<body onkeydown="javascript:if(window.event.keyCode == 13) window.event.keyCode = 9;" >
Se puede mejorar bastante permitiéndo ser multinavegador y cambiando su comportamiento si el control que está en el foco es un botón… pero eso será para otro post.


Fuente

Fallo en Response.Redirect

Cuando migré mis ordenadores a Windows7 beta estaba retocando una pequeña aplicación de facturación y, de repente, los response.redirect() me dejaron de funcionar.

Además el error que devolvía era muy raro y no me decía nada que fuera útil. Hasta que, por casualidad, me encontré con una solución que –hay que reconocer – es rara, de narices.

Se trata que el IIS7 que trae el Windows7 por defecto, en su instalación, no habilita las redirecciones http. Supongo que tendrá algún sentido desde el punto de vista de seguridad. Pero para un desarrollador asp.net es un problema.

Para solucionarlo hay que irse al Panel de control y escoger Programas.
image
Una vez allí escogemos la opción de Activar o desactivar las características de Windows.
image
Saldrá una ventanita y cargará todos los módulos instalados con el Windos7.
image
Aquí escogeremos el Internet Information Services –> Servicios World Wide Web –> Características HTTP comunes y encontraremos al culpable de los errores: Redirección HTTP. Debe estar seleccionado.

Espero que sea de utilidad.

jueves, 1 de julio de 2010

Cambiar los valores de un objeto DateTime

Hay que reconocer que tratar con fechas siempre es un engorro por sus “particularidades”. Pero el que cuando creas un objeto DateTime ya no lo puedas modificar directamente más que con operaciones aritméticas o con un objeto TimeSpan, pues como complica su uso.

 Por ello almaceno en esta entrada la manera facil de modificar cualquiera de los datos de una fecha u hora almacenados en este tipo de objetos.

Para ello lo que haremos es crear siempre un nuevo objeto DateTime pero con los valores que querramos como se vé en los siguientes ejemplos.

Partimos de la base de un DateTime con el siguiente contenido: 22/11/1967 00:00:00
DateTime fecha = new DateTime(2010, 11, 22, 0, 0, 0);
DateTime fechaDesde;
DateTime fechaHasta;
Para añadir días, meses, o años y que el propio método se enrede con la coherencia de los datos (no vale un 30 de febrero, pero si un 29 cuando el año es bisiseto) yo aconsejo utilizar el método Add().
fecha = fecha.AddDays(1);
Pero si lo que quiero es situarlo en una hora exacta el sistema que yo uso es:
fechaDesde = new DateTime(fecha.Year, fecha.Month, fecha.Day, 0, 0, 0);
fechaHasta = new DateTime(fecha.Year, fecha.Month, fecha.Day, 23, 59, 59);
Listo”!!

GridView, onclick condicionales.

Gabriela me solicita una ayudita en relación al post Seleccionar por filas de un GridView y esto me da para un post sobre cómo tratar de forma condicional diferentes eventos de click en un mismo GridView.

Es decir, tener dos columnas del grid que tienen botones (o combos en el caso de gabriela)  y que la aplicación sepa que hacer en cada caso.

Para ello lo primero es entender que todo lo que ocurre en un GridView lanza el evento GridViewCommand. Aprovechándonos de ello declaramos en nuestro Grid una columnas con un botón en donde definiremos el comando que queremos invocar.
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="imgbSeleccionar" runat="server" CausesValidation="false"
        CommandName="Seleccionar" 
        CommandArgument='<%# Eval("id")%>' 
        ImageUrl="~/imagenes/icon_06.png" ToolTip="Seleccionar." />
</ItemTemplate>
</asp:TemplateField>

Lo importante de este código son dos partes. Por un lado el CommandName que el que le va indicar al evento RowCommand el tipo de acción que hemos lanzado. (Acordaros de usar una nomenclatura clara y autoreferente).

Y por otro lado el CommandArgument que es en donde le vamos a mandar la información necesaria para realizar la acción que hemos lanzado.

En el código tendremos el evento RowCommand en donde capturaremos el CommandName y así tendremos la acción lanzada:


public void Grid_RowCommand(object sender, GridViewCommandEventArgs e)
{
switch (e.CommandName)
{
case "Seleccionar":
id = e.CommandArgument.ToString();
SeleccionaObjeto(id);
break;
default:
break;
}
}



Seguro ya os habréis dado cuenta que con este sistema puedes tener todas las acciones que se te ocurran, he incluso varias acciones en una misma columna.

Es importante recordar que existen tres acciones predefinidas que son: “Select”, “Edit” y “Delete” y que si usáis estos CommandName, deberéis gestionarlos en sus respectivos eventos u os dará un bonito error.

En resumen, Gabriela, espero que te haya sido de ayuda.