Chiamare un page-method da jQuery

by Andrea Dottor 17 July 2012 22:20

Con ASP.NET AJAX sappiamo bene come interrogare un page-method, ed in rete troviamo parecchia documentazione. Il tutto si basa sul controllo ScriptManager, dove abilitando il flag EnablePageMethods viene automaticamente creato un proxy javascript che ci permette di chiamare il page-method in modo molto semplice e veloce.

A questa pagina troviamo un esempio di come chiamare un page-method utilizzando ASP.NET AJAX: Exposing Web Services to Client Script

E' possibile però evitare l'utilizzo/dipendenza da ASP.NET AJAX, ed evitare quindi di avere nella pagina un controllo ScriptManager. Per fare questo ci viene in aiuto jQuery.

Come utilizzare jQuery per chiamare il page-method?

La cosa è molto semplice e si basa sull'uso del metodo Ajax di jQuery, e sul come comporre l'url da invocare.

Ecco qui un esempio di codice per invocare il page-method Save presente all'interno della pagina Product.aspx. Il metodo Save ha un parametro objToSave di tipo string (che riceverà un prodotto in formato JSON).

var product = new Object();
product.Description = "Descrizione";
product.Code = "ABC123";
product.Data = "20120712";
product.CategoryID = 12;

var dataToSave = new Object();
dataToSave.objToSave = JSON.stringify(product);

$.ajax({
  type: "POST",
  url: "Product.aspx/Save",
  data: JSON.stringify(dataToSave),
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  success: function (msg) {
    alert('Risultato del salvataggio: ' + msg.d);
  },
  error: function (err) {
    alert('Errore: ' + err.statusText);
  }
});

Come potete bene vedere l'url da chiamare da jQuery è composto dal nome della pagina seguito dal nome del page-method ("Product.aspx/Save").
Questo metodo permette di avere anche oggetti in ritorno da metodo, che verranno gestiti dal codice inserito all'interno del metodo success.

Utilizzando questo codice non si hanno dipendenze dalle librerie ASP.NET AJAX, e aggiungo che il codice JavaScript necessario è inferiore a quello del proxy che verrebbe generato dal controllo ScriptManager.

E quindi, per l'ennesima volta, jQuery batte ASP.NET AJAX Winking smile

Tags: ,

ASP .NET | ASP.NET AJAX | jQuery

Codice e slide della sessione ASP.NET e lo sviluppo Client Side

by Andrea Dottor 20 March 2012 14:30

Ecco pronti al download il codice e le slide della mia sessione "Il mondo è sempre più client. ASP.NET e lo sviluppo Client Side" che ho tenuto il 9 marzo 2012.

IScriptControl, Knockout e le ASP.NET Web API sono stati i principali protagonisti :-)

Abstract: Le applicazioni che sviluppiamo, e che il mercato richiede sempre più, stanno modificando il modo in cui le applicazione vengono scritte. La logica di interazione con l'utente stà diventando sempre più client side, questo grazie anche all'espansione di dispositivi mobile che fruiscono le nostre applicazioni. JQuery ed il javascript in generale hanno un ruolo sempre maggiore, e permetteno in molti casidi poter far fare la differenza a ciò che sviluppiamo.

Come per il codice dello scorso meeting, per quanto riguarda il database utilizzato nella demo è necessario scaricare il database AdventureWorks che trovate al seguente link http://msftdbprodsamples.codeplex.com/e modificare la connectionstring del progetto web.

Tags: , , ,

ASP .NET | ASP.NET AJAX | XeDotNet | Microsoft

Inizia un nuovo anno per XeDotNet

by Andrea 11 January 2012 00:10

E' stato pubblicato il calendario degli eventi XeDotNet per il primo semestre del 2012.

10/02/2012 - HTML5 e lo sviluppo mobile

  • Andrea Dottor - ASP.NET e lo sviluppo mobile
  • Davide Senatore - Packaging HTML5 application with PhoneGap

09/03/2012 - Sviluppo client side

  • Andrea Boschin - What's new in Silverlight 5.0
  • Andrea Dottor - Il mondo è sempre più client. ASP.NET e lo sviluppo Client Side

06/04/2012 - Real world experience

  • Cristiano Simionato - Ma quanto costa Windows Azure?
  • Mirco Vanini - REST & .NET Micro FW - A Real Case

04/05/2012 - Uno sguardo a futuro

  • Davide Vernole - Visual Studio vNext - Application Lifecycle Management
  • Andrea Boschin - Sviluppare applicazioni Metro con Windows 8 e WinRT.

01/06/2012 - Playing with gadgets

  • Mirco Vanini - Are you a Gadgeteer?
  • Davide Vernole - Playing with Team Foundation Server
