giovedì, aprile 17, 2008

Scaricare una GridView ed aprirla con Excel

Vabbè.... per chi non ha voglia di cercare con Google (come Andrea), ecco come salvare ed aprire con Excel una GridView da una pagina Asp.Net


Nella codice della pagina asp.net:


protected void Button_Click(object sender, ImageClickEventArgs e)
{
this.RenderToHtml(GVDetails, "foo.xls");
}


private void RenderToHtml(GridView gv, string fileName)
{
_bypassNormalVRISF = true;
Response.Clear();
Response.ContentType = "application/vnd.ms-excel";
Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName);
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
gv.RenderControl(htw);
Response.Write(sw.ToString());
Response.End();
}

private bool _bypassNormalVRISF = false;
public override void VerifyRenderingInServerForm(Control control)
{
if (_bypassNormalVRISF)
return;
else
base.VerifyRenderingInServerForm(control);
}


Per i dettagli su VerifyRenderingInServerForm vedere il sito MSDN. Comunque in 2 parole: molti (tutti?) dei controlli Asp.net devono essere creati al di sotto di <form runat="server">
Il metodo viene chiamato da questi controlli, tra cui GridView. L'implementazione standard di Page prevede che venga sollevata un eccezione se in quel momento la costruzione della pagina non è "al di sotto" di <form runat="server"> . Basta andare in override sul metodo e fargli fare una porcheria: saltare il controllo! Ovviamente è bene farlo solo quando serve: per questo c'è _bypassNormalVRISF.


[UPDATE: 29/10/2008]

Il pezzo di codice precedente funziona solo se nella GridView non sono presenti Control. Se è tutto testo OK ma se c'è anche un solo Control (ad esempio un Button), vengono sollevate eccezioni.
Soluzione: prima di eseguire il render in html, bisogna eliminare tutti i Control. Per fare questo il metodo riceve la lista delle colonne da eliminare. Inoltre, per non avere con il metodo VerifyRenderingInServerForm  basta copiare le righe della GridView in un oggetto Table creato al volo.

Codice:

public static void Export(string fileName, GridView gv, int[] skipColumns)
{
    List skipColumnsList = new List(skipColumns);
    using (StringWriter sw = new StringWriter())
    {
        using (HtmlTextWriter htw = new HtmlTextWriter(sw))
        {
            Table table = new Table();
            table.GridLines = GridLines.Both;

            if (gv.HeaderRow != null)
                table.Rows.Add(gv.HeaderRow);

            foreach (GridViewRow row in gv.Rows)                    
                table.Rows.Add(row);                    

            if (gv.FooterRow != null)
                table.Rows.Add(gv.FooterRow);

            foreach (TableRow row in table.Rows)
                RemoveCells(row, skipColumnsList);

            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
            HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName);
            table.RenderControl(htw);
            HttpContext.Current.Response.Write(sw.ToString());
            HttpContext.Current.Response.End();
        }
    }
}

private static void RemoveCells(TableRow row, List skipColumnsList)
{
    for (int i = row.Cells.Count - 1; i >= 0; i--)
        if (skipColumnsList.Contains(i))
            row.Cells.RemoveAt(i);
}


venerdì, aprile 11, 2008

Italiani... non sono poi così male!

Ecco una notizia che mi fa veramente piacere: Jeff Atwood ha donato 5000 dollari al progetto ScrewTurn.
Jeff si era impegnato a donare 5000 dollari ad un progetto open source in tecnologia NET. La scelta è caduta su ScrewTurn, un motore wiki basato su asp.net.
Cosa c'entrano gli italiani? Semplice: ScrenTurn è coordinato da Dario Solera di Milano.

Complimenti Dario!

Esempi di sviluppo insicuro

Ecco alcuni link dal blog di Raffaele Rialdi che illustrano come NON sviluppare applicazioni web:
Il primo è pazzesco: web.config leggibile, db pubblico, sa come utente del db, administrator per la web application. Una summa delle peggiori cose che si possono fare in una web application. E sono riusciti pure a bypassare la sicurezza di NET rendendo leggibile il web.config.

Il secondo, invece, è un po' più subdolo ed ha a che fare più con aspetti di "politica della sicurezza" che con questioni strettamente tecniche.

Entrambbi da leggere assolutamente, commenti compresi!

martedì, aprile 08, 2008

IIS6 StackOverFlow

Sometimes you need to run code with extensive use of stack due to recursive algorithms. But recursion (if very deep) can be very harmful for stack. I encountered such situation, in a particular use of iTextSharp. In my case, IIS 6 (w3wp.exe) crashed with an unknow exception that seemed to be thrown from kernel32.

I spent many hours trying to understand where the problem was. Using WinDbg and AdPlus I understood that the problem came from Net managed code, and after dumping the stack, it was clear which was the method(s).

