Could not load type ‘System.ServiceModel.Activation.HttpModule’ from assembly ‘System.ServiceModel, Version=3.0.0.0 […]

Uno de los incidentes que nos podemos encontrar al tener instalado el nuevo Framework 4.0 es que nuestras aplicaciones con WCF anteriores dejen de funcionar por el siguiente motivo:

Para solucionarlo, debemos acceder al servidor de aplicaciones (IIS), nos posicionamos en el sitio que nos está fallando y accedemos al apartado de Módulos:

Una vez allí, quitamos la versión 3.0 de ServiceModel, quedando únicamente la versión 4.0.

 

Espero que sea de utilidad.

¡Saludos!

Promoción especial de lanzamiento de la plataforma Windows Azure

Para todos aquellos que no disponemos de subscripción MSDN, o simplemente queremos probar la plataforma Windows Azure para ver si se ajusta a nuestros desarrollos, Microsoft nos ofrece un paquete especial de lanzamiento que finalizará el 31 de Julio del 2010. Si bien es un paquete reducido, será suficiente para poder realizar las pruebas necesarias.

Cada mes se incluye de forma gratuita:

  • Windows Azure
    • 25 horas de instancia de proceso pequeña
    • 500 MB de almacenamiento
    • 10.000 transacciones de almacenamiento
  • SQL Azure
    • 1 base de datos Web Edition (disponible sólo los 3 primeros meses)
  • AppFabric
    • 100.000 transacciones de Access Control
    • 2 conexiones a Service Bus
  • Transferencias de datos (por región)
    • 500 MB de entrada
    • 500 MB de salida

Cualquier uso mensual que exceda las cantidades mencionadas anteriormente se cobrará según las tarifas estándar. El precio especial de lanzamiento finalizará el 31 de julio de 2010. A partir de entonces, se aplicarán las tarifas estándar de uso.

Tarifas estándar:

Windows Azure

  • Proceso
    • Instancia pequeña (predeterminada): 0,0852 € por hora
    • Instancia media: 0,1703 € por hora
    • Instancia grande: 0,3405 € por hora
    • Instancia extragrande: 0,6809 € por hora
  • Almacenamiento
    • 0,1064 € por GB almacenado al mes
    • 0,0071 € por cada 10.000 transacciones de almacenamiento
  • Red de entrega de contenido (CDN)
    • Disponible actualmente como un servicio gratuito de Community Technology Preview (CTP)

SQL Azure

  • Web Edition: hasta 1 GB de base de datos relacional
    • 7,085 € por base de datos al mes
  • Business Edition: hasta 10 GB de base de datos relacional
    • 70,913 € por base de datos al mes

AppFabric

  • Access Control
    • 1,4114 € por cada 100.000 transacciones*
  • Service Bus
    • 2,8298 € por conexión mediante un sistema de pago por uso*
    • Paquete de 5 conexiones 7,0566 €*
    • Paquete de 25 conexiones 35,2827 €*
    • Paquete de 100 conexiones 141,1308 €*
    • Paquete de 500 conexiones 705,654 €*

Transferencias de datos

  • Regiones de Norteamérica y Europa
    • 0,071 € por GB de entrada
    • 0,1064 € por GB de salida
  • Región de Asia Pacífico
    • 0,2128 € por GB de entrada
    • 0,3192 € por GB de salida
  • Las transferencias de datos de entrada serán gratuitas durante las horas de menor afluencia hasta el 30 de junio de 2010. A partir del 30 de junio de 2010, se restablecerán los precios estándar para las transferencias de datos de entrada.

Si bien he leído, la cuenta es cancelable en cualquier momento por lo que deberíamos asegurarnos de anularla en la fecha de finalización de la promoción o, por el contrario, ajustarnos a las tarifas que nos indican.

CREACIÓN DE LA CUENTA

