Inviare email tramite un SMTP con certificato self-signed

by Andrea Dottor 05 September 2012 23:14

Può capitare (in fase di sviluppo) di dover inviare delle mail ad un server SMTP che ha un certificato self-signed.
Se provate ad inviare una mail da codice vi ritroverete con una bella eccezzione a causa del fallimento della validazione del certificato.

Un possibile work-around è quello di forzare il check della validità dei certificati in modo da far ritornare sempre true.
Il codice necessario è il seguente:

ServicePointManager.ServerCertificateValidationCallback =
                                (sender, certificate, chain, sslPolicyErrors) => true;

NOTE: il codice in questione è valido ogni qualvolta vi troviate a dover bypassare degli errori dovuti ai certificati.
Per ovvi motivi di sicurezza, siate ben consci di utilizzare questo codice solamente durante le fasi di sviluppo, altrimenti tanto varrebbe evitare l’uso del certificato.

Ed ecco il codice completo da utilizzare, compreso di invio della mail

ServicePointManager.ServerCertificateValidationCallback =
                                (sender, certificate, chain, sslPolicyErrors) => true;

MailMessage mail = new MailMessage();
mail.To.Add(new MailAddress("mail del destinatario"));
mail.Subject = "Oggetto";
mail.Body = "Corpo della mail";
mail.From = new MailAddress("mail del mittente");

SmtpClient smtp = new SmtpClient("smtp.miaazienda.it");
smtp.Credentials = new NetworkCredential("user", "password", "dominio");
smtp.EnableSsl = true;

smtp.Send(mail);

Tags: ,

ASP .NET | .NET

Baroliere - L'app per vincere/barare ai giochi di parole

by Andrea Dottor 12 June 2012 00:30

La mia esperienza con Windows Phone non si è assolutamente fermata, ed infatti ecco che me ne sono uscito con un'applicazione dedicata a chi ha difficoltà a vincere ai giochi di parole come ad esempio scrubble, scarabeo, o simili.
Se vi serve un aiuto per battere un vostro amico o familiare a questi giochi, ecco l'app che fa per voi!

La potete trovare al seguente link:
http://www.windowsphone.com/it-IT/apps/6753e7e0-4de1-4d56-854f-fdedf980cc4d

Barare+parole=BAROLIERE
Vincere ai giochi di parole non è mai stato così facile.
Immetti le lettere che hai a disposizione e ti verranno visualizzate tutte le parole disponibili nel dizionario italiano.

Paroliere, scrubble, scarabeo sono solo alcuni dei giochi in cui quest'applicazione ti può facilitare la vita.

Sviluppare per Windows Phone è divertente ed immediato, e quest'app lo dimostra...

Una sera, giocando a scrubble online, mi sono ritrovato di fronte ad un file txt contenente tutte le parole presenti all'interno del dizionario Italiano, e subito mi è nata l'idea di utilizzarlo per realizzare un'applicazione Windows Phone. Ed allora eccomi, qualche sera davanti a Visual Studio e questo è il risultato.

SplashScreenImagemainPageinfoPage

L'app è disponibile a pagamento con 3 giorni di trial...più che sufficienti per capire il funzionamento di questa semplice applicazione.
Ho aggiornato il prezzo a 1,29€ che per barare mi sembrano il minimo Winking smile

Tags: , , ,

Tempo libero | .NET | Windows Phone

Libero professionista a tempo pieno

by Andrea 10 September 2011 04:05

logoEbbene si, da quasi un mese, sono libero professionista a tempo pieno. Una nuova sfida da affrontare.

Sono più di 3 anni che ho la partita iva, ma fino al mese scorso ho sempre lavorato come dipendete. Questo mi ha permesso di aver le spalle sempre coperte e riuscire al tempo stesso a confrontarmi con sempre nuove prove.
L’essere dipendete ha sicurametne molti vantaggi, ma al tempo stesso può essere (a volte) limitante. (per poter tenere un corso (come speaker) dovevo prendermi ferie…per clienti che mi richiedevano la presenza da loro, avevo principalmente solo il sabato…)

