silverlight comments edit

Non so da quanto tempo esista…lo scopro oggi su consiglio di Marco. Smooth Streaming è una extension per IIS Media Services che consente di effettuare uno streaming “adattativo” verso il client in base alla banda a lui a disposizione, ed il client ovviamente dovrà essere munito del plugin di Silverlight.

Il risultato è veramente impressionante: riuscire a vedere un video in streaming senza effettuare buffering e con la massima qualità ottenibile dalla propria connessione. Sbalorditivo!
Di seguito trovate un filmato che mostra lo Smooth Streaming in azione.

 

SEIISAddon

Ciauz

various comments edit

Spesso si utilizza la mail come Log per tutti quegli errori di cui si ha l’esigenza di avere una notifica nell’immediato; un esempio potrebbe riguardare tutte le eccezioni che impediscono l’utilizzo dell’applicazione da parte degli utenti.

Anche se può sembrare un’operazione piuttosto semplice quella di inviare un’eccezione via mail, bisogna ugualmente prestare attenzione in tutti quei casi in cui si utilizza la proprietà Message dell’eccezione come Subject della mail; lo script seguente chiarisce la situazione.

MailMessage message = new MailMessage();
message.Subject = exc.Message;
...

Un approccio di questo tipo vi può portare incontro ad un’eccezione come la seguente:

ArgumentException: The specified string is not in the form required for a subject

Il problema è dovuto al fatto che il contenuto della proprietà Message può contente una nuova linea, quindi “\r\n”, che genera un errore nel metodo Send come spiegato qui.

La soluzione consiste nell’effettuare il replace delle stringhe non consentite con uno spazio vuoto, come mostrato di seguito:

MailMessage message = new MailMessage();
message.Subject = exc.Message.Replace("\r", " ").Replace("\n", " ");
...

Ciauz

various comments edit

Anche se in ritarto, è con estremo piacere che riporto la notizia che uno User Group .NET sta nascendo in Sicilia.
Se pur io non sia siciliano, ma marchigiano doc, sono molto affezzionato a questa regione, in quanto due miei carissimi amici ne fanno parte ed hanno avuto la bellissima idea di creare uno UserGroup proprio lì.
Di chi sto parlando? Beh dello sciuro Sudano e il grandissimo Salvo!
La partecipazione è d’obbligo, per qualsiasi info e idee vi segnalo questi due post 1 e 2.

Un mega "IN BOCCA AL LUPO" è di dovere.

Ciauz

asp.net comments edit

Ormai sempre più applicazioni web fanno uso della tecnologia AJAX, in quanto essa offre numerosi vantaggi: dall’ottimizzazione del traffico di rete ad una maggior velocità di navigazione. L’uso di questa tecnologia permette sì la navigazione tra contenuti differenti senza effettuare il reload della pagina, ma purtroppo toglie usabilità al sito, in quanto l’utente è portato ad utilizzare il bottone Back del browser per tornare al contenuto precedente, cosa che non avviene se si sta utilizzando AJAX.


Per risolvere questo incoveniente Microsoft ha introdotto, tramite il Service Pack 1 del .NET Framework 3.5, la possibilità di utilizzare i bottoni per la navigazione integrati con il browser per muoversi attraverso l’hystory delle chiamate AJAX.

Come per ogni ASP.NET WebForm che utilizza AJAX, è necessario che nella pagina sia presente lo ScriptManager, dove si andrà ad abilitare l’utilizzo dell’Hystory e ad associare l’evento che dovrà essere scatenato durante la navigazione, come mostrato di seguito:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnableHistory="True" 
    onnavigate="ScriptManager1_Navigate">
</asp:ScriptManager>

Nello snippet seguente viene mostrato come aggiungere un HystoryPoint, e l’evento che viene invocato alla pressione dei tasti Back e Forward del browser.

protected void GridView1_PageIndexChanged(object sender, EventArgs e)
{
    if(ScriptManager1.IsInAsyncPostBack && !ScriptManager1.IsNavigating)
    {
        ScriptManager1.AddHistoryPoint("Gridview1",GridView1.PageIndex.ToString());
    }
}

protected void ScriptManager1_Navigate(object sender, HistoryEventArgs e)
{
    int pageIndex = 0;

    if(string.IsNullOrEmpty(e.State["Gridview1"]))
    {
        GridView1.PageIndex = pageIndex;
    }
    else
    {
        pageIndex = int.Parse(e.State["Gridview1"]);
        GridView1.PageIndex = pageIndex;

        Title = "Paginda del gridview numero:" + (pageIndex + 1);

    }
}

In questo esempio si è optato per l’associazione degli HystoryPoint alla paginazione di un GridView, ma la stessa cosa è applicabile a qualsiasi tipo di chiamata AJAX.

asp.net comments edit

Dati i miei ultimi post, si è sicuramente capito che sono un “Fan”, se così si può dire, del Framework ASP.NET MVC .

Proprio su questo Framework posto alcuni link, a mio avviso molto utili, che possono aiutare a colmare alcune “lacune” di questo giovanissimo Framework, come la validazione client-side.

Proprio sulla validazione con ASP.NET MVC riporto una serie di link ad articoli su questo argomento:

 

  • Utilizzare MVC Validator ToolKit qui.
  • Utilizzare xVal per la validazione client-side qui.
  • Ottimo articolo sulla validazione con xVal e Castle qui.
  • Utilizzare il Validation Application Block dell’Enterprise Library con MVC qui.
  • Utilizzare il Validation Application Block dell’Enterprise Library con MVC Binde qui.

Ciauz

asp.net comments edit

Cercando di effettuare il porting di Dexter al .NET Framework 4.0 con Visual Studio 2010, mi sono accorto che non è possibile aprire l’applicazione web basata su ASP.NET MVC, in quanto questo Framework non è incluso nell’installer del nuovo Visual Studio.

La motivazione la apprendo qui, dal blog del PM di MVC Phil Haack , di cui riporto lo spezzone di seguito:

One thing you’ll notice is that ASP.NET MVC is not included in Beta 1. The reason for this is that Beta 1 started locking down before MVC 1.0 shipped. ASP.NET MVC will be included as part of the package in VS10 Beta 2.

We’re working hard to have an out-of-band installer which will install the project templates and tooling for ASP.NET MVC which works with VS2010 Beta 1 sometime in June on CodePlex. Sorry for the inconvenience. I’ll blog about it once it is ready.

 

Il problema è facilmente risolvibile scaricando l’installer per Visual Studio 2010 direttamente da qui, mentre a questo link è possibile trovare la RoadMap della versione 2.0 del Framework.

Ciauz

.net comments edit

Spesso l’utilizzo dell’Aspect Oriented Programming (AOP) viene associato alla parte di Logging, e rarissimamente alla parte di Business di un’applicazione; ovviamente il suo campo d'azione è ben più grande e, giusto la scorsa settimana, mi è capitato di utilizzare l’AOP per effettuare del Bug Fixing su un servizio WCF fornitomi da un’azienda esterna.

In una sessione insieme a Stefano mostrai l’approccio utilizzato in MTV.it per la parte di Logging e di Rewarding nei servizi WCF; affrontammo così come utilizzare AOP anche per la parte di business dell’applicazione e, sempre nella stessa sessione, mostrammo come realizzare un Custom Behaviour per WCF che permettesse di utilizzare l’AOP senza la necessità di ricompilare il servizio.

Come accennato sopra, proprio la scorsa settimana ho avuto dei problemi con un servizio WCF realizzato da una ditta fornitrice esterna che, nell’invocazione di un determinato metodo, non invalidava la cache, causando così un’incongruenza di dati tra tutte quelle applicazioni che accedevano allo stesso repository di Cache.

Purtroppo, non avendo il codice sorgente né la possibilità di effettuare un deploy in tutti i server, l’unica soluzione indolore che mi è venuta in mente è stata quella di realizzare un’interceptor per SpringFramework ed invalidare la cache tramite AOP.