Para activar nuestra cuenta, debemos dirigirnos al portal del cliente de Microsoft Online Services y, una vez allí, nos posicionamos en el link de los detalles del servicio Windows Azure. En este apartado, podemos ver todos los servicios disponibles y una oferta especial. Pulsaremos en el botón comprar de la oferta.

Para la activación de la promoción es necesaria una cuenta passport. Deberemos rellenar nuestros datos personales y además nos solicitarán una tarjeta de crédito o débito para cargar los posibles gastos que pudiéramos generar, en el caso de que nos pasáramos de las horas o transacciones que nos ofrecen en la promoción. Una vez realizados todos los pasos ya podríamos disfrutar de la promoción de la plataforma Windows Azure.

¡Saludos!

[Slides] Desarrollo con Windows Azure

El pasado 14 de Abril Aventia-Renacimiento ofreció un evento sobre la plataforma Windows Azure en colaboración con Microsoft. Tuve la suerte de poder dar una de las charlas, concretamente la parte de desarrollo en la nube, donde expliqué las herramientas, los tipos de servicios que nos ofrecen, cómo subir nuestros proyectos a la nube, etcétera.

Adjunto un documento pdf con las slides que comenté en el evento.

Espero que sea de utilidad 🙂

¡Saludos!

Crear un email con imágenes embebidas

Cuando creamos un email desde .NET solemos intentar que el formato del mismo sea bastante aceptable… O deberíamos 😛

En ocasiones, es necesario incluir imágenes en el mismo y aquí es donde comienzan los problemas: Si referenciamos una imagen que está en un servidor concreto puede que ese servidor deje de existir, o eliminen la imagen, cambien la ruta, etcétera.

Por ello, creo que lo mejor es embeber estas imágenes dentro del correo y hacer referencia a las mismas. ¡Vamos a verlo!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail;
using System.Net;
using System.IO;

namespace EmailAndImages
{
public class Email
{
public static void EnviarMail(MyEmail email)
{

MailMessage mailMessage = new MailMessage();

mailMessage.From = new MailAddress(email.sender);

foreach (string addressee in email.addressees)
mailMessage.To.Add(addressee);

mailMessage.Subject = email.subject;

AlternateView alternateView = AlternateView.CreateAlternateViewFromString("<img id='header' alt='header' src='cid:idImage'/><p>Hello <strong>world</strong></p>", null, "text/html");

LinkedResource linkedResource;

using (WebClient webClient = new WebClient())
{
webClient.UseDefaultCredentials = true;
byte[] buf = webClient.DownloadData(email.imgURI);
MemoryStream memoryStream = new MemoryStream(buf);
linkedResource = new LinkedResource(memoryStream);
}

linkedResource.ContentId = "idImage";

alternateView.LinkedResources.Add(linkedResource);
mailMessage.AlternateViews.Add(alternateView);

SmtpClient smtpClient = new SmtpClient("10.10.10.50");

smtpClient.Send(mailMessage);
}
}
}

Un dato muy importante a tener en cuenta es que LinkedResource no soporta URIs, por lo que tuve que hacer uso de WebClient para recuperar la imagen en un MemoryStream y posteriormente adjuntarla.

Espero que sea de utilidad.

 ¡Saludos!

Utilizando el API de TinyUrl

Todos aquellos que frecuentamos Twitter estamos más que acostumbrados a ver direcciones cortas generadas por distintos proveedores. En este post voy a mostrar un pequeño ejemplo de cómo podríamos utilizar uno de estos proveedores, TinyUrl, para conseguir esas direcciones cortas desde nuestra aplicación.

En primer lugar he creado un pequeño formulario Ajax con ASP.NET MVC:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Tiny Url Maker
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<p>
<% using (Ajax.BeginForm("MakeTinyUrl", new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "tinyUrl" }))
{%>
<%=Html.TextBox("url") %>
<input id="btnMakeUrl" type="submit" value="Make tinyUrl" />
<%
}%>
</p>
<div id="tinyUrl">
<%Html.RenderPartial("TinyUrl"); %>
</div>
</asp:Content>

