posts - 315, comments - 273, trackbacks - 15

My Links

News

View Pietro Libro's profile on LinkedIn

DomusDotNet
   DomusDotNet

Pietro Libro

Tag Cloud

Article Categories

Archives

Post Categories

Blogs amici

Links

domenica 12 marzo 2017

Screen Resolution Debian (guest) su Hyper-V

Se si ha una macchina virtuale Debian come guest su Hyper-V e si ha la necessità di cambiare la risoluzione dello schermo, dopo averle provate tutte, provare anche questa Smile.

Come riportato su uglygizmo.blogspot.ch i passi da seguire sono veramente pochi, per convenienza li riporto qui:

  1. Edit the grub configuration file, for example:  sudo vi /etc/default/grub
  2. Find the line starting with GRUB_CMDLINE_LINUX_DEFAULT, and add "video=hyperv_fb:1680x1050" (or your custom resolution) in between the quotes. For example: GRUB_CMDLINE_LINUX_DEFAULT="quiet splash video=hyperv_fb:1680x1050"
  3. Save and exit 
  4. Run sudo update-grub
  5. Restart your computer

Nel mio caso finalmente sono riuscito ad impostare la risoluzione desiderata.

posted @ domenica 12 marzo 2017 11.02 | Feedback (0) | Filed Under [ Varie ed eventuali Virtual Machine ]

giovedì 9 marzo 2017

Add REST Api Client: Unable to resolve dependency…

Se avete intenzione di utilizzare lo strumento “Add REST Api Client” di Visual Studio (2015/2017 poco importa):

image

e vi “scontrate” con l’errore “Unable to resolve dependency ‘Microsoft.NETCore.Platform ….’

image

Un “workaround” veloce è installare il pacchetto “Microsoft.Rest.ClientRuntime”:

Install-Package Microsoft.Rest.ClientRuntime

Attendere il tempo necessario (scarica un po’ di pacchetti di contorno Smile) e poi riprovare l’aggiunta del client REST, questa volta con successo:

image

posted @ giovedì 9 marzo 2017 15.53 | Feedback (0) | Filed Under [ Visual Studio 2015 .NET Core ]

domenica 30 ottobre 2016

.NET Core & Linux

E’ praticamente una vita che non scrivo piu’ su questo blog per diversi motivi (non penso se ne siano accorti in molti Open-mouthed smile), ma alla fine (meglio tardi che mai) eccomi con un nuovo post, con un nuovo progetto in testa: portare avanti una guida sullo sviluppo di .NET Core & affini in ambiente Linux. Una prima versione del documento è scaricabile qui: .NET Core & ASP.NET Core in ambiente Linux : si parte dall’installazione di .NET Core in OpenSuse 13.2 fino alla pubblicazione di una semplice Web API su Azure tramite Git, ovviamente usando VS Code come IDE e “molta riga di comando”. Gli argomenti da sviluppare (EF Core, IoT, OpenID etc …) sono ovviamente ancora tanti (compresi gli aggiornamenti rilasciati in questi giorni), vedremo se alla fine del progetto ne uscirà un buon documento. Al prossimo aggiornamento Smile