First: it's not a library bug. If I reduce the work-load (number of input pdf files) it works perfectly. Second: the same piece of code, with the same input pdf files, runs perfectly from a command-line application. So, the problem is related to the IIS "environment".

Solution: increase the stack! Ok, but how ? Simple: running the code inside a thread with a bigger stack!
On IIS6 the "default" threads are created with 256 KB of stack. I haven't found a way to change it. But, from your asp.net code you can create and run a new thread with a bigger stack.

Example code (direct run):

protected void Button1_Click(object sender, EventArgs e)
{
this.Run();
}


private void Run()

{

//... code with or calling library with high use of stack

}



Passing trought a "working" thread (with 1 MB of stack):

protected void Button1_Click(object sender, EventArgs e)
{

this.RunAsSeparatedThread();

}


private void RunAsSeparatedThread()

{

Thread t = new Thread(Run, 1 * 1024 * 1024);

t.IsBackground = true;

t.Start();

t.Join();

}

private void Run()
{

//... code with or calling library with high use of stack

}

domenica, aprile 06, 2008

Inkscape

Some days ago I was looking for a free drawing tool. But not a raster (bitmap) editor. I need a vector editor (like Illustrator or Freehand).
After googling for a while, I found Inkscape www.inkscape.org . It's an opensource vector graphics editor. It's based on SVG standard (W3C standard). Simple but very powerful.



Subversion: primi test con Visual Studio 2005

Primi test con SubVersion e Visual Studio 2005. Risultato: funziona... ma che bel casino!


Al momento sto valutando 2 approcci diversi per l'integrazione frs SVN e VS2005:
TortoiseSVN sembra decisamente più stabile e robusto ma AnkhSVN è molto più comodo da usare: tutte le attività possono essere fatte all'interno di Visual Studio.
Inoltre TortoiseSVN ha strumenti molto più sofisticati per la gestione dei conflitti. Ovviamente si possono usare entrambi: Ankhsvn per le attività "normali", TortoiseSvn per quelle speciali e sofisticate.

Dopo vari casini sono riuscito a mettere su anche Apache con il ModSvn e ad attivare l'Https. A dire la verità i grossi casini sono più nel creare un certificato di prova https per Apache che impostare subversion.



[Update 16/04/2008]

Primi test seri di sviluppo multi-utente: qui cominciano i veri problemi!
Il grosso problema è la fase di merge: è abbastanza comune che 2 sviluppatori abbiano bisogno di mettere mano agli stessi file di codice sorgente. Ad esempio il primo modifica un metodo e il secondo ne aggiunge uno nuovo. Fin qui non ci sono grossi problemi: il più delle volte Ankhsvn è in grado di fare il merge in automatico. In altri casi invece, non riesce a risolvere i conflitti è l'unica è risolverli "a mano" con TortoiseMerge: per ogni riga e/o blocco in conflitto bisogna decidere chi vince oppure se farli vincere entrambi. Se i 2 sviluppatori di prima aggiungono entrambi un nuovo metodo nella stessa zona di codice, si crea un conflitto.



In questo caso è probabile che la soluzione sia di farli convivere entrambi nella file finale.




Ma i veri casini arrivano quando si iniziano ad usare elementi gestiti in modo più o meno automatico da VS2005. Un esempio per tutti: i Typed DataSet. Personalmente li uso molto e come purtroppo immaginavo creano grossi problemi a Subversion. O meglio: subversion crea grossi problemi ai typed dataset. Il problema come al solito è il merge. C'è un dataset che ha già una datatable, 2 utenti lo modificano, ad esempio aggiungendo una datatable a testa. Ovviamente c'è un problema di merge. Ma il typed dataset è più complesso di un semplice file .cs. In gioco ci sono 4 file:
  • MyDS.xsd : dataset vero e proprio (xml)
  • MyDS.Deseigner.cs : file di codice autogenerato da VS2005
  • MyDS.xsc : autogenerato da vs2005
  • MyDS.xss : autogenerato da vs2005. Contiente le informazioni per la rappresentazione a video degli elementi (coordinate xy, larghezza, ecc.)
Il conflitto si può presentare su tutti e 4 i file ma il più importante è il file XSD. Nel mio caso con il tool di Merge ho risolto il conflitto anche se lavorare e muoversi all'interno del xml di un XSD non è la cosa più agevole di questo mondo. Il risultato, dopo vari click e calci in quel posto ai tool coinvolti è stato:




Ma... non è finita. Provo a muovere una tabella e mi becco un bel errore da VS2005.



Dopo vari tentativi, ho cancellato il file .xss e Designer.cs. A questo punto VS li crea nuovamente e tutto sembra tornare a funzionare.

Conclusione (per ora): continuo a fare prove ma non porto nulla in produzione. Subversion e compagni mi convincono ogni giorno sempre di meno.