Al pulsar en el botón, de manera asíncrona, llamaremos a la acción MakeTinyUrl donde llamaremos a la API disponible.

using System.IO;
using System.Net;
using System.Web.Mvc;

namespace TinyURLAPI.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";

return View();
}

[HttpPost]
public ActionResult MakeTinyUrl(string url)
{
var tinyUrl = WebRequest.Create("http://tinyurl.com/api-create.php?url=" + url);
var shortUrl = tinyUrl.GetResponse();

using (var reader = new StreamReader(shortUrl.GetResponseStream()))
{
ViewData["tinyUrl"] = reader.ReadToEnd();
}
return PartialView("TinyUrl");

}
}
}

Si arrancamos la aplicación e introducimos cualquier url, el resultado sería el siguiente:

¡Saludos!

Subir un disco duro virtual (vhd) a Windows Azure Storage

Windows Azure Drive, aún en fase beta, es una de las posibilidades dentro de Windows Azure Storage la cual nos permite montar un disco duro virtual en formato NTFS en la nube. En este post voy a mostrar la forma de crear un VHD desde Windows 7 y de subir el mismo.

CREACIÓN DEL DISCO DURO VIRTUAL (VHD)

En primer lugar, debemos acceder a la administración de discos, por ejemplo, a través del botón derecho sobre Mi PC y Administrar.

Pulsamos sobre  Acción y seleccionamos Crear VDH.

Nos aparece una nueva ventana, donde debemos seleccionar la ubicación, el tamaño y si queremos que se expanda de forma dinámica o, por el contrario, deseamos un tamaño fijo.

En realidad, el objetivo de este post es almacenar en un Blog de tipo página el vhd. Por ello hay que tener en cuenta que el tamaño mínimo debe ser de 16MB y el tamaño máximo de 1 TB.
Al aceptar la creación, un «nuevo dispositivo» se instalará en nuestro equipo y el proceso será completado con el siguiente mensaje informativo:

Si accedemos de nuevo al administrador de discos, nos informará de que existe un disco no inicializado y nos dará la opción de hacerlo. Si no habíamos abandonado la ventana, podemos realizar la misma operación seleccionando el disco duro virtual y pulsamos sobre Inicializar.

Hacemos clic con el botón derecho sobre el disco y seleccionamos Nuevo volumen simple, dándole formato NTFS.

He incluido una imagen dentro del disco virtual para comprobar que, al subirlo a la nube, la información se mantiene y el disco funciona correctamente.

 Por último, en el administrador de discos nuevamente, pulsamos sobre él con el botón derecho y seleccionamos Ocultar VHD y dejamos las opciones por defecto de la siguiente ventana.

Ahora podemos visualizar el archivo vhd en la ubicación que indicamos durante la creación.

SUBIR EL DISCO DURO VIRTUAL A LA NUBE

Para realizar la subida del disco, he creado una pequeña aplicación donde se realizan dos acciones: La creación del contenedor y el page blob que ocupará el vhd y la subida del mismo.

