domingo, 7 de diciembre de 2008

Agregar recursos dentro del proyecto

Para agregar un recurso (un jpg, bmp, xml, txt, etc) dentro del exe o la dll compilado hay que seguir los siguientes pasos

1) Ir al solution explorer y poner Add..New Item...
(Aqui agregaremos por ejemplo el archivo pepe.xml)

2) Seleccionar el archivo pepe.xml que acabamos de agregar
Se tiene que abrir el Inspector de las properties de ese archivo

3) En build action poner Embebed Resource

Listo. Cada vez que compilemos todo se incluira el archivo pepe.xml como recurso
Para leer el archivo pepe desde nuestro codigo debemos hacer


Assembly assembly = Assembly.GetExecutingAssembly();
String sNameSpace = "WindowsFormsApplication1";
Stream schemaStream = assembly.GetManifestResourceStream(sNameSpace+"."+"pepe.xml");


Esto nos devuelve un stream
Se puede ver que el camini para llegar al recurso es


[NombreNamespace].[Directorio].[NombreRecurso]

lunes, 3 de noviembre de 2008

Recursos Unit Testing

Algunos recursos de Unit Testing son
NUnit
DataFresh
JSUnit

martes, 28 de octubre de 2008

Select sobre Stored Procedure

Supongamos que queremos hacer un select sobre un store procedure que devuelve datos de la form:

select * from [store_procedure]

Para usar el stored procedures como si fuera una tabla. En mi caso queria hacer una interseccion sobre dos stored procedures que deberian dar lo mismo para saber las diferencias.

Para ello debemos
a) Declarar una tabla con la estructura del resulset del store procedure
b) Ejecutar el store procedure e insertarlo en esa tabla
c) Seleccionar los campos de la tabla

O mejor dicho en codigo

DECLARE @Resultado table(Campo1 int, Campo2 int, Campo3 int)

INSERT INTO @Resultado exec Store_procedure param1,param2,param3

select * from @Resultado

jueves, 16 de octubre de 2008

Serializar a JSon

En la siguiente URL se puede bajar el JSon serializer que sirve para serializar un objeto en .NET a Javascript Object Notation

JSon Serializer

miércoles, 15 de octubre de 2008

Viewstate

El viewstate nos permite guardar información entre distintos postbacks de la misma página, por ejemplo podemos almacenar un valor en el viewstate de la siguiente manera


protected void btnSalvarViewstate_Click(object sender, EventArgs e)
{
this.ViewState["sample"] = this.txtBoxValor.Text;
this.txtBoxValor.Text = "";
}

protected void btnRecuperarViewstate_Click(object sender, EventArgs e)
{
if (this.ViewState["sample"] != null)
{
this.txtBoxValor.Text = this.ViewState["sample"].ToString();
}
}

miércoles, 8 de octubre de 2008

Manipular HTML on the Fly

Las siguientes herramientas nos permitiran debuguear una pagina html.
Proveen la siguiente funcionalidad
1) Posicionarse con el mouse sobre un elemento html y ver sus propiedades
2) Modificar el estilo de los elementos HTML dinamicamente
3) Debuggear javascript

Dichos programas son

Para el Internet Explorer:
IE Developer Toolbar
Link

Para Firefox
Firebug
Link

miércoles, 17 de septiembre de 2008

Ver valor de retorno de un Store Procedure

Para ver el valor de retorno de un store procedure en una ventana del Management Studio de SQL server tenemos que hacer lo siguiente



declare @variable as int

storeProc 'param1','param2','param3',@variable output

select @variable

lunes, 15 de septiembre de 2008

Cookies en ASP.NET

Para guardar cookies en el cliente se puede hacer con el siguiente código


HttpCookie c = new HttpCookie("Nombre", "Valor");
this.Response.Cookies.Add(c);


El código análogo para obtener el valor de la cookie una vez almacenado es


HttpCookie c = this.Request.Cookies.Get("Nombre");
this.Label1.Text = c.Value;

Sistema testeo aplicaciones web

Con este plugin para firefox se pueden grabar test para que el sistema
los reproduzca al estilo test complete

El ide para firefox es:
http://selenium-ide.openqa.org/

Que a su vez se basa en
http://selenium.openqa.org/

miércoles, 27 de agosto de 2008

Cache condicional de un control en asp.net

Para indicar que el contenido de un control ascx se cache indicarle

Declaracion del control:


<%@ Control Language="C#" AutoEventWireup="true"
Codebehind="MyControl.ascx.cs"
Inherits="MyControl" %>


Indicacion quequeremos que el control sea cacheable


<%@ OutputCache Duration="86460"
VaryByParam="none"
VaryByCustom="AffiliateIDAndCulture"%>


El atributo interesante es VaryByCustom donde podemos indicar un
string que indica la condicion en la cual se actualiza el cache
(por ejemplo por usuario o por cultura)

Para ello en el Global.asax.cs definimos el metodo


public override string GetVaryByCustomString
(HttpContext context, string custom)


Donde implementamos que string devolver basada alguna condicion
para que se actualize el cache

martes, 12 de agosto de 2008

Integrar SVN con Visual Studio

Para integrar el SVN con el visual studio podemos usar el siguiente plugin

lunes, 28 de julio de 2008

Listar Bases de datos

Para poder listar las bases de datos existentes podemos usar el siguiente SQL

SELECT name FROM sys.databases

Formatear un numero a una cantidad finita de decimales


static void Main(string[] args)
{
//El símbolo de la divisa depende de la cultura del sistema
Console.WriteLine(String.Format("{0:c2}",1200.3343));
//Output: f1200.33
Console.WriteLine(String.Format("{0:n2}", 1200.3343));
//Output:1,200.33
Console.WriteLine(String.Format("{0:f2}", 1200.3343));
//Output:1200.33
Console.ReadLine();
}

Evitar que un control funcione por ajax

Si usamos el ajax control toolkit es posible que por el layout que definamos nos queden controles dentro de un update panel que querramos que no funcionen por ajax. En ese caso habria que registrar esos controles en el page load de la siguiente manera

ScriptManager.GetCurrent(this).RegisterPostBackControl(this.btnSinAjax);

martes, 22 de julio de 2008

Numerar Filas en SQL Server 2005

Para numerar las filas en SQL Server 2005 podemos usar la funcion Row_number() cuya sintaxis es



Row_Number() over ()



Donde en over le ponemos un ordenamiento y agrupamiento que usara como criterio para numerar las filas. Por ejemplo para numerar las filas de una tabla StringResource ordenada por el campo ResourceType debemos hacer



select
Row_Number() over (order by resourceType) as Nro,
stringresource.*
from
stringresource

Describir una tabla

Una forma simple de describir una tabla dentro del SQL Server management studio para ver por ejemplo los tipos de los campos y si admiten null entre otra informacion es usar el procedimiento sp_help que viene incorporado en SQL Server.

La forma de usarlo es:


sp_help [NombreTabla]

lunes, 21 de julio de 2008

Busquedas dentro los Stores Procedures

Supongamos que en SQL Server 2000 queremos hacer una búsqueda dentro de el código de todos los store procedures de la base de datos, por ejemplo aquellos que contengan la palabra "servidor" en su implementación. Para ello podemos usar la siguiente consutlta

select DISTINCT A.name from sys.sysobjects A
inner join sys.syscomments B on A.id = B.id
WHERE A.xtype = 'P' and B.text LIKE '%servidor%'

Reemplazando servidor por la palabra quedeseemos en el like de la consulta podemos conseguir el resultado esperado

viernes, 18 de julio de 2008

Manejando XML en SQLServer 2005

SQLServer 2005 incorpora nuevas funcionalidades para manejar sql server. Una de ellas es el manejo de xml. Dejo aca un ejemplo de manemplo de ello que se puede ejecutar con el SQL server management studio. El xml lo saque de www.w3schools.com y lo recorte por si a alguno le resulta similar

declare @xml as xml


set @xml =
'<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>

<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>

<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>Greatest Hits</title>
<artist>Dolly Parton</artist>

<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
<cd>
<title>Still got the blues</title>
<artist>Gary Moore</artist>
<country>UK</country>
<company>Virgin records</company>
<price>10.20</price>
<year>1990</year>
</cd>
</catalog>';



select @xml.query('/catalog/cd/title')

SELECT
coleccion.cd.value('title[1]','VARCHAR(100)'),
coleccion.cd.value('artist[1]','VARCHAR(100)'),
coleccion.cd.value('country[1]','VARCHAR(100)'),
coleccion.cd.value('company[1]','VARCHAR(100)'),
coleccion.cd.value('price[1]','VARCHAR(100)'),
coleccion.cd.value('year[1]','VARCHAR(100)')
FROM
@xml.nodes('/catalog/cd') as coleccion(cd)

Exportar un datos a excel con ASP.NET

A continuación muestro la forma mas práctica de exportar datos a excel desde asp.net. Esta clase funciona para exportar una coleccion de objetos que soporte la interfaz IEnumerable a excel
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections;
using System.IO;

///
/// This class exports an IEnumerable to Excell
/// It generates a response
///

