
Fuente: http://www.telerikwatch.com/2011/09/how-to-pick-your-platform-silverlight.html
Blog sobre desarrollo de aplicaciones Software basado en tecnología Microsoft (.Net/SQL/IIS) y otras (php/MySQL/Apache/Android...).
El pasado jueves 4 de octubre asistí al evento de lanzamiento del nuevo Visual Studio 2012. En este post quiero resumir lo más destacable.
La empresa Acciona (apoyados por Plain Concepts) ha desarrollado su propia aplicación para el control en tiempo real de las plantas de generación de energía: SCADA. A destacar:
(Ésta me la perdí…)
Charla entretenida e interesante, de la que podemos encontrar un amplio resumen en el blog del ponente (http://dasalga.wordpress.com/2012/10/08/charla-de-web-cloud-en-vslaunch/). Habló de:
Si decidimos utilizar Entity Framework para diseñar nuestro modelo de datos, tenemos la opción de utilizar el diseñador gráfico (siguiendo el patrón Database-First o Model-First dependiendo de si partimos de una base de datos existente o no), o crearlo “a pelo” (siguiendo el patrón Code-First). Para más info sobre estos patrones ver el post Database first vs Model first vs Code first.
Ambas formas de trabajar tienen sus gracias y sus inconvenientes:
La primera nos simplificará el trabajo de modelado de entidades y conexión con la base de datos, y además nos aporta una representación gráfica que siempre ayuda.
Para ello simplemente tenemos que añadir a nuestro proyecto un elemento de tipo ADO.NET Entity Data Model:
La segunda forma de trabajar (sin utilizar el diseñador gráfico que proporciona ADO.NET Entity Data Model) nos dará mayor libertad para crear nuestras entidades y basarnos por ejemplo en un modelo de objetos POCO.
Una de las posibilidades más interesantes es partir del modelo gráfico de ADO.NET Entity Data Model y a partir de él generar las entidades POCO y el contexto de BDD. Esto se puede conseguir utilizando un generador de código desde el diseñador:
Como se ve existen multitud de plantillas entre las que elegir, y no es objetivo de este post explicar cada una de ellas. Para generar un modelo de objetos POCO nos pueden servir por ejemplo ADO.NET POCO Entity Generator y ADO.NET DbContext Generator.
Data Annotations permite añadir validaciones al modelo de datos que luego tendrán reflejo en la vista. A continuación mostraré un ejemplo de aplicación hecha con ASP.NET con una única entidad (Team) definida en el modelo de datos y su controlador y vistas creadas por scaffolding (ver post Cómo crear un CRUD (mantenimiento) básico Web utilizando ASP.Net MVC y Entity Framework).
Supongamos que partimos de una entidad Team definida así:
using System.ComponentModel;
using System;using System.Collections.Generic;namespace PruebaEF
{
public partial class Team
{
public int Id { get; set; }public string Name { get; set; }public string City { get; set; }
}
}
Si creamos el controlador y las vistas mediante scaffolding y ejecutamos el proyecto tendremos (ojo, tendremos que añadir /teams a la URL inicial).
Si modificamos la entidad añadiendo Data Annotations podemos conseguir algunas validaciones sin necesidad de modificar ni el controlador ni la vista. Veamos el siguiente ejemplo:
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System;
using System.Collections.Generic;
namespace PruebaEF
{
public partial class Team
{
[DisplayName("Identificador")]
public int Id { get; set; }
[DisplayName("Nombre del club")]
[StringLength(10)]
public string Name { get; set; }[DisplayName("Ciudad")]
public string City { get; set; }
}
}
El resultado sería el siguiente (sin necesidad de modificar ni el controlador ni las vistas):
Pero si las entidades las generamos utilizando ADO.NET Entity Data Model tal como se explica en el post anterior (Modelo POCO a partir de ADO.NET Entity Data Model), cada vez que hagamos una modificación desde el diseñador, perderemos las Data Annotations. ¿Y qué podemos hacer al respecto? Tenemos varias opciones aunque ninguna me parece perfecta:
<?php
define('USERPWD','192.168.0.150\Administrador:xxx'); // Sustituir xxx por la contraseña del servidor include("NTLMStream.php"); include("NTLMSoapClient.php"); stream_wrapper_unregister('http'); stream_wrapper_register('http','NTLMStream') or die("Fallo al registrar protocolo"); $pageURL = 'http://192.168.0.150:7047/dynamicsnav/ws/Autoequip/Codeunit/NEUMALIAWS'; // El Web Service $params = array(); $params["param1"] = "2855519MDIAMARISVR"; // param1 es el nombre el primer parámetro.
$params["param2"] = "2";
$params["param3"] = "1024";
$client = new NTLMSoapClient($pageURL); stream_wrapper_restore('http'); $result = $client->ImportPedNeumalia($params); // El método del Web Service $numped = $result->return_value; echo 'Pedido creado: '.$numped; die(); ?>
Los módulos php incluídos son:
NTLMStream.php
<?php class NTLMStream { private $path; private $mode; private $options; private $opened_path; private $buffer; private $pos; /** * Open the stream * * @param unknown_type $path * @param unknown_type $mode * @param unknown_type $options * @param unknown_type $opened_path * @return unknown */ public function stream_open($path, $mode, $options, $opened_path) { $this->path = $path; $this->mode = $mode; $this->options = $options; $this->opened_path = $opened_path; $this->createBuffer($path); return true; } /** * Close the stream * */ public function stream_close() { curl_close($this->ch); } /** * Read the stream * * @param int $count number of bytes to read * @return content from pos to count */ public function stream_read($count) { if(strlen($this->buffer) == 0) { return false; } $read = substr($this->buffer,$this->pos, $count); $this->pos += $count; return $read; } /** * write the stream * * @param int $count number of bytes to read * @return content from pos to count */ public function stream_write($data) { if(strlen($this->buffer) == 0) { return false; } return true; } /** * * @return true if eof else false */ public function stream_eof() { return ($this->pos > strlen($this->buffer)); } /** * @return int the position of the current read pointer */ public function stream_tell() { return $this->pos; } /** * Flush stream data */ public function stream_flush() { $this->buffer = null; $this->pos = null; } /** * Stat the file, return only the size of the buffer * * @return array stat information */ public function stream_stat() { $this->createBuffer($this->path); $stat = array( 'size' => strlen($this->buffer), ); return $stat; } /** * Stat the url, return only the size of the buffer * * @return array stat information */ public function url_stat($path, $flags) { $this->createBuffer($path); $stat = array( 'size' => strlen($this->buffer), ); return $stat; } /** * Create the buffer by requesting the url through cURL * * @param unknown_type $path */ private function createBuffer($path) { if($this->buffer) { return; } $this->ch = curl_init($path); curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($this->ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_setopt($this->ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM); curl_setopt($this->ch, CURLOPT_USERPWD, USERPWD); $this->buffer = curl_exec($this->ch); $this->pos = 0; } } ?>
NTLMSoapClient.php
<?php
class NTLMSoapClient extends SoapClient { function __doRequest($request, $location, $action, $version) { $headers = array( 'Method: POST', 'Connection: Keep-Alive', 'User-Agent: PHP-SOAP-CURL', 'Content-Type: text/xml; charset=utf-8', 'SOAPAction: "'.$action.'"', ); $this->__last_request_headers = $headers; $ch = curl_init($location); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POST, true ); curl_setopt($ch, CURLOPT_POSTFIELDS, $request); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM); curl_setopt($ch, CURLOPT_USERPWD, USERPWD); $response = curl_exec($ch); return $response; } function __getLastRequestHeaders() { return implode("\n", $this->__last_request_headers)."\n"; } } ?>
NOTA: Debemos asegurarnos que la extensión php_soap está habilitada; de lo contrario se producirá un error similar a este:
En el caso de tener WAMP como servidor de Apache/PHP/MySQL, esta opción la encontraremos dentro de las PHP_Extensions.