using System;
using System.Configuration;
using System.IO;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace WADriveMaker
{
class Program
{
static void Main()
{
const string fileName = @"C:VHDsCloud Drive.vhd";

var file = File.Open(fileName, FileMode.Open);
var pageBlob = GetPageBlob(file.Length);
try
{
const int pageSize = 2048;
var numPages = file.Length / pageSize;
var page = new byte[pageSize];

using (var memoryStream = new MemoryStream(page))
{
for (var i = 0; i < numPages; i++)
{
file.Read(page, 0, pageSize);
memoryStream.Seek(0, SeekOrigin.Begin);
pageBlob.WritePages(memoryStream, i * pageSize);
var percentage = (float)((i * 100) / numPages);
Console.CursorLeft = 0;
Console.CursorTop = 0;
Console.WriteLine("Uploading {0}%", percentage);
}
if (file.Length > pageSize * numPages)
{
var lastPiece = (int)(file.Length - (pageSize * numPages));
var lastPage = new byte[lastPiece];

using (var lastStream = new MemoryStream(lastPage))
{
file.Read(lastPage, 0, lastPiece);
lastStream.Seek(0, SeekOrigin.Begin);
pageBlob.WritePages(lastStream, pageSize * numPages);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex.Message);
}
finally
{
file.Close();
}
Console.WriteLine("Upload completed!");
Console.WriteLine("URL Drive: {0}", pageBlob.Uri);
Console.ReadLine();
}

private static CloudPageBlob GetPageBlob(long size)
{
CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) => configSetter(ConfigurationManager.ConnectionStrings[configName].ConnectionString));

var storageAccount = CloudStorageAccount.FromConfigurationSetting("BlobConnectionString");
var cloudBlobClient = storageAccount.CreateCloudBlobClient();
var container = cloudBlobClient.GetContainerReference("drives");
container.CreateIfNotExist();
var pageBlob = container.GetPageBlobReference("Cloud drive in Azure.vhd");
pageBlob.Properties.ContentType = "binary/octet-stream";
pageBlob.Create(size);

return pageBlob;
}


}
}

 

Una vez finalizada la subida, he usado una utilidad llamada Gladinet Cloud Desktop, la cual nos permite mapear almacenamientos de tipo cloud de varios proveedores, entre ellos el de Windows Azure Storage. Si accedo a mi almacenamiento en la nube, compruebo que la operación se ha realizado correctamente.

En un próximo post, veremos cómo montar esa unidad en la nube y que nuestras aplicaciones puedan hacer uso de ella.

¡Saludos!

[Aventia-Renacimiento] Evento Cloud computing – Análisis de negocio y Windows Azure (Por Aventia-Renacimiento en colaboración con Microsoft)

El 14 de Abril Aventia-Renacimiento os ofrece un evento donde se expondrá la plataforma Windows Azure.

Por la
mañana, el evento será mayoritariamente ‘de negocio’
y por la tarde se realizarán sesiones y laboratorios
técnicos.

Agenda.


9:30 – 10:00.
Recepción.


10:00 – 10:45.
Ventajas para el negocio –
Pedro Lisbona ( Doxa ).


10:45 – 11:30.
Cloud-Computing y aspectos legales
Pablo García Mexia y Kitty Aguilera. (Expertos
juristas)


11:30 – 11:45.
Break Café


11:45 – 12:45.
Posicionamiento Cloud-Computing de
Microsoft – Cesar de la Torre (Microsoft).


12:45 – 13:30.
SharePoint OnLine – Mario
Cortés. (Renacimiento)


13:30 – 14:45.
Break Lunch. Comida


14:45 – 15:30.
Desarrollo con Azure – Gisela
Torres (Renacimiento)


15:30 – 16:15.
SQL Azure – Ignacio Arranz
(Renacimiento)


16:15 – 16:30.
Break Café


16:30 – 18:00.
Labs Creación App y cuenta en
Windows Azure – Roberto Gonzalez (Renacimiento)


(*) IMPORTANTE : Para la realización de los
LABS es necesario que cada asistente a los LABS traiga un
ordenador portátil con el siguiente software instalado:


  • Visual Studio 2008 ó Visual Studio 2010 RC

  • SQL Server Express (Incluido en instalación de Visual
    Studio)

  • Tools de Windows Azure para Visual Studio (Se podrá
    instalar durante el propio laboratorio)


Para la creación de cuenta de pruebas y subida de aplicación de
pruebas a la nube de Windows Azure, Microsoft proporcionará
cuentas de prueba específicas para este laboratorio.

Más
información y Registro >>>

Parches y las versiones asociadas para Sharepoint 2007

Hoy he descubierto lo importante que es mantener la misma versión de Sharepoint tanto en el área de desarrollo como en los distintos entornos (Sobre todo si necesitas hacer un restore de un lugar a otro :P). Por ello, adjunto un link donde aparecen los parches cumulativos y las versiones relacionadas con cada uno de ellos hasta Febrero del 2010.