public class ExcelExporter
{
IEnumerable _content = null;
String _filename = String.Empty;
DataControlFieldCollection _columns = new DataControlFieldCollection();

private string GetControlAsHtml(Control ctrl)
{
StringWriter sw = new StringWriter();
HtmlTextWriter htm = new HtmlTextWriter(sw);
ctrl.RenderControl(htm);
return sw.ToString();
}

private void ConfigureColumns(GridView grid)
{
if (this._columns.Count == 0)
{
grid.AutoGenerateColumns = true;
}
else
{
grid.AutoGenerateColumns = false;
grid.Columns.Clear();
foreach (DataControlField f in this._columns)
{
grid.Columns.Add(f);
}
}
}

public ExcelExporter(String fileName, IEnumerable content)
{
this._content = content;
this._filename = fileName;
}
public ExcelExporter(String fileName, IEnumerable content, DataControlFieldCollection columns) : this(fileName, content)
{
this.Columns = columns;

}

public ExcelExporter()
{
//
// TODO: Add constructor logic here
//
}

public String Filename
{
get { return this._filename; }
set { this._filename = value; }

}
public IEnumerable Content
{
get { return this._content; }
set { this._content = value; }
}
public DataControlFieldCollection Columns
{
get
{
return this._columns;
}
set
{
this._columns.Clear();
foreach (DataControlField f in value)
{
this._columns.Add(f);
}
}
}

public void ExportToExcell(HttpResponse response)
{
if (this._content == null) throw new Exception("ExcelExporter: Error exporting to Excel. \n No Content Specified.");
if (this._filename == String.Empty) throw new Exception("ExcelExporter: Error exporting to Excel. \n No output filename specified.");

response.Clear();
response.AddHeader("content-disposition", string.Format("attachment; filename={0}", this._filename));
response.ContentType = "application/ms-excel";

GridView grid = new GridView();
this.ConfigureColumns(grid);
grid.DataSource = this._content;
grid.DataBind();

response.Write(GetControlAsHtml(grid));
response.End();
}
}

Esta forma tiene la contra que si el cliente tiene Excell 2007 le va a tirar un warning y va a tener que confirmar un cartel antes de abrir el archivo. Suponiendo que tenemos. Una forma de usar esta clase sería.

ExcelExporter exporter = new ExcelExporter("archivo.xls",
FinderObjetoPrueba.FindAll());

exporter.ExportToExcell(Response);


o suponiendo que hay una gridview con datos y queremos usar sus columnas.

ExcelExporter exporter = new ExcelExporter("archivo.xls",
FinderObjetoPrueba.FindAll(),
grdDatos.Columns);
exporter.ExportToExcell(Response);




En ambos casos FinderObjetoPrueba es una clase que nos devuelve una lista de objetos y en el ejemplo completo funciona como object data source de grdDatos y Response es la clase de Page.Response donde escribiremos el html que por el content-type sera abierto por el excell del lado del cliente

Exportar una coleccion a CSV usando reflection

El siguiente ejemplo exporta una coleccion de objetos que implemente la interfaz IEnumerable a CSV usando reflection. Se eliminaron algunas validaciones e identaciones para que ocupe menos y dejar lo principal.



using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.IO;


public class ExportToCSV
{
public ExportToCSV()
{
//
// TODO: Add constructor logic here
//
}

IEnumerable _content = null;
String _filename = String.Empty;

public ExportToCSV(String fileName, IEnumerable content)
{
this._content = content;
this._filename = fileName;
}

public String Filename
{
get { return this._filename; }
set { this._filename = value; }
}

public IEnumerable Content
{
get { return this._content; }
set { this._content = value; }
}


private PropertyInfo FindProperty(String propertyName, PropertyInfo[] properties)
{
PropertyInfo result = null;
foreach (PropertyInfo p in properties)
{
if (String.Compare(propertyName, p.Name, true) == 0)
{
return p;
}
}
return result;
}

private string GetCSVColumns()
{
Object item = GetFirstItem();

if ((item != null))
{
Type itemType = item.GetType();
PropertyInfo[] publicProperties = GetPublicProperties(itemType);
return GetCSVColumnsFromPublicProperties(publicProperties);
}

return String.Empty ;
}

private static PropertyInfo[] GetPublicProperties(Type itemType)
{
PropertyInfo[] allTheProperties = itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
List
publicProperties = new List();
foreach (PropertyInfo p in allTheProperties)
{
if (p.GetIndexParameters().Length == 0)
{
publicProperties.Add(p);
}
}

return publicProperties.ToArray();
}


private Object GetFirstItem()
{
Object item = null;
IEnumerator iterador = this._content.GetEnumerator();
if (iterador.MoveNext())
{
item = iterador.Current;
}
return item;
}

private static string GetCSVColumnsFromPublicProperties(PropertyInfo[] publicProperties)
{
StringBuilder sb = new StringBuilder();
String propertyValue = String.Empty;
bool isFirst = true;

foreach (PropertyInfo p in publicProperties)
{
isFirst = AppenCSVSeparator(sb, isFirst);
sb.Append(p.Name);

}

return sb.ToString();
}

private string GetCSVLine(Object item)
{
Type itemType = item.GetType();
PropertyInfo[] publicProperties = GetPublicProperties(itemType);
StringBuilder sb = new StringBuilder();
String propertyValue = String.Empty;
bool isFirst = true;

foreach (PropertyInfo p in publicProperties)
{
if (p.GetIndexParameters().Length == 0)
{
isFirst = AppenCSVSeparator(sb, isFirst);

propertyValue = p.GetValue(item, null).ToString();

sb.Append(propertyValue);
}
}
return sb.ToString();
}


private static bool AppenCSVSeparator(StringBuilder sb, bool isFirst)
{
if (!isFirst)
{
sb.Append(";");
}

isFirst = false;
return isFirst;
}

private void AppendContentToStream(StreamWriter writer)
{
IEnumerator iterador = this.Content.GetEnumerator();
Object lastSelected = null;
while (iterador.MoveNext())
{
Object item = iterador.Current;
writer.WriteLine(this.GetCSVLine(iterador.Current));
lastSelected = iterador.Current;
}
}


private void ValidateHasContent()
{
if (this._content == null) throw new Exception("No hay content");
}

public void FillWithCSV(Stream stream)
{
ValidateHasContent();
StreamWriter writer = new StreamWriter(stream);
writer.WriteLine(this.GetCSVColumns());
AppendContentToStream(writer);
writer.Flush();
}
}

Mandar Mails por ASP.NET 2.0

Para mandar por asp.net 2.0 hay que usar

using System.Net.Mail;


luego

System.Net.Mail.MailMessage mail = new MailMessage("support@websitesample.com", "destino@destino.com");


mail.Subject = "ASubject";
mail.IsBodyHtml = true;
mail.Body = "Body del mail";

SmtpClient emailClient = new SmtpClient();
emailClient.Host = "smtp.gmail.com";
emailClient.Credentials = new System.Net.NetworkCredential("origen@gmail.com", "password");
emailClient.EnableSsl = true;
emailClient.Send(mail);





Con las clases de System.Net.Mail no encontre forma de mandar un mail sin especificar un servidor de smtp (con System.Web.Mail se puede pero encontre se recomienda el uso de System.Net.Mail en la version de ASP.NET 2.0) lo cual tiene sentido por una cuestión de seguridad.

Si quisieramos hacer un attachment podemos leerlo de un archivo o la opción que utilizamos fue enviar un Stream como attachment que correspondia a un reporte generado dinamicamente en formato CSV. En el siguiente ejemplo muestro como mandar un memory stream como attachment de un mail


//Creamos un stream de prueba
MemoryStream mem = new MemoryStream();
StreamWriter sw = new StreamWriter(mem);
//Le llenamos algunos datos
sw.Write("1;2;3;4;5;6;7;8;9");
sw.Flush();
//Es importante setear la posicion del stream en 0 sino puede
//fallar el envio del maio
mem.Position = 0;

System.Net.Mail.MailMessage mail = new MailMessage("support@websitesample.com", "destino@destino.com");
//Llenamos los datos del mail
...
Attachment a = new System.Net.Mail.Attachment(mem, "report.csv");
mail.Attachments.Add(a);



Ahora ASP.NET nos da la posibilidad de no tener que llenar la url del servidor de smtp, el usuario y el password sino hacerlo por medio del archivo Web.Config. Para ello podemos especificar en ese archivo que nos quedaria


<configuration>
<appsettings>
<system.net>
<mailsettings>
<smtp>
<network host="smtp.gmail.com" username="usuariogmail@gmail.com" password="passwordgmail">
<!-- esta el atributo port="portNumber" sino usa el default -->
</network>
</smtp>
</mailsettings>
</system.net>

...
</appsettings>
</configuration>




De esa forma para mandar el mail simplemente tenemos que hacer


System.Net.Mail.MailMessage mail = new MailMessage("support@websitesample.com", "destino@destino.com");
mail.Subject = "A Subject";
mail.IsBodyHtml = true;

SmtpClient emailClient = new SmtpClient();
emailClient.EnableSsl = true;

emailClient.Send(mail);


No hay que olvidarse que si mandamos el mail por gmail incluir la linea emailClient.EnableSsl = true;.Sino la presencia de esa línea dependerá de si el servidor smtp que usemos soporta SSL o no.

Primer post

En este blog simplemente muestra diversos temas que van surgiendo en un proyecto de asp.net con sqlserver 2005 y su solución