Con 10 righe di codice per l’interceptor e altre 10 nel file di configurazione del servizio, il bug è stato risolto.
Tutto questo a dimostrazione del fatto che l’utilizzo dell’AOP può andare ben oltre il semplice Logging applicativo, e che spesso può far risparmiare parecchio tempo in fase di sviluppo e bug fixing.

Ciauz

asp.net comments edit

Se si è abituati a sviluppare applicazioni con ASP.NET e si passa successivamente a sviluppare con il Framework ASP.NET MVC, la prima cosa di cui si sente la mancanza sono i controlli, che in MVC mancano proprio.

Uno tra questi è il controllo Pager che, come fa ben intuire il nome, serve per gestire la paginazione in tutte quelle parti dei siti web in cui non è possibile mostrare l’elenco completo dei contenuti in un’unica pagina.

Per poter creare un controllo Pager riutilizzabile in tutte le applicazion MVC based, è necessario stabilire tutto ciò che serve per poter creare questo tipo di controllo, ossia:

  • Numero totale di pagine (TotalCount);
  • Numero di contenuti per pagina (PageSize);
  • Pagina corrente (PageIndex);
  • Parametro da utilizzare in querystring per comunicare al server la nuova pagina (ParameterName);

Dato che gli MVC ViewUserControl, come le MVC ViewPage, possono avere un Model da utilizzare all’interno del controllo, come prima cosa sarà necessario costruirne uno come il seguente:

public class PagerViewModel
{
    public PagerViewModel(string parameterName, int totalCount, int pageSize, int pageIndex)
    {
        ParameterName = parameterName;
        TotalCount = totalCount;
        PageSize = pageSize;
        PageIndex = pageIndex;
    }

    public int PageIndex { get; set; }
    public int PageSize { get; set; }
    public int TotalCount { get; set; }
    public string ParameterName { get; set; }

    public int TotalPages
    {
        get { return (int) (TotalCount/(long) PageSize) + (TotalCount%(long) PageSize == 0 ? 0 : 1); }
    }

    public bool HasPreviousPage
    {
        get { return (PageIndex > 1); }
    }

    public bool HasNextPage
    {
        get { return (PageIndex*PageSize) <= TotalCount; }
    }

    public string PageActionLink(int pageIndex)
    {
        if (HttpContext.Current.Request.QueryString.Count > 0)
        {
            string q = string.Concat(HttpContext.Current.Request.Url.AbsolutePath, "?", HttpContext.Current.Request.QueryString.ToString(), "&", ParameterName + "=", pageIndex);

            if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[ParameterName]))
            {
                string qs = HttpContext.Current.Request.QueryString.ToString();
                string oldvalue = string.Concat(ParameterName, "=", HttpContext.Current.Request.QueryString[ParameterName]);
                string newvalue = string.Concat(ParameterName, "=", pageIndex);

                qs = qs.Replace(oldvalue, newvalue);

                return string.Concat(HttpContext.Current.Request.Url.AbsolutePath, "?", qs);
            }

            return q;
        }

        return string.Concat(HttpContext.Current.Request.Url.AbsolutePath, "?", ParameterName + "=", pageIndex);
    }

    public string GetPageUrl()
    {
        return HttpContext.Current.Request.Url.AbsolutePath + "?" + ParameterName + "=" + PageIndex;
    }
}

Da qui, con una serie di istruzioni if, è facile creare la struttura per la paginazione, come mostrato dal markup seguente:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<PagerViewModel>" %>
<%@ Import Namespace="imperugo.sample.mvc.pager.Models"%>

<% if (Model.TotalPages > 1) { %>
<div class="pnavigation">
    <div class="pager">
        <span class="pages">&#8201;<%= Model.PageIndex %> di <%= Model.TotalPages %>&#8201;</span>
        <% if (Model.PageIndex > 1) { %>
        <a href="<%=Model.PageActionLink (1)%>" title="&laquo; First">&#8201;&laquo; First&#8201;</a>
        <% } %>
        <% if (Model.PageSize - Model.PageSize > 0) { %>
            <a href="<%=Model.PageActionLink((Model.PageIndex - Model.PageSize) + 1)%>" title="<%=(Model.PageIndex - Model.PageSize) + 1%>">&#8201;...&#8201;</a>
        <% } %>
        <% if (Model.HasPreviousPage) { %>  
            <a href="<%=Model.PageActionLink((Model.PageIndex - 1))%>" title="Previous" >&laquo;</a>
        <% } %>
        <% for (int page = Model.PageIndex; page < Math.Round((Model.TotalCount / Model.PageSize) + 0.5) && page < Model.PageIndex + Model.PageSize; page++)
           { %>
            <% if (page == Model.PageIndex) { %>
                <span class="current">&#8201;<%= Model.PageIndex %>&#8201;</span>
            <% } else { %>
                <a href="<%=Model.PageActionLink(page)%>" title="<%=page.ToString()%>">&#8201;<%=page.ToString()%>&#8201;</a>
            <% } %>
        <% } %>
              
        <% if (Model.HasNextPage) { %>  
            <a href="<%=Model.PageActionLink ((Model.PageIndex + 1))%>" title="Next" >&raquo;</a>
        <% } %>
        <% if (Model.PageIndex + Model.PageSize <= (Math.Round((Model.TotalCount / Model.PageSize) + 0.5) - 1)) { %>
            <a href="<%=Model.PageActionLink((Model.PageIndex + Model.PageSize) + 1)%>" title="<%=(Model.PageIndex + Model.PageSize) + 1%>">&#8201;...&#8201;</a>
        <% } %> 
        <% if (Model.PageIndex < Model.TotalPages) { %>
        <a href="<%=Model.PageActionLink(Model.TotalPages)%>" title="Last &raquo;">&#8201;Last &raquo;&#8201;</a>
        <% } %>
    </div>
</div>        
<% } >

Ora che si hanno a disposizione sia l’ MVC ViewUserControl che il suo Model, è necessario popolare quest’ultimo dal controller come mostrato di seguito:

[HandleError]
public class HomeController : Controller
{
    public ActionResult Index(string page)
    {
        int pageIndex = string.IsNullOrEmpty(page) ? 1 : int.Parse(page);
        const int PAGE_SIZE = 10;

        HomeModel hm = new HomeModel();
        hm.News = GetNews(pageIndex, PAGE_SIZE);
        hm.NewsPage = new PagerViewModel("page", GetTotalNumber(), PAGE_SIZE, pageIndex);

        return View(hm);
    }

....

}

L’ultimo snippet mostra come utilizzare l’ MVC ViewUserControl  dalla View.

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
    <% for (int i = 0; i < Model.News.Count; i++) { %>
        <div><%= Model.News[i].Title %></div>
    <% } %>
    <div class="pager">
        <% Html.RenderPartial("~/Views/Shared/PagerUserControl.ascx", Model.NewsPage); %>
    </div>
</asp:Content>

Nello screeshot seguente è visibile il risultato raggiunto nell’esempio allegato.

MVC Pager

Download esempio qui

.net comments edit

Giuro che non vivo di soli DTO (Data Trasfer Object), ma dopo l’ultimo post, su consiglio di Matteo, mi sono messo a dare un occhio ad AutoMapper, ossia una libreria che semplifica la parte di “trasbordo” dei dati da una classe ad un’altra.

Dopo un primo sguardo le potenzialità  sembrano ottime, ed è molto interessante come hanno implementato la parte di mapping anche per entità e grafi di DTO complessi e non.
I mapping possibili sono diversi:

L’unico neo sono le performances. Come già detto nel post precedente (in realtà è stato detto praticamente da tutti) la Reflection non gode di una fama velocistica, e questa libreria ne fa uso per idratare le entities.

Dopo un veloce sguardo al codice sorgente ho sostituito con estrema facilità la parte in cui si faceva uso della Reflection con la parte utilizzata nel mio snippet precendete, per iniettare IL a runtime.
Il risultato è sbalorditivo, tutte le ottime potenzialità di questa libreria con le performances dell’IL.

Ovviamente ho segnalato la cosa al Team, che gode della presenza di Jeffrey Palermo, e che ha accolto la richiesta e sta analizzando come e quando integrare questo tipo di approccio.

Ciauz