En el desenvolupament d'aplicacions web cal una infraestructura per accedir a les dades a la BBDD, es a dir les stored procedures (SP) i també cal una forma fàcil per invocar-les. I a ser possible que NO sigui muntar les crides a mà. Per això he muntat la clsDades.
La clsDades és la classe principal que conté tots els métodes d'accés a BBDD. S'encarrega d'invocar les SP en funció de la definició concreta per cada taula. Es per això que la resta de classes hereden d'aquesta, i l'amplien definint amb detall els diferents paràmetres de cada SP.
Estructura clsDades i classes que hereten d'ella
Per tan la clsDades, de fet, conté els mètodes, mentre que la definició la tenen les classes particulars corresponents a cada taula. Per això la clsDades conté la declaració de les llistes de paràmetres i la inicialització es troba separada.
El primer que cal definir són les classes de suport que fa servir la clsDades, es a dir la classe Tipus i la classe clsCamp. Concretament la clsDades conté vectors d'objectes clsCamp destinats a construir els paràmetres de les SP. Per això detallaré aquestes classes primer, a demés que són força simples.
La clase Tipus indica el tipus (valgui la redundància) de BBDD, es farà servir per indicar el tipus en la clase Camp i després en el codi queda més clar.
publicstaticclass Tipus
{
publicconstint bit = 1;
publicconstint tint = 2;
publicconstint bigint = 3;
publicconstint nvarchar = 4;
publicconstint datetime = 5;
publicconstint nchar = 6;
publicconstint dec = 7;
publicconstint varchar = 8;
publicconstint chr = 9;
publicconstint date = 10;
publicconstint time = 11;
}
La classe camp també és força senzilla, conté informació d'un camp de BBDD.
Ok, ja tenim les imatges sel·leccionades, posades en una estructura FormData i enviades al servidor. Ara doncs és el moment de guardar-les on toca i posar-les a la BBDD (només el path). Sempre he estat de la filosofia que qui millor guarda els fitxers són els sistemes de fitxers, les BBDD les deixo sempre per dades (cadenes de text, números etc... no fitxers). Així doncs la rutina següent fa:
Gestió de la carpeta on es guarden els fitxers.
Un bucle que per cada imatge...
La guarda a disc
Insereix les seves dades a la BBDD
privatevoid GetFileAndSave()
{
try
{
Resp.ContentType = "plain/text";
string Arrel = Servr.MapPath("/");
string Any = DateTime.Now.Year.ToString();
string Mes = DateTime.Now.Month.ToString();
clsImatges Imatges = new clsImatges(ConnStr);
Dictionary<string, string> Params = newDictionary<string, string>();
string Imatge;
string IdPost = Req["IdPost"];
string HDDPathImgs;
//Arrel acaba en / per això no cal concatenar-lo
HDDPathImgs = Arrel + PathImgs + "/" + Any + "/" + Mes;
if (!Directory.Exists(HDDPathImgs))
{
Directory.CreateDirectory(HDDPathImgs);
}
foreach (string strFile in Req.Files)
{
HttpPostedFile postedFile = Req.Files[strFile];
Imatge = HDDPathImgs + "/" + postedFile.FileName;
if (!File.Exists(Imatge))
{
postedFile.SaveAs(Imatge);
Params.Add("Imatge", Imatge);
Params.Add("IdPost", IdPost);
Imatges.INS(Params);
Params.Clear();
}
}
Resp.Write("OK");
}
catch (Exception Err)
{
Resp.Write("ERROR: " + Err.Message);
}
}
Un cop guardades les imatges al servidor, el javascript pregunta quines imatges té associades el post per posar-les i que es puguin fer servir. Es fa servir una clase per després serialitzar en JSON. D'això s'encarrega la següent rutina:
Una altra funcionalitat que cobreix la part servidora és la eliminació de fitxers (peticions que també arriben via Ajax). S'ha d'eliminar de la BBDD i del sistema de fitxers.
Sembla que l'upload d'imatges via Ajax sigui el sant grial o la pedra filosofal d'internet. Algo que hauria de ser senzill es complica sobremanera, troves múltiples opcions i solucions. I quan enlloc d'un únic fitxer es volen pujar uns quants alhora ja és la bomba, si afegim barres de progrés UUUAHHH!!!
Sembla que les queixes continues dels desenvolupadors ha aconseguit que aquest tema es vagi posant en l'HTML5, aleshores el que passa és que el suport en diferents navegadors varia. Jo faig servir Firefox, així que per mi que funcioni en FF ja hi ha prou.
He triat una solució que fa servir jQuery i FormData (és una característica de HTML5 i sembla que IE10 la suporta i FF també). De fet disposar d'aquesta eina fa que sigui senzill. El procés consta de varies fases:
Un processat previ en Javascript per omplir l'objecte FormData
Fer una crida ajax amb jQuery configurada d'una forma especial que no causi errors al contenir fitxers (aqui m'he saltat el tema de les barres de progres, posaré com es fa però no ho he implementat)
Fent proves i més proves he trobat que el resaltador de sintaxis en el seu estat original no troba correctament algunes paraules. Per exemple les paraules reservades "get" o "set", o String i StringBuilder.
Estic muntant aquesta pàgina, poc a poc vaig afegint coses que em semblen interessants.
Tinc pensat afegir codi que trobi interessant al blog, com eina de consulta, per aquelles vegades que passa allò de: "això ho tenia fet en algun lloc". I clar si afegeixo codi queda una mica lleig que estigui com text pla. I és aquí on entra el resaltador de sintaxis, per donar-li un xic de color.
Això mateix passa en la demo de jquery que tinc muntada, que en la documentació vaig afegir trossos de codi. Aleshores vaig posar una llibreria javascript que fa aquesta tasca, i funciona prou bé. Com a avantatge té que no es modifica el codi original (es a dir que a la BBDD on està el text del post, el codi està sense modificacions, tal com estava a l'editor), i aleshores desde el manteniment per moltes vegades que s'editi el contingut no es fa cap embolic al guardar (es a dir, quan es guarda des de el manteniment no torna a recalcular la coloració del codi). Com inconvenient té que és javascript, no tots els navegadors van igual, no tothom té el javascript en marxa, començant per un servidor.
Per això m'he decidit a fer un resaltador de sintaxis, però l'he fet en Winforms (sí, sí, la tecnologia en teoria morta), té un "textbox" i un botó. El resultat va a a parar al clipboard i després ho puc engaxar aquí. El blog l'únic que ha de tenir en compte és afegir uns estils al CSS i llestos. Haig de conservar el codi original en fitxers de text per si haig de retocar el codi colorejat.
I que millor que fer servir d'exemple que el propi codi del colorejador...
//////////////////////////////////////////////////////////////////////////////// This source code and all associated files and resources are copyrighted by// the author(s). This source code and all associated files and resources may// be used as long as they are used according to the terms and conditions set// forth in The Code Project Open License (CPOL).//// Copyright (c) 2013 Jonathan Wood// http://www.blackbeltcoder.com//using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
namespace Colorizer
{
/// <summary>/// Class to colorize source code by inserting HTML markup around language tokens./// </summary>publicclass clsColorizer
{
// Language rules collectionpublic LanguageRulesCollection Languages { get; set; }
// Token class namespublicstring CssClassKeyword { get; set; }
publicstring CssClassSymbol { get; set; }
publicstring CssClassString { get; set; }
publicstring CssClassOperator { get; set; }
publicstring CssClassComment { get; set; }
/// <summary>/// Colorizer construction/// </summary>/// <param name="languageRulesFile">Name of XML file that contains all language rules</param>public clsColorizer(string languageRulesFile)
{
// Load language rules
Languages = new LanguageRulesCollection(languageRulesFile);
}
/// <summary>/// Color codes a block of source code using the specified language/// </summary>/// <param name="code">Source code to format</param>/// <param name="language">Language to use for formatting</param>/// <returns></returns>publicstring ColorizeCode(string code, string language)
{
// Load rules for the specified language
LanguageRules rules = Languages.GetLanguageRules(language);
if (rules == null)
thrownewException(String.Format("Undefined language \"{0}\" was specified", language));
// CSS class lookup tableDictionary<TokenClass, string> cssClasses = newDictionary<TokenClass, string>()
{
{ TokenClass.Keyword, CssClassKeyword },
{ TokenClass.Symbol, CssClassSymbol },
{ TokenClass.String, CssClassString },
{ TokenClass.Operator, CssClassOperator },
{ TokenClass.Comment, CssClassComment },
};
// Tokenize source code according to specified language rulesStringBuilder builder = newStringBuilder();
LanguageTokenizer tokenizer = new LanguageTokenizer(rules, code);
for (Token token = tokenizer.ParseNext(); token.Class != TokenClass.Null; token = tokenizer.ParseNext())
{
token.Value = WebUtility.HtmlEncode(token.Value);
string style;
if (cssClasses.TryGetValue(token.Class, out style) && !String.IsNullOrWhiteSpace(style))
builder.AppendFormat("<span class=\"{0}\">{1}</span>", style, token.Value);
else
builder.Append(token.Value);
}
return builder.ToString();
}
}
}
El més difícil alhora de fer un resaltat de sintaxis és trobar els identificadors de tipus, no he trobat cap resaltador que ho faci bé. Bé això no és del tot cert, hi ha un que sí ho fa però gairebé et compila l'aplicació (per saber quins tipus hi ha, i no és capaç de trobar-los en trossos de codi petits o aillats). També hi ha unes "productivity tools" del VisualStudio que et permeten guardar el codi com HTML, però al final m'he decidit per una cosa senzilleta i que no tingui que afegir res al VisualStudio, encara que no troba gaire bé els identificadors de tipus, he afegit els més comuns StringBuilder, DataTable etc...
#30/10/2013 23:05 Programació C# HTML/CSS Autor: Alex Canalda