Muy buenas,
Aquí os dejo un enlace a una nueva colección de vídeos sobre azure:
http://www.msdev.com/Directory/SeriesDescription.aspx?CourseId=166
Saludos
Juanlu
Muy buenas,
Aquí os dejo un enlace a una nueva colección de vídeos sobre azure:
http://www.msdev.com/Directory/SeriesDescription.aspx?CourseId=166
Saludos
Juanlu
Azure va a dar mucho que hablar así, que espero estar por aquí algo más de lo habitual.
Ya en un post anterior comenté algún tema curioso sobre Azure, en este caso en concreto me gustaría dejar un resumen a grandes rasgos de manera que sirva de orientación para el comienzo con esta nueva gran “area de desarrollo”, principalmente para aquellos que aún no conocen poco o nada sobre Azure.
¿Qué es Azure? y, concretamente, ¿Qué es Windows Azure Platform?
Antes de dar ninguna explicación, me gustaría hacer mención sobre como equiparar a Azure con otros temas históricos de nuestra vida y de los que actualmente nos estamos beneficiando. Este simile aunque ya utilizado en más de una presentación creo que aclara bastante: “La electricidad, el gas, etc, los tenemos al alcance de nuestra mano con un servicio. ¿Por qué no hacer lo mismo con la infraestructura de ordenadores y pagar por un servicio prestado? De esta manera cada “uno” se dedica única y exclusivamente a su negocio”. Con el tiempo, hay una menor inversión y se produce un alto ROI.
Windows Azure es un entorno de “Cloud Computing” basado en Internet, es decir, un Sistema Operativo basado en Internet. Una plataforma para el desarrollo de aplicaciones .net en la “nube”, todo ello apoyado en data centers repartidos por todo el mundo.
Una imagen muy buena que define o da respuesta a esta pregunta es la siguiente. ¡ Creo que hay poco más que contar para una breve respuesta!
Esta plataforma esta formada por:
Todo ello con algunas restricciones y algunas diferencias que ya intentaré ir contando poco a poco.
Adicionalmente, cuando comencemos a estudiar y a intentar aprender Azure, encontraremos muchos acronimos que es conveniente tener presente desde el principio y que yo creo que pueden acortar dicho tiempo:
Azure se identifica claramentecon algunos adjetivos; Elasticidad, flexibilidad y “On-Demand” (En el Cloud, se paga por lo que se usa). Pincipalmente lo definiría como “Self-Service”.
Una vez entendido que es Windows Azure Platform, he aquí un gráfico identificatio (sacado de uno de los correspondientes White Papers), aunque por el momento no entraremos en detalle:
Conviene conocer también que existe una API “REST” (tecnología basada en HTTP y URI), que es utilizada por Azure y que, aunque aparentemente es trasparente, su uso es posible de forma explicita incluso para otros lenguajes para el uso con componentes de la plataforma azure:
Adicionalmente y de cara a la seguirdad tendremos que entender algunos terminos que aunque ya exsten hace tiempo, se le comenzará a dar más uso en y con la nube;
A partir de ahora no tiene por que ir todo a la nube, cada cosa irá en su sitio, exisiten aplicaciones idóneas para la nube mientras que otras no:
Idóneas:
No idóneas:
Adicionalmente agradecer anuestro compañero de Geeks Ibon Landa, su recapitulación sobre el inicio con Windows Azure Platform.
Hasta aquí y en pocas palabras, un resumén o recapitulación y punto de partida hacia este gran y maravilloso mundo. En los siguientes post directo al grano con VS 2010 y Windows Azure Cloud Services.
Saludos desde nube
Juanlu
Muy buenas a todos,
Windows Azure está ya aquí rondando como ya sabéis y parece ser que no va a parar. Aunque aún estoy un poco “espeso” en la parte técnica a pesar de haber hecho algun que otro ejemplo y ser capaz de captar su potencia, por el momento os dejo algunos vídeos que os pueden dar una idea de lo que se mueve por “ahí fuera” alrededor de Azure, merece la pena echarles un vistazo: Videos sobre Windows Azure.
Algunas novedades:
Y, por otro frente tambien se aproxima “Windows Intune”
Azufresaludos
Juanlu
Muy buenas o no tan buenas si es que acabas de llegar de las vacaciones ! 🙁
En esta ocasión y continuando con el tema de alguno de mis posts anteriores sobre los Setups (.msí) quiero comentar un pequeño truco para generar .msi en 64bits de forma automática.
Si habéis trabajado en la generación de “.msi” de 64bits y haciendo uso de las “Custom Actions”, habéis podido observar que una vez generado este, si se intenta instalar en una máquina de 64bits (a pesar de haber sido generado en 64bits), se obtiene el siguiente error:
¿Por que ocurre esto si realmente hemos generado un .msi de 64bits y lo estamos instalando en una maquina de 64?
Para dar solución a este tema tendremos que hacer uso de la herramienta “Orca” (o de alguna otra similar), ya postee sobre ella en mis inicios (“ORCA” – Windows Installer Table Editor) y mira por donde hoy, vuelvo a hacerle mención, ¡algo bueno tendrá!. Pues bien, esta herramienta nos va a permitir modificar uno de los valores de nuestro .msi con objeto de evitar este error debibo, parece ser a un “bug”, y que llevan ya tiempo sin querer solucionar. Para ello:
Adicionalmente y con objeto de hacer esta labor de manera totalmente automática, seguiremos los siguientes pasos:
…Type classType = Type.GetTypeFromProgID(“WindowsInstaller.Installer“);
Object installerClassObject = Activator.CreateInstance(classType);
WindowsInstaller.Installer i = (WindowsInstaller.Installer)installerClassObject;
WindowsInstaller.Database db = i.OpenDatabase(MSIFileSpec, WindowsInstaller.MsiOpenDatabaseMode.msiOpenDatabaseModeTransact);
Console.WriteLine(“Running SQL Query for InstallUtil in the Binary MSI table“);
// NOTE: The ` is correct in the SQL statement below – it is not ” or ‘
WindowsInstaller.View v = db.OpenView(“SELECT `Name`,`Data` FROM `Binary` where `Binary`.`Name` = ‘InstallUtil’“);
v.Execute(null);
WindowsInstaller.Record Record = v.Fetch();
if (Record != null)
{
Console.WriteLine(“Updating the Binary Data for InstallUtil“);
Record.SetStream(2, InstallUtil64BitFileSpec);
v.Modify(WindowsInstaller.MsiViewModify.msiViewModifyUpdate, Record);
ChangesMade = true;
}
else
{
Console.WriteLine(“Error : InstallUtil not found in the Binary MSI Table“);
}
v.Close();
if (ChangesMade)
{
Console.WriteLine(“Commiting the changes to the database“);
db.Commit();
}….
Nota: Como se puede ver, lo que finalmente va a hacer nuestra aplicación de consola es exactamente lo mismo que hemos comentado anteriormente con nuestro amiga “Orca”.
Nota: Si se genera un .msi de 64bits desde un entorno de desarrollo de 64bits esto no llega a ocurrir.
Os dejo aquí (“elGuerre.InstallUtilEditor.zip”) la aplicación de consola para que podáis utilizarla directamente.
Descarga “Orca” desde aquí.
Saludos
Juanlu
Buenas,
He aquí, una anécdota del día a día:
Hoy estaba intentando hacer un “merge”, ¡la verdad, nada complicado, pero, cuanto más fácil parece, más “enrevesado” e incrompresible resulta! 😀
Después de no sé cuantos intentos, y de seguir diferentes caminos para intentar conseguirlo, nada de nada, los cambios se resisten.
Problema: Existen muchos cambios a llevar a cabo en el merge pero no se hace efectivo ninguno. Realizas comparaciones de ficheros y son distintos, pero nada, que el “merge” no reconoce los cambios.
Solución: Desde la línea de comandos de Visual Studio, ejecutar la siguiente instrucción:
tf merge /baseless “LocalPath-1” “LocalPath-2” /recursive
Y, después de la resolución de algún conflicto, “zasssss…” problema resuelto.
Referencia: “http://msdn.microsoft.com/en-us/library/bb668976.aspx”
Saludos @3Cantos
Juanlu
Muy buenas a tod@s,
Ya está lista la Release de lla Entlib 5.0 para ser descargada.
Todo, desde aquí (EntLib 5.0).
Saludos y a disfrutarla, 😉
Juanlu
Últimamente me he encontrado con dudas y preguntas que se plantean algunos compañeros sobre la compilación en 64bits. En ocasiones, me he encontrado cosas un poco “liososas” al respecto, pero, sinceramente, despues de hacer un pequeño ejemplo para chequearlo, veo que no parece tan complicado, o al menos eso creo yo.
Veamos ese ejemplo “chorras” pero que una vez más nos da la solución a la duda
Llegado este momento el proyecto compila y se ejecuta en 32 y 64 bits. Es en momento de ver como se comporta el proyecto de SETUP:
Entre las propieades del proyecto de setup tenemos la propiedad “TargetPlatform” que tendremos que cambiar según la compilación que queramos hacer; para 32 o para 64 bits.
Hasta aquí, el caso fácil y prácticamente todo automático, pero, siempre existen algunas excepciones o “complicaciones” a tener en cuenta:
Estos úiltimos puntos dependerán de la complejidad que tenga nuestro Setup. La cuestión es, complicarse cuanto menos, mejor. El principio KISS, siempre presente.
Saludos
Juanlu
Muy buenas de nuevo, (y nunca mejor dicho lo de “nuevo”).
Llevo ya un tiempo sin aparecer por aquí, y la verdad, es que desde entonces no han dejado de aparecer novedades. Me siento como un niño pequeño que quiere jugar con sus nuevos juguetitos y, de alguna manera “no le dejan”, en fin….. Ya os contaré algunas cosas poco a poco.
En un intento de retomar mi aparición por aqui, os muestro a continuación y un pequeño artículo sobre la generación de Setup personalizados que escribí hace poco. A ver si os sirve:
Hace ya un tiempo quería comentar la facilidad de .net para la generación de setup’s personalizados y sobre todo como encaminarlos a la distribución vía SCCM (el antiguo SMS) o incluso, como sustitución a la generación de diferentes ficheros de configuración para nuestros “famosos” y diferentes entornos; desarrollo, integración y producción.
Vamos a seguir detalladamente los pasos adecuados a partir de un sencillo ejemplo que consiste en un formulario Windows que utiliza un texto fijo recuperado del fichero de configuración y que podría ser cualquiera de nuestros proyectos actuales
1. Añadimos a la solución existente un proyecto de tipo “Setup and Deployment” con el nombre <NombreProyecto>Setup:
2. Añadimos un nuevo proyecto de tipo “Class library” y denominarlo por ejemplo, <NombreProyecto>CustomInstall:
3. Añadimos una nueva clase “CustomParameters.cs” o renombrar la clase “Class1.cs” generada por defecto con la siguiente información:
using System.Collections; using System.Configuration.Install; namespace DeployEn15MinCustomInstall { public class CustomParameters { private static System.Collections.IDictionary state = null; public static string PREFIJO_SALUDO = "PrefijoSaludo"; private string _prefijoSaludo; /// <summary> /// Constructor para los instalables sin parametros de entrada /// </summary> /// <param name="savedState"></param> public CustomParameters(IDictionary savedState) { state = savedState; } public string PrefijoSaludo { get { return _prefijoSaludo; } set { _prefijoSaludo = value; } } /// <summary> /// Recupera los parametros pasados al msi. /// </summary> /// <param name="installContext"></param> public void LoadContext(InstallContext installContext) { this.PrefijoSaludo = installContext.Parameters[PREFIJO_SALUDO]; } } }
Donde; la constante “PREFIJO_SALUDO”, el atributo y la propiedad “PrefijoSaludo” serán sustituidos por cuantos parámetros sean necesarios pasar al ”.msi” para la instalación.
4. Añadimos una nueva clase “ConfigManager” con objeto de manejar la sección de “AppSettings” del fichero de configuración de la aplicación y poder añadir así nuevos valores a las key’s ya existentes.
public class ConfigManager { #region Attributos private string _ConfigPath; private Configuration _Config; private AppSettingsSection _AppSettings; #endregion /// <summary> /// Inicializa una nueva instancia de la clase<see cref="ConfigUpdater"/>. /// </summary> /// <param name="configPath">The config path.</param> public ConfigManager(string configPath) { _ConfigPath = (configPath == null ? String.Empty : configPath); try { _Config = ConfigurationManager.OpenExeConfiguration(_ConfigPath); _AppSettings = _Config.AppSettings; } catch (Exception ex) { throw new ApplicationException( String.Format("Error adding new configuration parameters into: '{0}'.{1}{2}", _ConfigPath, ex.Message, ex.StackTrace)); } } /// <summary> /// Añade una nueva clave (keyName) a la sección "appSettings" /// del fichero de configuración con un valor (value). /// </summary> /// <param name="keyName">Nombre de la clave a añadir.</param> /// <param name="value">Valor a asignar a la nueva clave.</param> public void AddParam(string keyName, string value) { if (_AppSettings.Settings[keyName] == null) _AppSettings.Settings.Add(keyName, value); } /// <summary> /// Elimina del fichero de configuración una clave (keyName) de la sección "appSettings" /// del fichero de configuración. /// </summary> /// <param name="keyName">Nombre de la clave a eliminar..</param> public void RemoveParam(string keyName) { _AppSettings.Settings.Remove(keyName); } /// <summary> /// Modifica o añade una clave (keyName) de la sección "appSettings". /// </summary> /// <param name="keyName">Nombre de la clare a añadir o modificar.</param> /// <param name="value">Valor a asignar a la clave</param> public void SaveParam(string keyName, string value) { if (_AppSettings.Settings[keyName] != null) _AppSettings.Settings[keyName].Value = value; else AddParam(keyName, value); } /// <summary> /// Guarda el fichero de configuración con los cambios realizados /// en la sección "appSetting". /// </summary> public void Save() { if (!_AppSettings.ElementInformation.IsLocked) _Config.Save(); else throw new ApplicationException("Section was locked, could not update"); } }
5. Añadimos al proyecto “CustomIntall” un nuevo ítem de tipo “Installer Class” y lo denominamos por ejemplo “CustomActions.cs”.
El contenido de este fichero será:
using System; using System.Collections; using System.ComponentModel; using System.Configuration.Install; using System.Diagnostics; using System.IO; using System.Reflection; namespace DeployEn15MinCustomInstall { [RunInstaller(true)] public partial class CustomActions : Installer { private const string PAREMETER_NOT_SPECIFIED = "El parámetro de instalación '{0}' no ha sido especificado. La instalación será cancelada."; private CustomParameters _parameters = null; // Añadir al array todos los parámetros requeridos durante la instalación. // Dejarlo vacío sino hay parámetros requeridos. private ArrayList requiredParameters = new ArrayList { CustomParameters.PREFIJO_SALUDO }; public CustomActions() { InitializeComponent(); } public override void Install(System.Collections.IDictionary stateSaver) { #if DEBUG Debugger.Launch(); #endif base.Install(stateSaver); // Si la instalación es ejectuada previo paso de parámetros. if (this.Context != null && this.Context.Parameters.Count > 0) { _parameters = new CustomParameters(stateSaver); _parameters.LoadContext(this.Context); ConfigureFileConfig(); } } private void ConfigureFileConfig() { string assemblyPath = this.Context.Parameters["assemblyPath"]; string fileName = Path.GetFileNameWithoutExtension(assemblyPath).Replace("CustomInstall", ".exe"); string exeConfigPath = Path.Combine(Directory.GetParent(assemblyPath).FullName, fileName); ConfigManager config = new ConfigManager(exeConfigPath); this.UpdateAppSettings(config); // Si todo es correcto se realiza el commit del fichero de configuración. config.Save(); config = null; } private void UpdateAppSettings(ConfigManager config) { PropertyInfo[] props = _parameters.GetType().GetProperties(); foreach (PropertyInfo prop in props) { string propValue = prop.GetValue(_parameters, null) as string; if (!String.IsNullOrEmpty(propValue)) { config.SaveParam(prop.Name, propValue); } else { // Parámetro requerido no especificado if (requiredParameters.Contains(prop.Name)) { throw new InstallException( String.Format(PAREMETER_NOT_SPECIFIED, prop.Name)); } } } } } } Las siguientes instrucciones
Las siguientes instrucciones van a permitir realizar una parada en tiempo de depuración con objeto de facilitar dicha labor. Esta instrucción tendrá más sentido cuando el ejecutable no se inicie directamente desde el Visual Studio.
#if DEBUG
Debugger.Launch();
#endif
6. Añadimos al proyecto de Setup dos items del tipo, “Primary Output”;
7. Finalizado el paso anterior, nuestra solución tendrá la siguiente apariencia además de proyecto de Test correspondiente (como en cualquier proyecto debemos tener siempre):
8. A continuación seleccionamos el proyecto “DeployEn15MinSetup” y hacemos click en el icono de “Custom Actions”.
9. Sobre la carpeta “Install” de las Custom Actions, hamemos click derecho y seleccionamos del “Application Folder” el “Primary output” referente al “CustomInstall”.
10. Generamos un fichero de comandos “.bat” con la siguiente instrucción y lo ejecutamos en la misma carpeta en donde se encuentre el Setup:
msiexec /l* “DeployEn15Min.log” /i DeployEn15MinSetup.msi TARGETDIR=”C:Test” allUsers=[ALLUSERS] PREFIJOSALUDO=”Deploy en 15 minutos v1.1″
Ahora, el ejecutable recibe los parámetros pasados en el comando. Los que se muestran durante la instalación son parámetros estándares, sin embargo, si después de la instalación comprobamos el fichero de configuración resultante, veremos como el valor de la key “PrefijoSaludo” del “appSettings”, ha cambiado por el nuevo valor.
Es en este punto, donde cobra fuerza la instrucción, “Debugger.Launch();” antes comentada.
Para conseguir la modificación de todos nuestros parámetros de configuración durante la instalación, tendremos que añadir valores a la propiedad “CustomActionData” del Custom Action “Install” tal y como se indica en la siguiente figura para nuestro parámetro “PrefijoSaludo”:
Se añadirán tantos valores como parámetros sean susceptibles de recuperar en tiempo de instalación.
Los “custom actions”; “Commit”, “Rollback” y “Uninstall”, serán implementados de la misma manera siempre y cuando en nuestra clase DeployEn15MinCustomInstall.CustomInstall.cs sobrescribamos los métodos correspondientes. Adicionalmente podrán sobrescribirse otros métodos que ocurren antes o después de estas acciones, con lo que tendremos mayor control sobre cualquier “cosa” que queramos realizar durante y después de la instalación.
El comando “msiexec” recibe un parámetro /l* que permite indicar un fichero de log en el que se registrarán todos pasos generados durante la instalación. Su objetivo, detectar cualquier posible error durante dicho proceso.
Nota: Con objeto de mejorar la instalación de prerrequisitos, actualizaciones, parches etc. de nuestra aplicación, podemos utilizar un “.vbs” (Visual Basic Script) en lugar de un “.bat”, permitiendo de esta manera mayor control; acceso al registro de Windows, etc. El objetivo de esto es permitir a los administradores de sistemas las modificaciones adecuadas según las necesidades concretas de la distribución. Un ejemplo claro podría ser, comprobar una clave del registro de Windows para verificar la existencia de otro programa o prerrequisito, de una versión anterior, etc.
Un saludo desde mi “nueva casa”
Juanlu, El Guerre
AND
Hace unos días, tuve la necesidad de formatear (a Windows Vista, aunque para Windows Server 2008 el caso hubiese sido el mismo) de nuevo el equipo, ¡cosa casi habitual!. Después de otros varios días trabajando con el, y tras haber instalado Visual Studio 2008 entre otras cosas, :-D, me disponía a crear un proyecto ASP.NET con objeto de realizar unas pruebas, pero de repente, me encuentro con “esto”, no es que sea un error, pero si me parece curioso, o ¡al menos es la primera vez que lo veo!.
Pues bien, si intentas publicar un proyecto ASP.NET en un IIS7 (local en mi caso) en donde NO se encuentre instalada la caractarística “IIS6 Metabase and II6 Configuration Compatibility” de II6, resulta imposible publicar, curioso como digo, pero, si estoy con II7,¿no debería evitar esta compatibilidad y trabajar directamente con IIS7?, 😀
Aquí os dejo los pasos que seguí:
A continuación continué con las indicaciones de la instalación de esta característica, marcando sólo la casita “IIS Metabase and II6 configuration compatibility” y tras un reinicio y una actualización de Window Vista…. ¡pues sí, finalmente funcionó!
Tampoco soy el único con este caso o similar; Visual Studio 2008 and IIS 7.
Para más detalle, aquí os dejo un enlace bastante interesante sobre temas de deploy con II7: Using Visual Studio 2008 with IIS 7.0
Buuueno, poco para aprender, pero algo más a tener en cuenta, 😉
Saludos @home
Juanlu
Durante la semana pasada he estado realizando una pequeña POC para el acceso a OWA (Outloook Web Access) via OwaAuth.dll y creo que, en cierto modo, estoy en la necesidad de que no pase al olvido, (si Juan, por si acaso, jejeje…).
¿Que es eso de OwaAuth.dll?
Se trata de la ISAPI de Exchange para el Logon en Owa. Esta es quizás una gran desconocida para muchos y aunque pasa desapercibida puede ser que en alguna ocasión sea necesario tener que hacer uso de ella para un propósito “un tanto distinto” :-D.
Owa necesita un “sessionid” y un “cadata” para poder acceder y obtener información de cada una de sus páginas, pues bien, owaauth.dll es la encargada de obtener estos dos datos en una primera petición http de tipo POST, y, a partir de aquí, haciendo uso de estos en las peticiones sucesivas cada página web de Owa retornará el código HTML sin ningún tipo de preámbulo.
Paso a paso:
public string GetPostData(Uri uri)
{
// Setting data to create a request body.
Dictionary<string, string> props = new Dictionary<string, string>();
props.Add("destination",
uri.Scheme + Uri.SchemeDelimiter + HttpUtility.UrlEncode(uri.Host + "/exchange/" + _user + "/"));
props.Add("flags", "4"); /* 0 */
props.Add("forcedownlevel", "0");
props.Add("trusted", "4"); /* 0 */
props.Add("username", HttpUtility.UrlEncode(String.Format(@"{0}{1}", _domain, _user)));
props.Add("password", HttpUtility.UrlEncode(_password));
props.Add("submitCreds", "Log+On");
props.Add("isUtf8", "1");
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = String.Empty;
foreach (string key in props.Keys)
{
string pValue = null;
props.TryGetValue(key, out pValue);
postData += string.Format("{0}={1}&", key, pValue);
}
if (props.Keys.Count > 0)
postData = postData.Substring(0, postData.Length - 1);
return postData;
}
public CookieCollection Authenticate(string url)
{
string postData = GetPostData(new Uri(url));
// Get Response - Cookie
var response = HttpManager.SendRequest(
url, postData, null,
RequestMethod.POST, _user, _password, _domain,
"application/x-www-form-urlencoded");
if (response.Cookies.Count < 2)
return null;
return response.Cookies;
}
El método “SendRequest” es el encargado de realizar:
public static HttpWebResponse SendRequest(string url, string postData,
CookieCollection cookieCol, RequestMethod requestMethod,
string user, string pwd, string domain, string contentType)
{
ServicePointManager.ServerCertificateValidationCallback = delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true;
};
Uri uri = new Uri(url);
var request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = requestMethod.ToString();
request.CookieContainer = new CookieContainer();
request.ContentType = contentType;
request.AllowAutoRedirect = false;
// request.ServicePoint.Expect100Continue = false;
request.KeepAlive = true;
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1;" +
".NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)";
request.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,"
+ "application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*";
byte[] body = null;
if (requestMethod == RequestMethod.POST)
{
// BODY
body = Encoding.ASCII.GetBytes(postData);
request.ContentLength = body.Length;
}
// Cookies
if (cookieCol != null)
{
foreach (Cookie c in cookieCol)
// request.Headers.Add(c.Name, c.Value);
request.CookieContainer.Add(c);
}
// Security
CredentialCache credentialCache = new System.Net.CredentialCache();
credentialCache.Add(uri,
"Basic", /* Basic */
new System.Net.NetworkCredential(user, pwd, domain)
);
request.Credentials = credentialCache;
if (requestMethod == RequestMethod.POST)
{
// Response
var stream = request.GetRequestStream();
stream.Write(body, 0, body.Length);
stream.Close();
}
return (HttpWebResponse)request.GetResponse();
}
Esto ha sido todo por esta vez, espero como siempre, haber dado un pasito más.
Saludos @SundayHome
Juanlu