Sharepoint Versions – Sharepoint 2007 Administration Wiki

Espero que sea de utilidad.

¡Saludos!

Crear un documento Excel con Open XML

¿Cuántas veces hemos necesitado exportar los datos desde una aplicación a un documento Excel? Este es uno de los retos de ayer y de hoy 🙂
Si bien las opciones son varias y, como no, algunas mejores que otras, he optado por trabajar esta vez con Open XML. Este estándar está basado en archivos XML comprimidos en un ZIP (docx, xlsx, pptx). En este post me centraré en las hojas de cálculo aunque también es posible la creación de documentos Word, presentaciones y charts.

DESCARGAS NECESARIAS

Para poder trabajar con Open XML y Visual Studio, necesitamos descargar 
Open XML SDK 2.0 for Microsoft Office.
Con este SDK tendremos la capacidad de definir una serie de esquemas XML para la representación de hojas de cálculo, charts, presentaciones y documentos word bajo el estándar ECMA 376 y la aprobación ISO/IEC 29500. Microsoft Office Word 2007/2010, Excel 2007/2010 y PowerPoint 2007/2010 usan Open XML como formato por defecto para sus archivos.

CREACIÓN DE UNA HOJA DE CÁLCULO

Lo primero que necesitamos para comenzar a trabajar con Open XML en Visual Studio es agregar las referencias a DocumentFormat.OpenXML y Windows.Base.

Una hoja de cálculo consta fundamentalmente de tres partes: Un workbook, las hojas y los datos almacenados en cada hoja. La estructura más simple de un documento excel sería algo parecido a esto:

<x:workbook xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<x:sheets>
<x:sheet xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" name="ReturnGisSheet" sheetId="1" r:id="rId1" />
</x:sheets>
</x:workbook>

El primer objetivo es crear el documento con los elementos mínimos para que el mismo sea un documento válido.

using System.IO;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace OpenXMLExcel.Models
{
public class OpenXml
{
public static byte[] CreateExcel()
{
var memoryStream = new MemoryStream();
using (var excel = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook, true))
{
CreateParts(excel);
}

return memoryStream.ToArray();
}

public static void CreateParts(SpreadsheetDocument excel)
{
//workbook area
var workbookPart = excel.AddWorkbookPart();
//workbook content
CreateWorkbookPartContent(workbookPart);

//worksheet area
var worksheetPart = workbookPart.AddNewPart<WorksheetPart>("rId1");
GenerateWorksheetContent(worksheetPart);
}

private static void CreateWorkbookPartContent(WorkbookPart workbookPart)
{
var workbook = new Workbook();

//Workbook sheets
var sheets = new Sheets();
var sheet = new Sheet { Name = "ReturnGisSheet", SheetId = 1, Id = "rId1" };

sheets.Append(sheet);
workbook.Append(sheets);

workbookPart.Workbook = workbook;
}

private static void GenerateWorksheetContent(WorksheetPart worksheetPart)
{
var worksheet = new Worksheet();

var sheetData = new SheetData();

worksheet.Append(sheetData);

worksheetPart.Worksheet = worksheet;
}
}
}

Cada elemento de un archivo Open XML está alojado en un contenedor específicamente diseñado para ese tipo de elemento. De la misma manera, todos ellos deben estar enlazados entre sí ya que, de lo contrario, el documento no se abrirá (En el caso de Office 2003/2007) o bien nos solicitará su reparación, lo cual no es muy elegante.
Si arrancamos el proyecto web y solicitamos el archivo veremos que el nombre de la hoja es ReturnGis y, en el caso de Office 2010, esta aparecerá protegida.

AÑADIR DATOS A LA HOJA DE CÁLCULOS

La parte del documento encargada de contener los datos de una hoja se llama SheetData, la cual está alojada dentro de un WorkSheet y, a su vez, dentro del WorkSheetPart del documento. En este caso alimentaré la hoja de cálculo a través de la base de datos de ejemplo de Adventure Works 2008 R2.

using System;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace OpenXMLExcel.Models
{
public class OpenXml
{
public static byte[] CreateExcel()
{
var memoryStream = new MemoryStream();
using (var excel = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook, true))
{
CreateParts(excel);
}

return memoryStream.ToArray();
}

public static void CreateParts(SpreadsheetDocument excel)
{
//workbook area
var workbookPart = excel.AddWorkbookPart();
//workbook content
CreateWorkbookPartContent(workbookPart);

//worksheet area
var worksheetPart = workbookPart.AddNewPart<WorksheetPart>("rId1");
GenerateWorksheetContent(worksheetPart);
}

private static void CreateWorkbookPartContent(WorkbookPart workbookPart)
{
var workbook = new Workbook();

//Workbook sheets
var sheets = new Sheets();
var sheet = new Sheet { Name = "ReturnGisSheet", SheetId = 1, Id = "rId1" };

sheets.Append(sheet);
workbook.Append(sheets);

workbookPart.Workbook = workbook;
}

private static void GenerateWorksheetContent(WorksheetPart worksheetPart)
{
var worksheet = new Worksheet();

var sheetData = new SheetData();

var adventureWorksEntities = new AdventureWorksEntities();
var creditCardData = adventureWorksEntities.CreditCard.ToList();

for (var i = 0; i < creditCardData.Count; i++)
{
var rowNumber = (i + 1).ToString();
var row = new Row { RowIndex = UInt32.Parse(rowNumber) };
var creditCardId = new Cell { CellReference = "A" + rowNumber, CellValue = new CellValue(creditCardData[i].CreditCardID.ToString()) ,DataType = CellValues.Number};
row.Append(creditCardId);
var cardType = new Cell { CellReference = "B" + rowNumber, CellValue = new CellValue(creditCardData[i].CardType), DataType = CellValues.String };
row.Append(cardType);
var cardNumber = new Cell { CellReference = "C" + rowNumber, CellValue = new CellValue(creditCardData[i].CardNumber), DataType = CellValues.Number };
row.Append(cardNumber);
var expMonth = new Cell { CellReference = "D" + rowNumber, CellValue = new CellValue(creditCardData[i].ExpMonth.ToString()), DataType = CellValues.Number };
row.Append(expMonth);
var expYear = new Cell { CellReference = "E" + rowNumber, CellValue = new CellValue(creditCardData[i].ExpYear.ToString()), DataType = CellValues.Number };
row.Append(expYear);
sheetData.Append(row);
}
worksheet.Append(sheetData);

worksheetPart.Worksheet = worksheet;
}
}
}

El resultado sería el siguiente:

OPEN XML SDK 2.0 PRODUCTIVITY TOOL FOR MICROSOFT OFFICE

Existen infinidad de combinaciones a la hora de crear un documento, por lo que es bastante complicado aprender y localizar cada una de las propiedades y la forma de asociación entre los elementos que componen un Open XML. Por ello, cuando instalamos el SDK vimos que en la página de descarga aparecían dos elementos disponibles:

El primero de ellos se trata de una herramienta que nos permite ver de una forma jerárquica documentos ya creados, así como la posibilidad de obtener el código necesario para implementarlo en C#. Puede ser recomendable utilizar esta herramienta como guía pero resulta algo complejo de comprender ya que el código no está optimizado para su uso.

También es posible validar nuestros documentos para comprobar que la estructura es la correcta aunque no siempre es efectivo. El motivo es que dependiendo del error cometido en la creación del mismo la herramienta nos permitirá abrir el documento o no.

La gran ventaja de trabajar con este formato es que no existe la necesidad de tener instalado Office en el servidor y creamos nuestros documentos a través de una programación orientada a objetos.

Facilito el proyecto por si fuera de utilidad.

¡Saludos!