Per quanto mi riguarda, avrò il piacere di tenere due sessioni, basate su alcune esperienze lavorative che ho affrontato in quest'ultimo periodo.
Le sessioni si completano a vicenda, la prima basata sullo sviluppo verso il mondo mobile grazie all'utilizzo di HTML5, jquery mobile, ASP.NET MVC e WCF...mentre la seconda si propone di presentare alcune interessanti librerie javascript e la loro integrazione con ASP.NET, e alcuni suggerimenti di come sviluppare al meglio client-side.

Quindi non vi rimane che registrarvi ;-)

Tags: , , , ,

.NET | ASP .NET | ASP.NET AJAX | XeDotNet

DynamicData e ColorPicker FieldTemplates

by Andrea 16 September 2009 03:17

Con i Dynamic Data la velocità di realizzare l'applicazione aumenta notevolmente (ovvio che dipende sempre dal tipo di applicazione che si deve realizzare) e con la creazione di FieldTemplates di ha la possibilità di migliorare l'iterazione tra applicazione e utente.

Una delle necessità che ho avuto è stata quella di dover far inserire il valore in esadecimale di un colore (es: #FFFFFF), e consapevole del fatto che un utente non potesse conoscere i valori a memoria, mi sono adoperato per realizzare un opportuno FieldTemplate.
L'ultima versione degli AJAX Control Toolkit mi è venuta in aiuto grazie al controllo ColorPicker che è stato recentemente incluso, ed ecco qui il risultato ottenuto:

ColorFieldTemplate

Il codice del FieldTemplate è il seguente:

   1: public partial class Color_EditField : FieldTemplateUserControl
   2: {
   3:     protected override void ExtractValues(IOrderedDictionary dictionary)
   4:     {
   5:         dictionary[Column.Name] = ConvertEditedValue(txtColor.Text);
   6:     }
   7:  
   8:     public override Control DataControl
   9:     {
  10:         get { return txtColor; }
  11:     }
  12: }
   1: <%@ Control Language="C#" CodeBehind="Color_Edit.ascx.cs" Inherits="DynamicData.FieldTemplates.Color_EditField" AutoEventWireup="True" %>
   2:  
   3: <asp:ImageButton 
   4:     runat="Server" 
   5:     ID="btnOpenColorPicker" 
   6:     style="float:left;margin:0 3px" 
   7:     ValidationGroup="none" 
   8:     ImageUrl="~/images/cp_button.png" 
   9:     AlternateText="Click to show color picker" />
  10: <asp:Panel 
  11:     runat="server"
  12:     ID="pnlColor" 
  13:     style="width:18px;height:18px;border:1px solid #000;margin:0 3px;float:left" />
  14: <atk:ColorPickerExtender 
  15:     runat="server"
  16:     ID="colorPicker"     
  17:     TargetControlID="txtColor" 
  18:     PopupButtonID="btnOpenColorPicker" 
  19:     SampleControlID="pnlColor" 
  20:     PopupPosition="Absolute" />
  21: <asp:TextBox ID="txtColor" 
  22:     runat="server" 
  23:     Text='<%# FieldValueEditString %>' 
  24:     style="visibility:hidden;" />

Nella mia applicazione non avevo la necessita di visualizzare il codice del colore (che compare nella TextBox), ma nel caso a qualcuno interessasse, sarà sufficiente togliere lo stile "visibility:hidden;" dalla TextBox txtColor.

Tags: ,

ASP.NET AJAX | ASP .NET | .NET

ASP.NET Ajax Control Toolkit e DynamicPopulateExtenderControlBase

by Andrea 14 September 2009 06:51

Stavo introducendo il controllo HoverMenuExtender all'interno di uno UserControl e nell'intellisense mi compaiono alcune proprietà che mi risultano "anomale" per il controllo che stavo per utilizzare. Anomale nel senso che non mi aspettavo proprio di trovare tali proprietà in questo controllo.
HoverMenuExtender 
Le proprietà in questione sono quelle che hanno il suffisso Dynamic: DynamicContextKey, DynamicControlID, DynamicServiceMethod e DynamicServicePath.

Visto che (dal nome) potevano fare al caso mio, guardo la documentazione online, e scopro che non esiste documentazione a riguardo. Allora, come spesso accade, scarico i sorgenti degli ajax control toolkit e do un'occhiata al codice per capire dove fossere utilizzate e a cosa servissero. Ed è qui che sono rimasto sorpreso.

I controlli HoverMenuExtender, DropDownExtender, ModalPopupExtender e PopupControlExtender derivano dalla classe base DynamicPopulateExtenderControlBase, che contiene per l'appunto queste proprietà:

  • DynamicServicePath: url del web service che conterrà il metodo da chiamare. (lasciare vuoto se si intende chiamare un page method)
  • DynamicServiceMethod: metodo del web service da chiamare.
  • DynamicContextKey: permette di definire un parametro opzionale per parametrizzare il metodo chiamato. (parametro opzionale)
  • DynamicControlID: id del controllo che verrà utilizzato come container per iniettare il codice HTML restituito dal metodo.

Utilizzando queste proprietà è possibile utilizzare un metodo (DynamicServiceMethod) di un web service (DynamicServicePath) per farsi ritornare una porzione di condice HTML, che verrà poi iniettato in un preciso controllo (DynamicControlID).

Per provare se il tutto funziona correttamente, la via più semplice è quella di provare il tutto.
Creo un metodo in un web service che restituisca una porzione di codice HTML:

   1: [WebMethod]
   2: [ScriptMethod]
   3: public string GetHoverMenuContent(string contextKey)
   4: {
   5:     return String.Format("<span style='{0}'>Hello World!</span>", contextKey);
   6: }

e nella pagina vado a inserire il controllo, con le proprietà correttamente valorizzate:

   1: <ajax:HoverMenuExtender 
   2:     ID="hoverMenuExtender"
   3:     runat="server"
   4:     TargetControlID="linkButton" 
   5:     PopupControlID="Panel1" 
   6:     PopupPosition="Right" 
   7:     DynamicControlID="Panel2"
   8:     DynamicContextKey='font-weight:bold' 
   9:     DynamicServiceMethod="GetHoverMenuContent" 
  10:     DynamicServicePath="~/ajax.asmx" />
  11:  
  12: <asp:Panel ID="Panel1" runat="server" style="display:none;">
  13:   <asp:Label ID="Panel2" runat="server" />
  14: </asp:Panel> 

Il risultato che ho ottenuto è stato esattamente quello voluto, e quindi che al passaggio del mouse sopra al linkButton (o al controllo definito nella proprietà TargetControlID), è stato chiamato il metodo del web service, passando nel parametro contextKey il valore specificato nella prorietà DynamicContextKey (in questo caso il valore è fisso a font-weight:bold), e una volta ritornato il codice HTML, questo è stato inserito come innerHTML del controllo Panel2, e il Panel1 reso visibile.

In poche parole, tramite queste proprietà si ha la possibilità di popolare i controlli con maggiore dinamicità, e delegando la creazione di parte del contenuto HTML ad un metodo esterno. Questo in molti casi risulta veramente utile, permettondo con poche righe di codice di ottenere il comportamento/effetto voluto, e dimostrando per l'ennesima volta la flessibilità dei controlli contenuti negli AJAX Control Toolkit.

Tags: ,

ASP.NET AJAX | ASP .NET | .NET

Visualizzare e nascondere un PopupControlExtender da una funzione server side

by Andrea 20 July 2009 08:55

Qualcuno ha posto la domanda, se fosse possibile visualizzare o nascondere un popup creato con il PopupControlExtender direttamente da una funzione server side.

A differenza del ModalPopupExtender, PopupControlExtender il  non dispone di queste funzionalità server side, ma con poche righe di codice si può aggirare la problematica.

Per fare questo dobbiamo valorizzare la proprietà BehaviorID dell'extender:

   1: <ajax:PopupControlExtender 
   2:   ID="popup"
   3:   runat="server" 
   4:   BehaviorID="popupExt" ... />

utilizzando i metodi client showPopup e hidePopup, possiamo registrare uno script che si occupi di far visualizzare o nascondere il popup. Lo script utilizzerà la funzione $find per cercare l'extender all'interno del DOM della pagina, e successivamente verrano chiamate le funzioni showPopup oppure hidePopup esposte dallo script dell'extender.

Grazie al metodo RegisterStartupScript esposto dallo ScriptManager possiamo registrare lo script che immadiatamente verrà eseguito alla fine del postback.

   1: // visualizzare il popup
   2: ScriptManager.RegisterStartupScript(this, this.GetType(), "showPopup", "$find('popupExt').showPopup();", true);
   3:  
   4: // nascondere il popup
   5: ScriptManager.RegisterStartupScript(this, this.GetType(), "hidePopup", "$find('popupExt').hidePopup();", true);

 

Tags: ,

.NET | ASP .NET | ASP.NET AJAX

Seadragon Ajax

by andrea 13 March 2009 01:56

Leggendo il post di Mike Ormond sono venuto a conoscenza che Microsoft Live Labs  ha sfornato un nuovo progetto che ha dell'incredibile, dal nome Seadragon Ajax.

logo_color_seadragon_90 Questo progetto è una "replica" di Deep-Zoom, la funzionalità realizzata per silverlight che vi permette di gestire una foto grande quanto un campo da calcio, ed eseguire lo zoom fino al minimo particolare. Ma a differenza di Deep-Zoom questa è una funzionalità AJAX, che si appoggia completamente a JavaScript.

Ecco il link per vedere il progetto: http://livelabs.com/seadragon-ajax/

Tags: ,

ASP .NET | ASP.NET AJAX

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