Ho scelto di fare un passo importante, di lanciarmi in una nuova sfida, e mettermi totalmente in gioco decidendo di intraprendere questa nuova strada.
Alcune persone mi hanno spinto in questa decisione, altre mi hanno fatto riflettere, specialmente a riguardo del periodo non proprio positivo, e ho tirato le somme.
Per me (e per mia moglie) questo era il momento giusto, ed ora non mi rimane altro che impegnarmi a pieno in questo nuovo obbiettivo e continuare a crederci fino in fondo.

Il tutto sembra esser iniziato proprio nel migliore dei modi Open-mouthed smile

Tags:

+1 | ASP .NET | Pensieri | Generale

Aggiornare un UpdatePanel da un differente UserControl

by andrea 11 March 2009 06:54

Quando si utilizza un UpdatePanel consiglio sempre di impostare la proprietà UpdateMode a Conditional e ChildrenAsTriggers a False, per avere il pieno controllo su ciò che accade, e far trafficare il minimo html possibile.

Ci sono condizioni però in qui questo non sembra possibile.
Uno di questi casi è quando il postback asincrono dovrebbe essere scatenato da un controllo contenuto all'interno di un'altro UserControl. La soluzione più semplice sarebbe stata quella di settare UpdateMode ad Always, ma questo causerebbe l'aggiornamento durante un qualsiasi postback asincrono.
Ma anche a questo caso esiste una soluzione, e la soluzione sono gli eventi.

UserControl 1
Controllo che contiene il pulsante che deve scatenare il PostBack asincrono.

Questo UserControl esporrà un evento Command, che servirà come trigger per indicare che è stato scatenato un evento in un controllo in esso contenuto (in questo caso un LinkButton).
Andiamo a gestire l'evento OnCommand del LInkButton, e al suo interno faremo rilanciare l'evento utilizzando il metodo RaiseBubbleEvent.

Gli UserControl possono contenere controlli che scatenano eventi. Il metdo RaiseBubbleEvent permette di rilanciare all'esterno questi eventi, permettendo di riassegnare il sender.

Si ha quindi la condizione che l'evento OnCommand scatenato dal LinkButton verrà visto come evento OnCommand (contenente le stesse informazioni) ma generato dallo UserControl.

   1: public event CommandEventHandler Command;
   2:  
   3:  
   4: protected void Button_Command(object sender, CommandEventArgs e)
   5: {
   6:     CommandEventHandler handler = this.Command;
   7:  
   8:     if (handler != null)
   9:         handler(this, e);
  10:  
  11:     base.RaiseBubbleEvent(this, e);
  12: }

UserControl 2
Controllo che contiene l'UpdatePanel da aggiornare con il PostBack asincrono.

Il controllo contiene un UpdatePanel che deve essere aggiornato dal PostBack asincrono scatenato dal controllo contenuto nel primo UserControl.

Quello che si può fare è esporre la collection del Triggers dell'UpdatePanel, in modo da poterli impostare da chi utilizza il controllo.

Creiamo una proprietà Triggers (di tipo UpdatePanelTriggerCollection) nello UserControl e gli facciamo ritornare la collezione di trigger dell'UpdatePanel.
Per poterla vedere nel design, aggiungiamo gli attributi DesignerSerializationVisibility e PersistenceMode.

DesignerSerializationVisibility permette di specificare la visibilità della proprietà a design-time.

PersistenceMode specifica come la proprietà viene inserita nello UserControl, se tramite attributo o come proprietà interna.
Esempio di Attribute è la proprietà ID="…", o runat="sever" , che vendono specificate come attributi del tag.
Esempio di InnerProperty sono i SelectedParameters, o i Triggers, che devono essere specificati in un elemento contenuto nel tag del controllo, e non come attributi.

   1: [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   2: [PersistenceMode(PersistenceMode.InnerProperty)]
   3: public UpdatePanelTriggerCollection Triggers
   4: {
   5:     get { return updPanel.Triggers; }
   6: }

La pagina

Inseriamo nella pagina i due UserControl. Come sarà possibile vedere, nel controllo DisplayData (UserControl 2) sarà visibile una proprietà Triggers che ci da la possibilità di inserire un trigger associato al controllo Filters (e che si aggancerà all'evento Command che noi abbiamo esposto).
In questo modo, al click del pulsante contenuto nel UserControl di ricerca, avremo l'aggiornamento asincrono dell'UpdatePanel contenuto nel UserControl DisplayData.

   1: <dtr:Filters ID="filters" runat="server" />
   2: <dtr:DisplayData ID="displayData" runat="server">
   3:   <Triggers>
   4:       <asp:AsyncPostBackTrigger ControlID="filters" EventName="Command" />
   5:   </Triggers>
   6: </dtr:DisplayData>

Ecco quindi che grazie alla possibilità di esporre (e gestire) gli eventi, abbiamo potuto mantenere l'UpdatePanel con UpdateMode a Conditional, permettendo quindi di non far scatenare postback asincroni del tutto inutili.

Tags: , , ,

ASP.NET AJAX | ASP .NET | .NET

MultiHandleSliderExtender in un Templated Control

by Andrea 05 March 2009 05:18

Se provate a utilizzare un MultiHandleSliderExtender all'interno di una GridView, o di un Repeater o di un altro Templated Control, vi capiterà con una bella eccezione javascript (null is null or not an object) in quanto non l'extender non riesce a trovare i controlli impostati come MultiHandleSliderTarget.
Dando un'occhiata al file javascript di questo extender si può notare che il controllo esegue la funzione $get (recupera un elemento all'interno della pagina) usando come parametro l'id inserito, ma che nel caso di inserimento in un Templated Control, questo sarà differente dall'effettivo id utilizzato nella pagina (ClientID), sollevando quindi l'eccezione.

Per risolvere questo è sufficiente gestire l'evento RowDataBound (nel caso della GridView) e sostituire in ogni MultiHandleSliderTarget l'id dei controlli con i rispetti ClientID.

Ecco il codice necessario:

   1: protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
   2: {
   3:     if (e.Row.RowType == DataControlRowType.DataRow)
   4:     {
   5:         MultiHandleSliderExtender slider = e.Row.FindControl("multiHandleSliderExtenderTwo") as MultiHandleSliderExtender;
   6:         foreach (MultiHandleSliderTarget target in slider.MultiHandleSliderTargets)
   7:             target.ControlID = e.Row.FindControl(target.ControlID).ClientID; 
   8:     }
   9: }

Tags: , , , ,

.NET | ASP .NET | ASP.NET AJAX

Utilizzare una pagina dei Dynamic Data in una folder differente

by andrea 16 February 2009 02:17

Può capitare di voler riutilizzare una pagina dei Dynamic Data (al di fuori della cartella dei Dynamic Data), e questo per avere "a gratis" le validazioni dei campi, oppure semplicemente perchè utilizzano dei FiledTemplate custom (su cui magari abbiamo investito parecchio tempo).
Nel mio caso, la necessità è nata dal voler far editare le informazioni della propria Azienda, senza dare accesso all'utente alla lista delle Aziende (percorso che viene normalemente proposto con i Dynamic Data: visualizzazione lista aziende -> dettaglio azienda).

COME FARE?

Per fare ciò è sufficiente copiare la pagina nel nuovo percorso e modificare il Global.asax in modo da aggiungere le regole di routing appropriate:

   1: routes.Add(new DynamicDataRoute("Edit/Company.aspx")
   2: {
   3:     Action = PageAction.Edit,
   4:     Model = model,
   5:     Table = "Companies"
   6: });

All'interno della pagina copiata, si dovranno valorizzare le proprietà EntitySetName e ContextTypeName della EntityDataSource, altrimenti si presenterà il seguente errore:

The control 'DetailsDataSource' does not have a TableName property and a table name could not be inferred from the URL.

Nel caso si utilizzi i Dynamic Data con LINQ to SQL, le proprietà da modificare sono TableName e ContextTypeName della LinqDataSource.

Se la pagina prevede eventuali parametri in querystring, dovranno essere presenti nell'url della pagina, oppure dovrete essere voi a settarli andando ad aggiungere da codice gli appropriati WhereParameters, e cancellando il controllo DynamicQueryStringParameter (contenuto nella datasource).

Technorati Tags: ,

Tags: ,

ASP .NET

Dynamic Data - Nascondere colonne in determinate action

by Andrea 19 December 2008 03:16

Nel visualizzare i dati nelle nostre applicazioni, spesso si ha la necessità di visualizzare un numero di informazioni differenti nel caso fossimo in una lista, o in un dettaglio o in edit di un nostro oggetto.

Lavorando con i Dynamic Data, di default la cosa non è possibile, ma con un pò di codice la cosa è fattibile.

Stephen Naughton ha trovato una soluzione davvero brillante, e cioè implementando l'interfaccia IAutoFieldGenrators (che viene utilizzata dalla GridView, e DetailsView per creare in automatico le colonne e/o fields), e creando un attributo da utilizzare nelle classi dei Metadati dove verranno specificate le action per le diverse property.

Il post è il seguente: Dynamic Data - Hiding Columns in selected PageTemplates

Tags: , , ,

ASP .NET

Passaggio a BlogEngine. Addio WordPress

by Andrea 30 May 2008 02:23

Era da tempo che avevo iniziato la cosa, ma per un motivo o per un'altro avevo sempre posticipato. Ecco che ora il mio blog gira su BlogEngine e non più su WordPress.

Perchè questo?
Semplice perchè BlogEngine è sviluppato in .NET e questo mi permette di personalizzarlo e aggiungergli funzionalità a mio piacimento, senza dipendere da plugin di terze parti.
WordPress è una piattaforma di blog davvero stupenda, e credo proprio di poter dire che è la migliore che conosca, e la consiglierei a tutti....ma purtroppo è in PHP e non ho la voglia (e il tempo) di approfondirlo come argomento (dite pure che è pigrizia). Ecco il motivo di questo cambiamento.
In questo modo avrò anche la possibilità di testare le ultime tecnologie riguardanti il mondo del .NET Framework direttamente nel mio blog, e non è una cosa da poco.

Cambia il blog e cambia anche il dominio.
Il nuovo dominio ora è http://blog.dottor.net perchè il target del mio blog è un pò cambiato da quando ho iniziato, e "il silenzio di un urlo" ha poco a che vedere con i post relativi alle tecnologie Microsoft .NET.
Ma non ho intenzione di far morire quel dominio perchè ci sono proprio affezionato...lo terrò quindi per qualche idea/progetto futuro (che non si sa mai).

Dal vecchio blog è attivo un redirect (redirect 301) che ridirige i vecchi url verso quelli nuovi (e per questo rigrazio Roberto che mi ha dato una mano a riguardo), e spero di esser riuscito a redirigerli tutti. Spero poi che google mi dia una mano, a riposizionare il mio nuovo blog allo stesso livello di quello vecchio, per permettervi di trovare velocemente i miei vecchi post.

Il feed invece rimane invariato, e per chi non lo ha ancora sottoscritto, ecco qui: http://feeds.dottor.net/ilsilenziodiunurlo

Inoltre, se riscontrate qualche problema, non esitate a contattarmi.

Technorati Tags: ,

Tags: , ,

.NET | Sito

AutoComplete Extender - alcuni workaround

by Andrea 04 April 2008 14:04

BoxRicercaStò utilizzando il controllo AutoComplete Extender, contenuto negli Ajax Control Toolkit, e mi sono trovato ad affrontare diversi problemi dovuti a bug del controllo ed altri dovuti a problemi con IE6.
Voglio però sottolineare che grazie alla flessibilità di questi controlli, sono riuscito facilmente a trovare alcuni workaround senza dover scrivere montagne di codice.

Nella mia applicazione mi trovo ad avere un controllo TextBox a cui è collegato l'AutoComplete Extender (per agevolare l'inserimento del testo), e posizionati subito sotto sono presenti alcune DropDownList.