posted @ domenica 30 ottobre 2016 8.24 | Feedback (1) | Filed Under [ C# Virtual Machine .NET Core ]

mercoledì 22 luglio 2015

Documentazione EF 7 (Beta 5)

Documentazione "Work in Progress" della prossima release di Entity Framework : http://ef.readthedocs.org/en/latest/

posted @ mercoledì 22 luglio 2015 8.07 | Feedback (0) | Filed Under [ Visual Basic .Net C# LINQ SQL ASP.NET Tools Entity Framework 7 Visual Studio 2015 ]

domenica 30 novembre 2014

ASP.NET 5 e AzureTableStorage

Riprendiamo l’esempio del post precedente per testare l’integrazione tra EF7 e lo storage di Azure. Apriamo NuGet ed installiamo il package “EntityFramework.AzureTableStorage” (sempre in beta):

image

Modifichiamo il codice della classe ItemDB in questo modo:

1 public class ItemDB : DbContext 2 { 3 public DbSet<Item> Items { get; set; } 4 5 protected override void OnConfiguring(DbContextOptions options) 6 { 7 options.UseAzureTableStorage("[Storage_Name]", "[Secret_Key"); 8 } 9 10 protected override void OnModelCreating(ModelBuilder modelBuilder) 11 { 12 modelBuilder.Entity<Item>().ForAzureTableStorage() 13 .PartitionAndRowKey(a => a.CategoryId, a => a.Id) 14 .Table("Items"); 15 } 16 }

Rispetto all’esempio precedente è stato rimosso il metodo di estensione UseSqlServer ed aggiunto un degli overload di UseAzureTableStorage che accetta in ingresso due parametri: accountName ed accountKey. Tramite l’override di OnModelCreating andiamo ad istruire il runtime sulle propietà della classe Item che rappresentato rispettivamente la PartitionKey e la RowKey del Table Storage su Azure. Modifichiamo il file Project.json commentando la voce aspnetcore50 nella sezione frameworks:

image

La classe Item modificata è la seguente:

1 public class Item 2 { 3 public int Id { get; set; } 4 public int CategoryId { get; set; } 5 public string Code { get; set; } 6 public string Description { get; set; } 7 }

Infine modifichiamo la classe Program.cs:

1 public void Main(string[] args) 2 { 3 using (ItemDB db = new ItemDB()) 4 { 5 int nextId = new Random().Next(100000); 6 7 db.Items.Add(new Item() 8 { 9 Id = nextId, 10 Code = "Item #" + nextId, 11 Description = "Description #" + nextId 12 }); 13 14 db.SaveChanges(); 15 } 16 17 using (ItemDB db = new ItemDB()) 18 { 19 foreach (Item item in db.Items) 20 { 21 Console.WriteLine("Item Id: {0}, Code: {1}, Description : {2}", 22 item.Id, item.Code, item.Description); 23 } 24 } 25 26 Console.ReadLine(); 27 }

Proviamo quindi ad eseguire l’applicazione:

image

Ulteriore prova che tutto funzioni correttamente si puo’ avere utizzando l’”Azure Storage Explorer”:

image

posted @ domenica 30 novembre 2014 22.48 | Feedback (0) | Filed Under [ C# ASP.NET 5 Entity Framework 7 ]

ASP.NET 5 e Entity Framework 7 (beta)

Vediamo in questo post come iniziare a giocare con Entity Framework 7 “beta” (in “beta” solo per uniformità con in rilascio della preview di VS 2015, cosi come descritto in questo post). Partiamo con aprire VS 2015 e creare un progetto di tipo “ASP.NET 5 Console Application”:

image

Per utilizzare Entity Framework 7, apriamo il file Project.json e aggiungiamo nella sezione dependencies le tre dipendenze seguenti:

  1. "EntityFramework": "7.0.0-beta1"
  2. "EntityFramework.Commands" : "7.0.0-beta1"
  3. "EntityFramework.SqlServer": "7.0.0-beta1"

Le dipendenze 1 e 3 ci servono per integrare EF nel nostro progetto ed “informare” che andremo a lavorare utilizzando EF per SQL Server (dato che nella nuova versione, il provider di EF puo’ essere utilzzato nativamente per interagire con SqlServer, SqlLite, AzureTableStorage e InMemory, quindi non solo database relazionali), la dipendenza 3 ci serve per utilizzare i comandi di DB Migration all’interno del nostro progetto.

Sempre in Project.json aggiungiamo la sezione Commands con la relativa voce “EF”:

"commands": {
    "ef": "EntityFramework.Commands"
},

 

Cosi’ che alla fine delle modifiche il file Project.json sia simile a quanto illustrato nella figura seguente:

image


Aggiungiamo al progetto un file di tipo “ASP.NET Configuration file” (Config.json):

image

Il quale di Default si presenta in questo modo:

image

Nella sezione “Data\DefaultConnection” modifichiamo la voce ConnectionString editando la propietà Database oppure cambiando l’intera stringa di connessione, secondo di dove vogliamo ospitare il nostro database (Istanza di SQL Server Express piuttosto che LocalDB ad esempio). Tramite “NuGet Package Manager” (molto piu’ carino graficamente di quello precedente), aggiungiamo un riferimento al Package “Microsoft.Framework.ConfigurationModel.Json” :

image

Aggiungiamo al progetto il file Startup.cs:

image

E modifichiamolo come segue:

1 public class Startup 2 { 3 public static Microsoft.Framework.ConfigurationModel.IConfiguration Configuration { get; set; } 4 5 static Startup() 6 { 7 Configuration = new Microsoft.Framework.ConfigurationModel.Configuration() 8 .AddJsonFile("config.json").AddEnvironmentVariables(); 9 } 10 }

Aggiungiamo al progetto due nuovi classi C#, “Item” e “ItemDB”, dove “ItemDB” è la classe derivata da System.Data.Entity.DbContext ed “Item” il Data Model:

1 public class Item 2 { 3 public int Id { get; set; } 4 public string Code { get; set; } 5 public string Description { get; set; } 6 } 7 8 public class ItemDB : DbContext 9 { 10 public DbSet<Item> Items { get; set; } 11 12 protected override void OnConfiguring(DbContextOptions options) 13 { 14 options.UseSqlServer(Startup.Configuration.Get("Data:DefaultConnection:ConnectionString")); 15 } 16 }

Il nuovo metodo OnConfigure di cui abbiamo eseguito l’override ci permette di specificare quale Data Provider (nel nostro caso SqlServer) lavorerà con il nostro DbContext. UseSqlServer accetta come parametro  una stringa di connessione che recuperiamo dal file Config.json tramite la proprietà Configuration (Microsoft.Framework.ConfigurationModel.IConfiguration) presente nella classe Startup.cs.

Per utilizzare EF Migrations, non è ancora finita, in quanto è necessario installare e configurare KVM (K Version Manager), sul sito è presente una piccola guida all’installazione.

Apriamo un’istanza di Windows PowerShell (o Command Prompt secondo le preferenze) e ci spostiamo nella directory del nostro progetto, dopo digitiamo il comando “K ef migration add initial”:

image

Se tutto è stato eseguito correttamente, nel nostro progetto viene aggiunta la classica cartella “Migrations” con tutti i file necessari:

image

Applichiamo quindi il nostro “piano di migrazione” tramite il comando “migration apply”:

image

Ora possiamo testare che tutto l’Ambaradan (Smile) funzioni, modificando la classe Programs.cs in questo modo:

1 public void Main(string[] args) 2 { 3 ////Save data. 4 using (ItemDB db = new ItemDB()) 5 { 6 db.Items.Add(new Item() 7 { 8 Code = "Item #1", 9 Description = "Description #1" 10 }); 11 12 db.SaveChanges(); 13 } 14 15 ////Load data. 16 using (ItemDB db = new ItemDB()) 17 { 18 foreach (Item item in db.Items) 19 { 20 Console.WriteLine("Item Id: {0}, Code: {1}, Description : {2}", 21 item.Id, item.Code, item.Description); 22 } 23 } 24 25 Console.ReadLine(); 26 }

E poi avviando il tutto con un bel F5:

image

Sicuramente la versione 7 di EF è ancora “poco” matura per essere utiizzata in progetti reali, ma questo esempio vuole essere un punto di partenza per scoprire quali novità ci attendono Smile

posted @ domenica 30 novembre 2014 12.21 | Feedback (0) | Filed Under [ ASP.NET 5 Entity Framework 7 Visual Studio 2015 ]

domenica 23 novembre 2014

Asp.Net 5, MVC 6 e Web Api

E’ qualche mese che non scrivo nulla sul blog, ma gli studi, come la vita, sono andata avanti. Ora eccoci qui a fare qualche test con le nuove versioni delle ultime tecnologie\framework web del mondo Microsoft, che ci regala ogni giorno qualcosa di tecnlogicamente fantastico…alla faccia dei soliti criticoni Smile. Torniamo con i piedi per terra e proviamo ad utilizzare le Web Api in un progetto MVC 6 (attualmente in versione beta, ASP.NET 5 fonde i framework MCV e Web Api). Apriamo il nostro VS 2015 preview (scaricabile nella versione ultimate a questo indirizzo: ) e creiamo un nuovo progetto “ASP.NET Web Application”:

image

Poi selezioniamo il template ASP.NET 5 Empty:

image

Attendiamo qualche secondo che Visual Studio crei l’alberatura della soluzione con tutti i relativi file:

image

Notiamo due file in formato “.json”, global.json e project.json, che possiamo editare rispettivamente per i settings e per le references a livello globale (solution) o di singolo progetto. La classe Startup.cs ed in particolare il metodo Configure(…) definisce l’entry point della pipeline di ASP.NET, ed è qui che andremo ad aggiungere il codice necessario all’esecuzione dell’applicazione. Prima, apriamo il file project.json, e nella sezione dependencies aggiungiamo la riga seguente:

"Microsoft.AspNet.Mvc": "6.0.0-beta1"

Notare come l’editor sia completo di IntelliSense che ci permette di scegliere dinamicamente package e versione (tra quelle disponibili):

image

Inizializziamo MVC nella classe Startup.cs, aggiungendo il metodo ConfigureServices:

1 public void ConfigureServices(IServiceCollection services) 2 { 3 services.AddMvc(); 4 }

il quale aggiunge tutte le dipendenze di cui MVC 6 ha bisogno. Utilizziamo il metodo d’estensione UseMvc nel metodo Configure:

1 public void Configure(IApplicationBuilder app) 2 { 3 app.UseMvc(); 4 }

Aggiungiamo una classe ItemsController (“Web Api Controller Class”) nella classica cartella di progetto Controllers:

image

1 [Route("api/[controller]")] 2 public class ItemsController : Controller 3 { 4 // GET: api/values 5 [HttpGet] 6 public IEnumerable<Item> Get() 7 { 8 return new List<Item>( 9 new Item[]{ 10 new Item() { Code= "Item#1", Description= "Item_Description#1" }, 11 new Item() { Code = "Item2", Description = "Item_Description#2"} }); 12 } 13 }

Poi aggiungiamo la classe Item:

1 public class Item 2 { 3 public string Code { get; set; } 4 public string Description { get; set; } 5 }

Avviamo il progetto ed invochiamo via browser il servizio:

image

Il servizio dovrebbe restituire il seguente json :

1 [{"Code":"Item#1","Description":"Item_Description#1"} 2 ,{"Code":"Item2","Description":"Item_Description#2"}]

Notiamo come la classe ItemsController a differenza delle versioni precedenti, non derivi piu’ dalla classe ApiController, ma direttamente da Controller. Se proviamo ad utilizzare uno strumento come Fiddler per analizzare le request e le response delle nostre Api, possiamo scoprire qualcosa di interessante, se ad esempio, modifichiamo la nostra Web Api in modo da tornare null, con l’attuale versione di ASP.NET Web Api otterremmo:

image

Ovvero una response con status 200 e corpo del messaggio vuoto, con la versione MVC 6 invece:

image

Una response con status 204 (No Content), che logicamente parlando IMHO è piu’ corretta (la risposta è OK, ma il contenuto del body è vuoto). Ulteriori dettagli sui Formatters in MVC6 possono essere trovati in questo post di Filip W. Per ritornare ad avere un comportamento Old Style è sufficiente agire a livello di configurazione, in ConfigureServices:

1 public void ConfigureServices(IServiceCollection services) 2 { 3 services.AddMvc().Configure<MvcOptions>(o => o.OutputFormatters 4 .RemoveAll(f => f.Instance.GetType() == typeof(HttpNoContentOutputFormatter))); 5 }

Ovviamente di novità ci sono e tante, ma almeno sappiamo da dove iniziare Smile .

posted @ domenica 23 novembre 2014 9.17 | Feedback (0) | Filed Under [ ASP.NET Web Api ASP.NET 5 MVC 6 ]

venerdì 29 agosto 2014

JSON.Merge

Un’interessante novità introdotta con la versione 6.0 release 4 di Json.NET è la possibilità di eseguire il Merge (utilizzando 4 possibili “variazioni”) di oggetti JObject e Jarray. Un rapido esempio, tramite Web Api:

[HttpPost]        
public void JsonStringPost([FromBody]string value)
{
    JObject jCar = JObject.Parse(value);
    JObject jOptional = JObject.Parse(@"{Optionals :['Air Conditioned','Smoker'] }");

    jCar.Merge(jOptional, new JsonMergeSettings() { MergeArrayHandling = MergeArrayHandling.Union });

    string jsonFormat = jCar.ToString();
    Car mergedCar =  jCar.ToObject<Car>(); 
}

Dove l’Action “JsonStringPost” accetta una stringa tipo:

"{ 'Brand': 'Ferrari','Model': 'f450 Modena','Optionals': [] }"

Utilizzando, ad esempio il Composer di strumenti come Fiddler2 possiamo invocare il servizio:

image

Per ottenere una nuova istanza di Car con tutti gli Optionals:

image

Se il nostro servizio accetta direttamente un’istanza di oggetto invece di una stringa in formato JSON, il nostro codice cambia leggermente, come di seguito:

[HttpPost]
public void JsonObjectPost([FromBody] Car carByPost)
{
    JObject jCar = JObject.FromObject(carByPost);

    JObject jOptional = JObject.Parse(@"{Optionals :['Air Conditioned','Smoker'] }");
    jCar.Merge(jOptional, new JsonMergeSettings() { MergeArrayHandling = MergeArrayHandling.Union });

    string jsonFormat = jCar.ToString();
    Car mergedCar = jCar.ToObject();
}

Dove utilizziamo il metodo FromObject della classe JObject invece di Parse. Utilizzando Fiddler, passando come Body del messaggio la stringa (senza i doppi apici ad inizio e fine stringa)

{ 'Brand': 'Ferrari','Model': 'f450 Modena','Optionals': [] }

Otteniamo (ovviamente) lo stesso risultato dell’invocazione precedente. E’ possibile modificare il comportamento di “Merge” utilizzando l’enumerazione MergeArrayHandling. La classe Car (C#) è descritta nell’esempio, è la seguente:

public class Car
{
    public string Brand { get; set; }
    public string Model { get; set; }
    public string[] Optionals { get; set; }
}

La lista completa delle features aggiunte nel rilascio della versione 6.0 release 4 è disponibile qui.

posted @ venerdì 29 agosto 2014 12.30 | Feedback (0) | Filed Under [ Varie ed eventuali C# ASP.NET Tools .Net Framework 4.5 ASP.NET Web Api ]

giovedì 27 marzo 2014

EF 6.1 : What’s new (3)

Supporto a “.ToString()” e “String.Concat()”, un esempio:

var queryConcat = from c in db.Vehicles
            where string.Concat(c.EngineSize, c.HP).Equals("1600110")
            select c;

var queryToString = from c in db.Vehicles
            where  c.HP.ToString().Equals("110")
            select c;

 

Abbiamo due Query LINQ che filtrano i dati in base a condizioni su stringhe, la prima “tira fuori” tutti i veicoli dove la concatenazione dei valori delle proprietà “EngineSize” e “HP” è uguale a “1600110”, mentre la seconda esegue un filtro su di un valore intero convertio in stringa. Se proviamo ad eseguire il codice in un ambiente con EF 6.0 otteniamo un’eccezione a runtime in tutti e due i casi:

image

Con EF 6.1 le query sono eseguite correttamente:

image

Cosa succede dietro le quinte:

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [DomusDotNet].[Vehicles] AS [Extent1]
        WHERE N'1600110' = (CASE WHEN ([Extent1].[EngineSize] IS NULL) THEN N'' ELSE [Extent1].[EngineSize] END +  CAST( [Extent1].[HP] AS nvarchar(max)))
    )  AS [GroupBy1]

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [DomusDotNet].[Vehicles] AS [Extent1]
        WHERE N'110' =  CAST( [Extent1].[HP] AS nvarchar(max))
    )  AS [GroupBy1]

Da analizzare il funzionamento di “String.Concat(…)” con SQL Server 2012 per verificare la conversione in SQL con la funzione “nativa SQL” “Concat”.

posted @ giovedì 27 marzo 2014 9.04 | Feedback (0) | Filed Under [ C# LINQ SQL SQL Server .Net Framework 4.5 Entity Framework 6 Visual Studio 2013 ]

giovedì 20 marzo 2014

EF 6.1 : What’s new (2)

Altra feature introdotta, l’attributo “IndexAttribute” che ci permette di definire un indice su una o piu’ colonne. Ad esempio, per creare un indice (di nome “IX_FreeDailyKm”) sulla proprietà “FreeDailyKm” del nostro modello, scriviamo:

[Index("IX_FreeDailyKm_Clustered", IsUnique = false, IsClustered = false)]
public int FreeDailyKm { get; set; }

 

Mentre per creare un indice che insiste su due proprietà, è sufficiente utilizzare lo stesso nome come da esempio:

[Index("IX_Engine", 2)]
public string EngineSize { get; set; }

[Index("IX_Engine", 1)]
public int HP { get; set; }

 

Utilizzando EF migrations per aggiornare il database, avremmo:

CreateIndex("DomusDotNet.Vehicles", "FreeDailyKm", name: "IX_FreeDailyKm_Clustered");
CreateIndex("DomusDotNet.Vehicles", new[] { "HP", "EngineSize" }, name: "IX_Engine");

 

Quindi, a livello di database:

image

posted @ giovedì 20 marzo 2014 16.49 | Feedback (0) | Filed Under [ C# .Net Framework 4.5 Entity Framework 6 Visual Studio 2013 ]

EF 6.1 : What’s new (1)

Da qualche giorno è stata rilasciata in RTM la versione 6.1.0 di Entity Framework. Una delle novità piu’ interessanti è sicuramente la possibilità di utilizzare l’approcio  Code First partendo da un database esistente (potrebbe sembrare strano, ma se pensiamo ad un nuovo sviluppo potrebbe non esserlo). I “ferri” da utilizzare sono ovviamente  EF 6.0.1 e la nuova versione di EF Tools, “scaricabile” per VS 2012 e VS 2013 seguendo questo link.

Per un semplice test, apriamo VS 2013 (o 2012), magari creando un semplice progetto “Console” al quale aggiungiamo tramite NuGet i riferimenti a EF 6.0.1. Poi tasto destro sul progetto e “Add New Item”, e scegliamo “ADO.NET Entity Data model”:

image

Il testo di “Name” infuenzerà il nome della classe “DbContext” generata. Dalla scheramata successiva (“Entity Data Model Wizard”) scegliamo “Code First model from Database”:

image

Nella schermata successiva del Wizard verrà chiesta la connessione dati da utilizzare (eventualmente ne creiamo una nuova), nel mio caso, per i test ho utilizzato un DB di un evento “DomusDotNet”. L’ultimo passo è la scelta degli oggetti da “importare”:

image

Dopo aver premuto “Finish” e qualche secondo di pazienza, VS aggiungerà all’alberatura del progetto, tutte le classi necessarie, una “buildata” per verificare che sia tutto a posto , e qualche riga di codice per verificare l’estrapolazione dati :

using (CarRental db = new CarRental())
{
    System.Console.WriteLine("There are {0} cars.", db.Cars.Count());
    System.Console.ReadKey();
}

posted @ giovedì 20 marzo 2014 11.42 | Feedback (0) | Filed Under [ C# .Net Framework 4.5 Entity Framework 6 Visual Studio 2013 ]

lunedì 3 marzo 2014

Dynamic Data Provider per EF6 released

Sono stati rilasciati in RTM, ASP.NET Dynamic Data e EntityDataSource per EntityFrameowrk 6. Per provare la nuova versione di Dynamic Data è sufficiente creare un nuovo progetto di tipo “ASP.NET Dynamic Data Entities Web Application”, ed installare tramite NuGet il package Microsoft.AspNet.DynamicData.EFProvider:

image

Eventualmente forziamo la scrittura dei Template (“A” per sovrascrivere tutto):

image

Aggiungiamo in modalità Code First una semplice classe Book e relativo DbContext:

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Authors { get; set; }
    public int Pages { get; set; }
}

public class Db : DbContext
{
    public DbSet<Book> Books { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

 

Nel Global.asax registriamo il nostro DbContext:

DefaultModel.RegisterContext(
            new Microsoft.AspNet.DynamicData.ModelProviders.EFDataModelProvider(() => new Db()),
            new ContextConfiguration { ScaffoldAllTables = true });

 

F5, per vedere in azione il nostro Data Site:

image

Discorso simile per l’utilizzo dell’EntityDataSource control.

posted @ lunedì 3 marzo 2014 9.06 | Feedback (0) | Filed Under [ C# ASP.NET Tools .Net Framework 4.0 Code First Migrations .Net Framework 4.5 Entity Framework 6 Visual Studio 2013 ]

lunedì 17 febbraio 2014

Windows Azure WebJobs (parte 4)

Per automatizzare tramite script il processo di creazione di un WebJob utilizzando Windows Azure Power Shell (Windows PowerShell ISE), i principali comandi da utilizzare sono:

  • Add-AzureAccount, che ci permette di autenticarci utilizzando Active Azure Directory
  • Get-AzureWebsite, per avere una panoramica dei WebSites legati alla subscription con la quale siamo collegati
  • Get-AzureWebsiteJob, il quale ritorna le informazioni sul WebJob specificato dal paramentro Name 

image

  •  New-AzureWebsiteJob, il quale permette la creazione di un nuovo WebJob ed accetta in ingresso i seguenti parametri:
    • Name, il nome del WebSite di riferimento
    • JobName, il nome del WebJob
    • JobType, la modalità di esecuzione del WebJob come descritto nel primo post relativo a questa serie
    • JobFile, il percorso dell’archivio compresso contenente tutti i file necessari all’esecuzione del Job
  • Remove-AzureWebsiteJob, il quale rimuove il WebJob specificato ed necessita dei parametri: Name, JobName e JobType

Per eseguire “Start&Stop” del WebJob, possiamo utilizzare i comandi:

  • Start-AzureWebsiteJob, con parametri Name, JobName e JobType
  • Stop-AzureWebsiteJob, con parametri Name e JobName

Se i comandi sopracitati non dovessero essere presenti nel tool (I WebJob sono in Preview) è sufficiente aggiornare la documentazione della guida:

image

posted @ lunedì 17 febbraio 2014 9.02 | Feedback (1) | Filed Under [ C# .Net Framework 4.5 Visual Studio 2013 ]

martedì 11 febbraio 2014

Windows Azure WebJobs (parte 3)

Torniamo ancora sull’argomento “WebJobs” descrivendo brevemente le varie modalità di Triggering:

  • Alla creazione di un nuovo Blob
  • Alla ricezione di un nuovo Queue Message
  • Esplicatamente tramite l’invocazione della funzione Call

Nei post precedenti (parte 1 e parte 2) abbiamo visto come attivare il Trigger del “WebJob” alla creazione di un nuovo Blob all’interno di un container specifico semplicemente utilizzando l’attributo [BlobInput]. Con le stesse modalità é possibile eseguire il Binding di una funzione invocata dall’instanza di JobHost al ricevimento di un messaggio in un specifica coda (Queue) come da esempio:

public static void ProcessBobByQueueMessage([QueueInput(@"inputqueue")] string message,
    [BlobOutput(@"outputcontainer/resized_image.png")] Stream outputStream)
{

    if (!message.Equals("go"))
        return;

    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
        System.Configuration.ConfigurationManager.ConnectionStrings["AzureJobsData"]
        .ConnectionString);

    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
    CloudBlobContainer container = blobClient.GetContainerReference("inputcontainer");
    CloudBlob blob = container.GetBlobReference("TestPicture");

    Stream inputStream = new MemoryStream();

    blob.DownloadToStream(inputStream);

    ResizeImage(inputStream, outputStream);
}

 

La funzione “ProcessBobByQueueMessage” é invocata al momento che un messaggio contenente il testo “go” arriva nella coda denominata “inputqueue”, come nei casi precedenti, creiamo un nuovo Blob nel container “outputcontainer” con il nome di “resized_image.png”. Da notare che nel codice utilizziamo le clasi del namespace Microsoft.WindowsAzure.StorageClient per lavorare con le classi che rappresentano lo storage di Windows Azure. Per testare il tutto é sufficiente caricare il Job sul nostro Web Site di test o premere F5 e lavoare “in locale”. Tramite l’Azure Storage Explorer possiamo creare un nuovo messaggio con la dicitura “go” come da figura:

image

E nel container di output avremo:

image

Dal codice si evince come il nome del Blob di ouput (e di input) sia fissato, ma per un’applicazione reale questo non é un comportamento desiderabile, cosi’, sarebbe auspicabile avere un comportamento piu’ dinamico utilizzando (ad esempio) una classe “Custom” serializzata in JSON, contenente la definizione dei file (Blob) di Input ed Output e passata come messaggio testo alla coda, tradotto in codice:

 public static void ProcessBobByQueueCustomMessage([QueueInput(@"inputqueue")] ImageMessage message,
[BlobOutput(@"outputcontainer/{OutputName}")] Stream outputStream)
{
    CloudStorageAccount storageaccount = CloudStorageAccount.Parse(
       System.Configuration.ConfigurationManager.ConnectionStrings["AzureJobsData"]
       .ConnectionString);

    CloudBlobClient blobclient = storageaccount.CreateCloudBlobClient();
    CloudBlobContainer container = blobclient.GetContainerReference("inputcontainer");
    CloudBlob blob = container.GetBlobReference(message.InputName);

    Stream inputStream = new MemoryStream();

    blob.DownloadToStream(inputStream);

    ResizeImage(inputStream, outputStream);
}

 

Da notare l’utilizzo del placeHolder “{OutputName}” specificato nel percorso (BlobPath) ed accettato come argomento dall’attributo BlobPath, uguale alla proprietà omonima della classe ImageMessage, ed utilizzata per definire il nome del Blob di output in questo modo:

public class ImageMessage
{
    public string InputName { get; set; }
    public string OutputName { get; set; }
}

 

Per un giro di test è sufficiente creare un nuovo messagio con il testo seguente:

image

Ottenendo:

image

Interessante è l’utilizzo dell’attributo [NoAutomaticTrigger()] che indica all’istanza di “JobHost” di non far scattare un particolare metodo (magari per evitare che il job venga attivato quando non tutte le condizioni necessiaro sono presenti). Questo attributo non va d’accordo con l’attributo [QueueInput(…)] in quanto a runtime solleva un’eccezione con il messaggio seguente: “Can't have QueueInput and NoAutomaticTrigger on the same function.”.

Per invocare programmaticamente una funzione è sufficiente utilizzare il metodo Call() della classe JobHost:

host.Call(methodInfo);

 

Dove “methodInfo” puo’ essere facilmente calcolato tramite Reflection.

posted @ martedì 11 febbraio 2014 11.27 | Feedback (0) | Filed Under [ C# ASP.NET .Net Framework 4.5 ]

giovedì 6 febbraio 2014

Windows Azure WebJobs (parte 2)

Nella prima parte abbiamo visto come creare un’applicazione console ed utilizzarla per elaborare (ridimensionare) in modalità Continuously dei Blob contenenti immagini, caricati in un particolare container del nostro storage. L’applicazione non è stata fisicamente copiata su un Web Site di Azure, ma è stata eseguita “in locale” sfruttando gli endpoint allo storage. Per caricare il nostro processo su Web Site i passi da compiere sono pochi e semplici:

image

  • Aprire il Web Site e visualizzare la sezione “Configure”:

image

  • Nella sottosezione “connection strings”, aggiungiamo la stringa di connessione “AzureJobsRuntime”:

image

  • Visualizziamo la sezione “WebJobs”:

image

  • Prima di effettuare l’upload dell’eseguibile è necessario creare una cartella compressa contenente sia “.exe” che “.dll” necessari al corretto funzionamento dell’applicazione. E’ sufficiente creare un archivio “zip” partendo (ad esempio) dalla cartella Debug\Release del nostro progetto. A questo punto è sufficiente cliccare sul bottone “ADD”, assegnare un nome al nostro “WebJob”, specificare il percorso della cartella compressa ed infine la modalità di esecuzione:

image

  • Una volta caricato il file compresso, dovremmo avere una situazione simile alla seguente:

image

  • Il Job caricato è in stato “STOP”, per entrare in “RUNNING” è ncessario cliccare l’icona con la dicitura “START” in fondo alla pagina:

image

  • Per testare che tutto funzioni correttamente è sufficiente utilizzare il tool Azure Storage Explorer come visto nella prima parte.

Se avessimo optato per un’esecuzione On Demand del Job ci saremmo trovati in una situazione di questo tipo:

image

Dove per eseguire il processo si rende necessario cliccare l’icona con la dicitura “RUN ONCE”. Se si vuole invece provare la versione Scheduled è necessario attivare il servizio “Windows Azure Scheduler” tra quelli presenti in questa pagina: https://account.windowsazure.com/PreviewFeatures

posted @ giovedì 6 febbraio 2014 11.22 | Feedback (0) | Filed Under [ C# .Net Framework 4.5 Visual Studio 2013 ]

Powered by: