Después de probar varias aplicaciones disponibles actualmente en el marketplace de Windows Phone 7, me gustaría compartir aquellas que creo que son imprescindibles en nuestros dispositivos

Después de probar varias aplicaciones disponibles actualmente en el marketplace de Windows Phone 7, me gustaría compartir aquellas que creo que son imprescindibles en nuestros dispositivos
Una de las preguntas que me llegan a través del formulario de contacto es qué es lo necesario para subir una aplicación que ya tenemos implementada, en este caso con Web Forms, a la plataforma Windows Azure. En realidad, un proyecto para la nube contiene todos aquellos proyectos que componen nuestra aplicación y además un proyecto relacionado con la plataforma en el cual se define qué rol tiene el resto de proyectos de nuestra solución.
Una de las cosas que más me gustan de la plataforma Windows Azure es que nuestras soluciones se convierten en un paquete capaz de acondicionar su entorno de vida Todos aquellos pasos previos, como la instalación de librerías, configuración de puertos en el firewall, etcétera, podemos definirlos gracias a la sección Startup del archivo ServiceDefinition.csdef.
¡Perfecto! Ya tenemos nuestra solución con una aplicación ASP.NET MVC 3 y el ejecutable que instalará las librerías necesarias para que el sitio web funcione en Windows Azure. Como último paso, debemos definir el apartado Startup y definir una tarea donde indiquemos que es necesario instalar ASP.NET MVC 3 antes de que la aplicación esté disponible para los usuarios. Para ello, abrimos el archivo ServiceDefinition.csdef donde añadimos la sección Startup con los siguientes valores:
<?xml version="1.0" encoding="utf-8"?> <ServiceDefinition name="Startups" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"> <WebRole name="MyASPNETMVC3"> <Startup > <Task commandLine ="installaspnetmvc3.cmd" executionContext="elevated" taskType="simple"></Task> </Startup> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="80" /> </Endpoints> <Imports> <Import moduleName="Diagnostics" /> </Imports> </WebRole> </ServiceDefinition>
E:approotfilesAspNetMVC3ToolsUpdateSetup.exe /q
Si desplegamos nuestra aplicación en Windows Azure, podremos disfrutar de ASP.NET MVC 3 gracias a Startup section
public override void Run() { this.SyncForever(TimeSpan.FromSeconds(1)); }
Fuente | Descripción | Destino |
---|---|---|
Windows Azure Logs | En estos logs se guardan todas aquellas trazas registradas a través de la clase System.Diagnostics.Trace. | Tabla |
Performance Counters | Se almacenan los contadores de rendimiento configurados previamente. | Tabla |
Windows Azure Diagnostic Infrastructure Logs | Son todos aquellos registros relacionados con el servicio de Windows Azure. | Tabla |
Windows Event Logs | Podemos añadir tanto fuentes predeterminadas de Windows, como System o Application, como aquellas dadas de alta programáticamente. | Tabla |
Crash Dumps | Volcados de memoria de nuestra aplicación. | Blob |
Custom Error Logs | Esta opción nos permite dar de alta nuestros propios logs dentro del proceso de transferencia de Windows Azure Diagnostics para poder recuperar los mismos a través del storage. | Blob |
IIS 7.0 Logs | Podemos recuperar toda la información generada de forma automática relacionada con IIS | Blob |
Failed Request Logs | Almacena información sobre aquellas peticiones fallidas de IIS | Blob |
//We need to get default initial configuration var config = DiagnosticMonitor.GetDefaultInitialConfiguration();
Trace.WriteLine("WorkerRole_Diag entry point called", "Information");
//Windows Azure Logs. Table: WADLogsTable config.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose; config.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(5);
//Performance counters. Table: WADPerformanceCountersTable config.PerformanceCounters.DataSources.Add( new PerformanceCounterConfiguration { CounterSpecifier = @"Processor(*)*", SampleRate = TimeSpan.FromSeconds(1) } ); config.PerformanceCounters.DataSources.Add( new PerformanceCounterConfiguration { CounterSpecifier = @"Memory*", SampleRate = TimeSpan.FromSeconds(1) } ); config.PerformanceCounters.ScheduledTransferPeriod = TimeSpan.FromMinutes(5);
//Windows Azure Diagnostic Infrastructure Logs. Table: WADDiagnosticInfrastructureLogsTable config.DiagnosticInfrastructureLogs.ScheduledTransferLogLevelFilter = LogLevel.Verbose; config.DiagnosticInfrastructureLogs.ScheduledTransferPeriod = TimeSpan.FromMinutes(5);
//Windows Event Logs. Table: WADWindowsEventLogsTable config.WindowsEventLog.ScheduledTransferLogLevelFilter = LogLevel.Verbose; config.WindowsEventLog.DataSources.Add("Application!*"); config.WindowsEventLog.DataSources.Add("System!*"); config.WindowsEventLog.ScheduledTransferPeriod = TimeSpan.FromMinutes(5);
//Crash Dumps. Blob. Container: wad-crash-dumps CrashDumps.EnableCollection(true); config.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
//Custom Error Logs var localResource = RoleEnvironment.GetLocalResource("CustomErrorStorage"); var directoryConfiguration = new DirectoryConfiguration { Container = "wad-mycustom-log-container", DirectoryQuotaInMB = localResource.MaximumSizeInMegabytes, Path = localResource.RootPath }; config.Directories.DataSources.Add(directoryConfiguration); config.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
config.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(5);
<system.webServer> <!-- Blob. Container: wad-iis-failedreqlogfiles --> <tracing> <traceFailedRequests> <add path="*"> <traceAreas> <add provider="ASP" verbosity="Verbose" /> <add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" /> <add provider="ISAPI Extension" verbosity="Verbose" /> <add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module" verbosity="Verbose" /> </traceAreas> <failureDefinitions timeTaken="00:00:15" statusCodes="400-599" /> </add> </traceFailedRequests> </tracing> <modules runAllManagedModulesForAllRequests="true"/> </system.webServer>
config.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(5);
//Start with new configuration DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", config);
a través de SQL Server 2008 R2 Management Studio:
Create DATABASE mybbdd (EDITION='web',MAXSIZE=1GB)
ALTER DATABASE mybbdd MODIFY (EDITION='business', MAXSIZE=50GB)
ALTER DATABASE mybbdd MODIFY (EDITION='web', MAXSIZE=5GB)
ALTER DATABASE mybbdd MODIFY (MAXSIZE=20GB)
Un repositorio para recuperar los valores:
using System.Linq; namespace WebGridAsync.Models { public class StuffRepository { private readonly StuffEntities _model; public StuffRepository() { _model = new StuffEntities(); } public FileViewModel GetFiles(int page = 1) { var fileViewModel = new FileViewModel(); var files = _model.Files.ToList(); fileViewModel.FilesPerPages = 5; fileViewModel.NumberOfFiles = _model.Files.Count(); fileViewModel.Files = files.Skip((page - 1) * fileViewModel.FilesPerPages) .Take(fileViewModel.FilesPerPages); return fileViewModel; } public void SaveChanges() { _model.SaveChanges(); } } }
using System.Web.Mvc; using WebGridAsync.Models; namespace WebGridAsync.Controllers { public class HomeController : Controller { private readonly StuffRepository _stuffRepository; public HomeController() { _stuffRepository = new StuffRepository(); } public ActionResult Index(int page = 1) { return View(GetFilesWithUpdatedStatus()); } public FileViewModel GetFilesWithUpdatedStatus() { var fileViewModel = _stuffRepository.GetFiles(); foreach (var myFile in fileViewModel.Files) { switch (myFile.Status) { case "Pending": myFile.Status = "Processing"; break; case "Processing": myFile.Status = "Waiting"; break; case "Waiting": myFile.Status = "More waiting..."; break; case "More waiting...": myFile.Status = "Completed"; break; default: myFile.Status = "Pending"; break; } } _stuffRepository.SaveChanges(); return fileViewModel; } } }
@model WebGridAsync.Models.FileViewModel @{ ViewBag.Title = "Async WebGrid"; WebGrid grid = new WebGrid(rowsPerPage: Model.FilesPerPages, canSort: false); grid.Bind(Model.Files, rowCount: Model.NumberOfFiles); } <h2>@ViewBag.Message</h2> <div id="myWebGrid"> @grid.GetHtml(columns: new[]{ grid.Column("Name"), grid.Column("Date"), grid.Column("Status") }) </div>
<script language="javascript" type="text/javascript"> $(document).ready(function () { $.ajaxSetup({ cache: false }); setTimeout(reloadAsync, 5000); }); function reloadAsync() { $("#myWebGrid").load("/Home/Index #myWebGrid", function (response, status, xhr) { if (status == "error") { var msg = "Sorry but there was an error: "; $("#error").html(msg + xhr.status + " " + xhr.statusText); } else { setTimeout(reloadAsync, 5000); } }); } </script>
Cuando trabajamos detrás de un proxy podemos experimentar algunos problemas con ciertas aplicaciones. Incluso Visual Studio puede verse perjudicado por ello
Para solucionarlo, podemos modificar el archivo de configuración de Visual Studio para especificar el uso del proxy por defecto.
<defaultProxy useDefaultCredentials="true" enabled="true"> <proxy usesystemdefault="True" /> </defaultProxy>
De tal manera que el archivo de configuración quede con el siguiente aspecto: