FileUpload caricato in un postback asincrono

by andrea 13 March 2009 01:54

Se avete provato a caricare un controllo FileUpload durante un PostBack asincrono, oppure settate la visibilità da false a true, avrete notato che il controllo non funziona correttamente e quindi non vi permette di caricare il file (anche se con PostBackTrigger impostato correttamente).

Questo problema avviene perchè il controllo non è in grado di aggiornare correttamente il tag form della pagina.

Per risolvere il problema si deve modificare il tag form aggiungendo l'enctype:

   1: enctype="multipart/form-data"

è anche possibile aggiungerlo da codice utilizzando questo codice nel page_load:

   1: Page.Form.Attributes.Add("enctype", "multipart/form-data"); 

 

Tags:

ASP.NET AJAX | ASP .NET | .NET

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

Dynamic Data - recuperare la action corrente

by Andrea 18 December 2008 06:42

Se avete la necessità di recuperare la action corrente all'interno di un FieldTemplate (o di una pagina dei Dynamic Data), il codice che potete utilizzare è il seguente:

   1: RequestContext requestContext = DynamicDataRouteHandler.GetRequestContext(HttpContext.Current);
   2: string action = requestContext.RouteData.GetRequiredString("action");
   3:  
   4: if (string.Compare(action, "Details", true) == 0)
   5: {
   6:     ...
   7: }
   8: else
   9: {
  10:     ...
  11: }

Una delle motivazioni in cui può essere utile recuperare tale informazione è nel caso di un FileldTemplate custom nella modalità di sola lettura dei dati, che viene utilizzato sia per la lista che per il dettaglio, e quindi può esserci la necessità di modificare la visualizzazione a seconda della action.

Nel mio caso, ho inserito due panel nel FieldTemplate e con il codice qui riportato ne modifico la visibilità (ovviamente eseguendo il databind dei soli interessati). Un panel contiene una Label con un contatore dei dati (utilizzato nella lista), mentre il secondo panel contiene una ListView che visualizza l'elenco dei figli (utilizzato nel Dettaglio). Questo per visualizzare informazioni recuperate da una relazione molti a molti.

Tags: , ,

ASP .NET

Akismet Extension per BlogEngine.net

by Andrea 17 December 2008 01:21

BlogEngine ha un captcha invisibile che nel 99% dei casi ha sempre funzionato perfettamente.
In questi giorni però qualche commento di spam è riuscito a passare, e quindi mi sono messo alla ricerca (se esisteva) un'extension che verificasse i commenti utilizzando le Akismet.

L'extension esiste, e la potete trovare qui Akismet Extension Updated for BlogEngine.net 1.4 sviluppata da Justin Etheredge (che ringrazio davvero molto).

Comunque appena avrò un pò di tempo inizierò a sviluppare una nuova versione, aggiungendo l'invio per email dei commenti di spam (cosa che manca all'attuale extension, che annulla solamente l'inserimento).

Technorati Tags: ,

Tags: ,

ASP .NET | Generale | Sito

Dynamic Data - ScaffoldTable a false e CustomPages

by Andrea 16 December 2008 09:17

Può sembrare che il post parli di due argomenti distinti, ma non è così. Infatti il parametro ScaffoldTable e le CustomPage hanno una cosa in comune, e riguarda la visibilità delle tabelle.

Lavorando con i Dynamic Data, avevo la necessità di non visualizzare una mia classe/tabella. Per fare questo, la cosa è veramente semplice:

  • Impostare nel Global.asax ScaffoldAllTables = false, in modo essere noi a specificare quali tabelle visualizzare e quali no. (Per default lavoro già con questo parametro impostato a false, perchè le tabelle che di solito visualizzo con i Dynamic Data sono poche, rispetto quelle presenti nel database).
  • Creare una partial class della classe del modello di Entity Framework (o di Linq to SQL) e impostare l'attributo ScaffoldTable a false per nascondere, oppure a true per farle visualizzare.
    [ScaffoldTable(false)]
    public partial class Users
    {
    }

La cosa divertente (si fa per dire), è che sebbene abbia impostato tale attributo a false, la tabella era comunque visibile.
Ho fatto diverse prove, e poi ho ragionato nel cosa differisse questa classe rispetto a quelle non visibili, e l'unica risposta era...le CustomPage.

Se si imposta nella classe l'attributo ScaffoldTable con valore false, se esistono delle Custom page che le appartengono, la classe sarà (lo stesso) visibile nel nostro sito creato con i Dynamic Data.

Infatti, rinominando la cartella contenente le custom page da Users a _Users (oppure cancellando la cartella) la tabella si è correttamente eliminata dalla visualizzazione.
Non sono d'accordo su questo comportamento, e mi sarei aspettato che l'attributo avesse la priorità, ma c'è anche da dire, che se una persona crea delle custom page è perchè ha l'intezione di vidualizzare quei dati. Ecco quindi dei pro che dei contro per questa scelta.

Il lato negativo di questo aspetto è che uno è costrettto a eliminare eventuali CustomPage che avevo già creato (e customizzato), e che dovrò ripristinare appena quella sezione (quella tabella) dovrà essere visibile all'utente.

Update: Ho inserito la segnalazione su connect per capire se il comportamento è un by design oppure un bug. Ecco il link
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=388504

Tags: , ,

ASP .NET

Usare uno UserControl come Page Templates per i Dynamic Data

by Andrea 26 November 2008 00:04

Leggo oggi nel ble di David Ebbo della possibilità di associare uno UserControl come Page Template, e il tutto sia con l'utilizzo del routing, ma anche senza.

Il post è il seguente: Using User Controls as Page Templates in Dynamic Data

Non ho ancora provato la cosa, ma sicuramente a breve farò qualche test per capirne meglio i vantaggi. L'unico che vedo al momento è la possibilità di riutilizzare degli usercontrol esistenti eseguendo delle modifiche minime.

Technorati Tags: ,

Tags: , ,

ASP .NET

Controllo Calendar e Z-Index

by andrea 20 November 2008 09:15

A volte le cose banali sono quelle che fanno perdere maggior tempo. Chissa che quindi questo post faccia risparmiare qualche minuto a qualcuno di voi. ;)

Oggi mi sono trovato alle prese con il controllo Calendar degli AJAX Control Toolkit, che si posizionava al di sotto del div contenente le google maps.
  
Controlando con la Developer Toolbar avevo verificato l'impostazione dello z-index, che era impostato correttamente a 1000. L'unico dubbio che avevo era a riguardo della proprietà, che mi veniva chiamata zIndex (senza il trattino), ma ho pensato che fosse comunque valido. Calendar_index_0Calendar_index_2
Dopo vari test, mi sono detto di provare a settare correttamente lo z-index impostando io lo stile, ed effettivvamente il problema si è risolto. :D

.ajax__calendar_container
{
    z-index: 1000;
}

Calendar_index_1

Tags:

ASP.NET AJAX | ASP .NET