Iniziamo dal primo problema:
con IE6, all'apertura del pannello dell'AutoComplete Extender, le DropDownList rimangono in primo piano, "bucando" il pannello.
La soluzione che ho trovato è stata quella di intervenire nelle animations, inserendo alcuni ActionScript che nascondono le DropDownList quando il pannello si apre, e le rivisualizzano non appena il pannello si stà chiudendo. In questo modo, l'AutoComplete Extender sarà visualizzato senza problemi grafici.

Altro problema:
alla chiusura del pannello non riuscivo più a modificare il valore delle DropDownList perchè il pannello viene nascosto impostando lo stile visibility, che lo fa quindi mantere in primo piano, bloccando l'accesso ai controlli posti sotto.
La soluzione più veloce è stata quella di intervenire anche qui nelle ActionScript, recuperandomi l'oggetto del pannello (che ha l'ID composto da BehaviorID__completionListElem) e settandogli la proprietà display a none. Facendo così, il pannello non risulta più essere in primo piano, e si ha l'accesso ai controlli in precedenza bloccati.

Ecco qui il codice per risolvere questi due problemi:

<ajaxToolkit:AutoCompleteExtender 
    runat="server" 
    BehaviorID="AutoCompleteEx" 
    ID="autoComplete1"
    TargetControlID="CittaCod" 
    ServiceMethod="GetCityList" 
    ServicePath="~/Services.asmx"
    MinimumPrefixLength="2" 
    CompletionInterval="1000" 
    FirstRowSelected="true" 
    EnableCaching="true"
    CompletionSetCount="20" 
    CompletionListCssClass="autocomplete_completionListElement"
    CompletionListItemCssClass="autocomplete_listItem" 
    CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem">
    <Animations>
    <OnShow>
        <Sequence>
            <OpacityAction Opacity="0" />
            <HideAction Visible="true" />
            <ScriptAction Script="
                var behavior = $find('AutoCompleteEx');
                if (!behavior._height) {
                    var target = behavior.get_completionList();
                    behavior._height = target.offsetHeight - 2;
                    target.style.height = '0px';
                }" />
            <Parallel Duration=".4">
                <FadeIn />
                <Length PropertyKey="height" 
                        StartValue="0" 
                        EndValueScript="$find('AutoCompleteEx')._height" />
            </Parallel>                                
            <ScriptAction Script="                 
                var ddlPrezzoMin = $get(ddlPrezzoMinID);
                var ddlPrezzoMax = $get(ddlPrezzoMaxID);
                var ddlMqMin = $get(ddlMqMinID);
                var ddlMqMax = $get(ddlMqMaxID);
                
                ddlPrezzoMin.style.visibility = 'hidden';
                ddlPrezzoMax.style.visibility = 'hidden';
                ddlMqMin.style.visibility = 'hidden';
                ddlMqMax.style.visibility = 'hidden'; 
                " />
        </Sequence>
    </OnShow>
    <OnHide>
        <Sequence>
            <ScriptAction Script="    
                var ddlPrezzoMin = $get(ddlPrezzoMinID);
                var ddlPrezzoMax = $get(ddlPrezzoMaxID);
                var ddlMqMin = $get(ddlMqMinID);
                var ddlMqMax = $get(ddlMqMaxID);
                
                ddlPrezzoMin.style.visibility = 'visible';
                ddlPrezzoMax.style.visibility = 'visible';
                ddlMqMin.style.visibility = 'visible';
                ddlMqMax.style.visibility = 'visible';
                
                var autoCompleteElement = $get('AutoCompleteEx_completionListElem');
                autoCompleteElement.style.display = 'none';                                    
                " />
            <Parallel Duration=".4">
                <FadeOut />
                <Length 
                    PropertyKey="height" 
                    StartValueScript="$find('AutoCompleteEx')._height" 
                    EndValue="0" />
            </Parallel>
        </Sequence>
    </OnHide>
    </Animations>
</ajaxToolkit:AutoCompleteExtender>

 

Tags: , , , ,

ASP.NET AJAX

Creare un Control Extender, da dove cominciare

by Andrea 19 June 2007 23:06

AspNetAjax Se avete intenzione di cimentarvi a creare un Control Extender sappiate che la cosa è più semplice di quello che credete.

Per cominciare vi consiglio alcuni link:
Il primo è un tutorial che trovate nel sito di ASP .NET AJAX e vi guiderà passo passo: Creating a new extender

Un'altra risorsa molto utile è il webcast tenuto da :
ASP.NET 2.0 AJAX: Extending ASP.NET AJAX

Ed infine il link al progetto AJAX Control Toolkit. All'interno del progetto scaricato è disponibile anche il pacchetto di installzione per aggiungere il template per creare un Control Extender (il file si chiama AjaxControlExtender.vsi) e permetterà di creare in automatico i file necesssari allo sviluppo di un Extender (file *Behavior.js, *Designer.cs ed *Extender.cs): AJAX Control Toolkit

Tags: , , , ,

ASP.NET AJAX