A vegades haig d'invocar Webservices de formes rares, aleshores ensopegues amb les llibreries i eines que et proporciona l'arquitectura que fas servir. Per exemple potser l'eina WSDL del .NET no et genera les classes correctament, o bé el Webservice fa servir WS-Addressing, o ...
I es que de fet, si un s'ho para a pensar el SOAP no és res més que XML, i text al fi i al cap. I el que es diu "invocar a un Webservice" no és res més que HTTP POST contra una URL d'un servidor web. Com a molt, i principal diferència amb una petició HTTP normal s'ha d'afegir una capçalera HTTP, el SOAPAction en SOAP 1.1, en 1.2 no cal posar-la.
Aleshores quan un vol invocar a un Webservice el que ha de fer és ajuntar un text, un XML, i fer un POST. Donat que això és senzill he fet un programa per fer tests ràpids de Webservices, es el SOAP Poster.
El SOAP Poster és una aplicació Winforms que amb un interface simple permet enviar un text a una URL. Amb alguns detalls, com per exemple si s'ha de fer servir un proxy, o HTTP-Basic Authentication o si cal fer proves de concurrència hi ha un número que indica la quantitat d'invocacions. El codi està directament posat als events dels controls. El veure'm en detall en futurs posts.
El SOAP poster en acció
#11/02/2015 11:26 Programació C# Autor: Alex Canalda
M'ha passat que he intentat obrir un projecte del tipus ".rptproj" en Visual Studio m'ha dit que "tururú", que aquest tipus de projecte no està suportat.
El que cal instal·lar per que es puguin obrir NO és cap característica del Visual Studio, és del SQL Server.
En la instal·lació del SQL Server cal marcar el "Bussines intelligence development studio", també conegut com BIDS.
La casella del BIDS
Aleshores en el "About" del Visual Studio apareixen 3 nous dissenyadors, un d'ells el de reports.
Els 3 nous dissenyadors.
I voilà, ja podem fer projectes de reporting.
#14/01/2015 17:55 Programació SQLServer Autor: Alex Canalda
Quan es deserialitzen valors que venen d'un JSON contra un formulari normalment tots els controls del formulari reben correctament els valors del JSON. Tots? No! Un grup d'irreductibles controls es resisteixen a l'invasor. Els "checkboxes"!
En el JSON es poden passar els booleans de dues formes diferents, el serialitzador genera el JSON de forma diferent segons l'origen. Es poden serialitzar de forma nativa ja que el JSON suporta el tipus booleà, llavors es troba algo com: "Camp_boolea": true. En canvi també es pot serialitzar com un "string", i queda així: "Camp_boolea": "True", cal fixar-se en les cometes...
Quan es declara un control checkbox s'ha de fer de les següents maneres, si al JSON arriba un booleà:
Canvia el value, i el que no és tan intuïtiu és que surti un value="1" pel JSON booleà. També cal tenir en compte el deserialitzador javascript que es fa servir...
#05/11/2014 11:33 Programació Javascript HTML/CSS Autor: Alex Canalda
Estava meditant sobre els operadors de les expressions regulars i hi ha un modificador que no acabava d'entendre. És l'operador "?", que especifica que funciona en mode mandrós enlloc de golut. I això del golut i del mandrós (o "greedy" i "lazy" en guiri) que és?
Suposem que volem construir una expressió regular que encaixi en un tag HTML. Seria algo així:
<.+>
Es a dir: "<" per l'inici de tag, "." per qualsevol caràcter, "+" per dir repetició i ">" pel fi del tag. D'aquesta manera l'expressió encaixaria amb "<em>" o amb "<body>" o amb "<table>" o amb... Però aleshores aquesta expressió regular també es menjaria això, que seria incorrecte:
<em>Hello World</em>
Es a dir, funciona en mode golut i el ".+" vol encaixar el màxim nombre de caràcters i aleshores retorna tot el text sencer (el que hi ha entre els caràcters en vermell, encaixa el primer "<", després qualsevol caràcter (inclòs el segon ">") i tanca amb l'últim ">"). Si es vol que només agafi el primer tag caldria posar l'expressió regular en mode mandrós, així:
<.+?>
Observar que s'ha afegit el "?" per indicar que el ".+" funciona en mode mandrós. Aleshores obtindria el següent:
<em>Hello World</em>
Es a dir s'atura en el següent ">" que troba i no segueix encaixant caràcters.
En una aplicació a vegades cal un petit fitxer de configuració, actualitzable etc... llavors amb la clsConfig hi ha prou. A vegades cal guardar més dades, més estructurades, aleshores és quan es fan servir BBDD, ja que un fitxer XML té un mal rendiment guardant dades (s'ha de llegir sencer per modificar-lo). Però tampoc cal un SQL Server si no es vol més que guardar unes quantes dades, ni pagar llicències ni instal·lar res.
Per això he estat buscant un BBDD local que es pugui enganxar a un programet, i he trobat que el SQLServerCE (made by Microsoft) s'ajusta força a aquestes necessitats. L'únic problema que té és que Microsoft sembla que no el vol mantenir més ja que suposo que estaria menjant-se vendes de petits SQLServers. També he llegit que és possible que el torni a posar al VisualStudio (encara que això ja és més un rumor). El cas és que la última versió del SQLServer CE és força recent i s'integra perfectament amb el VisualStudio 2013 si es sap com.
El primer que cal fer és instal·lar les eines del SQLServer CE (el "ToolBox"), amb això al menú "TOOLS" ens apareix una nova opció que ens permet crear BBDD de SQLServerCE, veure els camps, executar scripts, ...
SQL Server CE Toolbox
Un cop les eines estan instal·lades cal poder accedir des de programa a la BBDD. Aquí és on m'ha costat més per que no està del tot clar. El que cal fer és copiar la DLL del SQLServer CE a la carpeta del projecte que estem desenvolupant. Normalment aquesta carpeta està a: "C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v4.0\Private" (s'ha de copiar sencera, amb subcarpetes). Un cop copiada la carpeta, cal posar a l'arrel del projecte les carpetes "amd64" i "x86" (aquestes dues carpetes són subcarpetes de la "Private"). Totes les DLLs han d'estar marcades com "Copiar si es modifiquen" en l'acció "Copiar al directori de sortida" (es fa fent "Propiedades" sobre la DLL). Un cop fet això es posa la "Referència" a la DLL "System.Data.SqlServerCe.dll". Queda així:
Resultat
A partir d'aquest moment ja es pot fer servir el SQLServer CE en VisualStudio 2013.
#31/05/2014 16:08 Programació C# SQLServer Autor: Alex Canalda
Amb HTML5 es pot carregar un fitxer de l'ordinador local on està el navegador directament a una pàgina web, sense passar pel servidor web. Antigament per fer això calia pujar el XML al servidor, aquest processar-lo i enviar-te el HTML amb els controls degudament informats. Això s'ha acabat, al menys en Firefox. Cal fer un HTML com el següent:
Un cop fet això cal fer el següent script (té el document.ready del jQuery, així que s'ha de posar el jQuery també):
<script>
var reader = new FileReader();
reader.onload = function (e) {
var text = reader.result;
if (window.DOMParser) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(text, "text/xml");
$("#test").val(xmlDoc.getElementsByTagName("SOAPAction")[0].childNodes[0].nodeValue);
}
else {
alert("No hi ha parser!");
}
}
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object// files is a FileList of File objects. List some properties.var output = [];
for (var i = 0, f; f = files[i]; i++) {
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
reader.readAsText(f);
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
$(document).ready(function () {
// Check for the various File API support.if (window.File && window.FileReader && window.FileList && window.Blob) {
document.getElementById('files').addEventListener('change', handleFileSelect, false);
} else {
alert('The File APIs are not fully supported in this browser.');
}
});
</script>
Com es pot veure a l'exemple, el XML ha de tenir el tag "SOAPAction" i el seu valor es posa al control "test", i llestos!
#26/05/2014 16:06 Programació Javascript HTML/CSS Autor: Alex Canalda
Igualment que poques vegades totes les dades estan en una única taula, poques vegades no cal filtrar per cap camp. El Generador té suport per això.
És en aquest punt on entren els camps que permeten filtrar una taula, també els anomeno "Params extra" ja que són paràmetres s'afegeixen als que hi ha per defecte. Per defecte hi ha la clau primària de la taula per tal de permetre treballar o seleccionar només un registre. Al fer JOINS també es poden incloure camps d'altres taules per filtrar.
En els paràmetres de filtrat cal avaluar quina estratègia es fa servir, ja que depenent de la quantitat de paràmetres cal convertir la consulta a una amb suport de WHERE's dinàmics.
El interface permet generar els WHEREs més normals, una comparació directa, una altra amb operador habituals (>, <, >=, <=...), hi ha el cas de comparació amb NULL (marcar la casella Null compare, es genera un IS NULL), amb strings fent LIKE (amb dos sabors, que coincideixi el principi del camp o qualsevol lloc del camp. Finalment el BETWEEN per dates (s'especifica el camp i després els paràmetres, per exemple si es vol filtrar per data alta, es posa el camp DataAlta a la informació del camp, i després es posa Inici, Fi i es marca la casella. Això crea dos paràmetres Inici i Fi, i es genera el BETWEEN amb el camp).
També cal pensar que si un mateix camp es pot filtrar per diferents operadors, no hi ha problema en afegir-lo més d'un cop, només cal posar noms diferents.
Aqui s'especifiquen els WHEREs.
#12/05/2014 10:43 Programació SQLServer Autor: Alex Canalda
En poques ocasions totes les dades que requereix un formulari estan en una única taula. En aquest punt és on entren en joc els JOINS.
El Generador té suport per JOINS, de tal manera que es poden obtenir dades de més d'una taula d'una sola consulta. Encara que els UPDATE/INSERT/DELETE només funcionen per la taula en la que s'està treballant. Els JOINs només es generen pels SELECT/QUERY.
La forma d'indicar-los és fàcil, taula origen, camp origen, taula destí, camp destí. També cal indicar si és un LEFT JOIN o un INNER JOIN.
Els LEFT JOIN són els que estan per defecte ja que obtenen dades de la taula principal independentment que tinguin un registre relacionat a la taula a la que es fa el JOIN.
Per exemple si estem fent el mestre de Comarques, i es vol obtenir la Província, cal fer un JOIN, es serialitza el camp per enviar-lo al formulari per no es deserialitza al no pertànyer a la taula que s'està editant. Quan es fan servir JOINs aleshores ja es poden afegir camps de la taula que s'ha afegit a la llista de camps a retornar (marcant que s'han de serialitzar), i a més a més també es poden posar com paràmetres del WHERE. Cal anar amb compte perque els JOINs introdueixen duplicats, i potser cal marcar el DISTINCT o valorar la forma de fer el CTE, si amb ROW_NUMBER o DENSE_RANK.
Part de la pantalla on es defineixen els JOINs
#07/05/2014 10:29 Programació SQLServer Autor: Alex Canalda
A vegades és necessari comparar objectes i s'ha de proporcionar a altres classes alguna forma de fer aquesta comparació. Per aquest motiu s'ha d'implementar l'interficie IEquatable.
En el Generador això és necessari per que treballa amb llistes d'objectes. Les llistes tenen un mètode força interessant que es diu "Contains", que indica si una llista té dins seu un objecte com el que es passa per paràmetre, però això necessita que la classe que defineix els objectes de la llista tingui implementat el IEquatable. Veiem el codi, a la classe clsTaula hi ha el mètode que afegeix camps a la taula:
publicvoid AddCamp(clsCamp Camp)
{
if (Camps == null) Camps = newList<clsCamp>();
if (!Camps.Contains<clsCamp>(Camp)) Camps.Add(Camp);
}
Aleshores cal que la classe clsCamp implementi el IEquatable: