460 likes | 534 Views
Windows SharePoint 2003 Products & Technologies – Sviluppare Web Part. Marco Bellinaso Senior trainer & consultant Code Architects S.r.l. Web: http://www.codearchitects.com E-mail: mbellinaso@codearchitects.com. Biografia. Consulenza, sviluppo e training con Code Architects Srl
E N D
Windows SharePoint 2003 Products & Technologies–Sviluppare Web Part Marco Bellinaso Senior trainer & consultant Code Architects S.r.l. Web: http://www.codearchitects.com E-mail: mbellinaso@codearchitects.com
Biografia • Consulenza, sviluppo e training con Code Architects Srl • Collaboratore di Visual Basic & .NET Journal, Computer Programming, MSDN Magazine e ASP Today • Coautore di “ASP.NET Website Programming”, “Fast Track ASP.NET” e “Visual C# .NET: a Guide for VB6 Developers” (Wrox Press) • Sviluppatore di UGI SharePoint (www.ugisharepoint.it) • Sviluppatore dei siti *2TheMax (www.dotnet2themax.com) (www.dotnet2themax.it ) e-mail: mbellinaso@codearchitects.com
Agenda • Concetti base • Generazione manuale di HTML • Riutilizzo di controlli ASP.NET • Proprietà • Deployment • Debug • Web part avanzate • Custom Tool Part • Connessioni
Architettura ASP.NET Page • Le Web Part sono controlli ASP.NET server-side che vengono inseriti all’interno di pagine o zone eseguite nel contesto di SharePoint • Forniscono caratteristiche comuni, offerte dal framework • Titolo, bordi, stato (minimizzato ecc.) • Supporto per drag & drop • Proprietà shared o per utente • I controlli sulla pagina sono determinati da record del DB dei contenuti • Implementano interfacce standard per comunicare le une con le altre Controlli ASP.NET che ereditano dalla classe base WebPart, che a sua volta eredita da System.Web.UI.Control Web Part zone
Sviluppo in VS.NET • Microsoft fornisce un template per VS.NET 2003, scaricabile separatamente, chiamato “Web Part Library” • WebPart1.cs: scheletro per la classe della Web Part • WebPart1.dwp: file XML che descrive la Web Part (nome, descrizione) e contiene valori di default per alcune proprietà • AssemblyInfo.cs: specifica versione, il file .snk per lo strong name, ecc. • Manifest.xml: file XML che contiene un riferimento a tutti i file necessari • “References” contiene un riferimento a Microsoft.SharePoint dll
Classe base • Browser Rendering • Non è possibile fare l’override del metodo Render()della classe base • La classe base lo usa per creare il bordo, il titolo e il menu della Web Part • Le Web Part custom devono implementare l’override di RenderWebPart() per fare l’output dell’HTML del proprio contenuto
Request ASPX Page WebPart.Render() ASP.NET starts page render Web Part CustomPart.RenderWebPart() Response Classe base • Browser Rendering
Classe base • Rendering per client diversi da browser • L’interfaccia IDesignTimeHtmlProvider viene usata per ottenere il rendering della Web Part quando questa viene inserita in client diversi dal browser Internet. Es: FrontPage 2003 • IDesignTimeHtmlProvider consiste in un singolo metodo: GetDesignTimeHtml • Non è implementata di default
Classe base • Override di eventi • I seguenti metodi della classe base sono marcati come sealed, e non se ne può fare l’override: • OnInit , OnDataBinding, OnLoad, OnPreRender, OnUnload • Ci si può iscrivere agli eventi relativi: this.Load += new EventHandler (myLoadEvent);
Proprietà • Introduzione • Le Web Part, come gli altri controlli web, possono esporre proprietà custom che permettono di personalizzarne il comportamento e l’aspetto • Due tipi di proprietà: • Proprietà della classe base • Proprietà custom • Tutte le proprietà devono poter essere serializzabili tramite l’XmlSerializer • Gli attributi della proprietà ne possono cambiare il comportamento
Proprietà • Attributi supportati • Browsable (.Net) • Category (.Net) • Description (.Net) • - Ecc. – • FriendlyName (Web Part Framework) • HtmlDesigner (Web Part Framework) • WebPartStorage (Web Part Framework) • - Ecc. -
Proprietà • Modifica e salvataggio dei valori delle proprietà • Le proprietà vengono serializzate e salvate nel database • Due contesti di salvataggio • Shared • Personal • Il tipo di storage è controllato dall’attributo WebPartStorage: • WebPartStorage = Storage.Shared • WebPartStorage = Storage.Personal • WebPartStorage = Storage.None • I valori di default delle proprietà possono anche essere salvati nel file .dwp <WebPart> ... <Text xmlns=”MyWebPart”>Hello World!</Text> </WebPart>
Proprietà [Browsable(true), Category("Miscellaneous"), DefaultValue(defaultText), WebPartStorage(Storage.Personal), FriendlyName("Text"),Description("Text Property")] public string Text { get { return _text; } set { _text = value; } } protected override void RenderWebPart(HtmlTextWriter output) { output.Write(SPEncode.HtmlEncode(this.Text)); }
Rendering • Due metodi per eseguire il rendering • Il codice HTML viene generato tutto manualmente, all’interno di RenderWebPart • Pro: controllo totale sul codice generato • Contro: codifica molto lunga, non si sfruttano alcuni dei vantaggi più interessanti di ASP.NET • Creare dei controlli ASP.NET all’interno di CreateChildControls, ed eseguirne il rendering in RenderWebPart • Pro: La generazione di output complesso (es: griglie) è incapsulata all’interno delle classi di .NET • Pro: Si possono sfruttare eventi • Contro: in alcuni casi personalizzazioni avanzate richiedono più sforzo di una completa codifica manuale • Soluzione ideale: scrivere Web Part sotto forma di user control, ma...gli user control non sono attualmente supportati!
Rendering di controlli ASP.NET protected override void CreateChildControls() { btnSubmit = new Button(); btnSubmit.Text = "Somma"; btnSubmit.Click += new EventHandler(btnSubmit_Click); this.Controls.Add(btnSubmit); txtOp1 = new TextBox(); this.Controls.Add(txtOp1); txtOp2 = new TextBox(); this.Controls.Add(txtOp2); lblResult = new Label(); this.Controls.Add(lblResult); } public void btnSubmit_Click(object sender, EventArgs e) { lblResult.Text = "La somma è " + (Convert.ToInt32(txtOp1.Text)+Convert.ToInt32(txtOp2.Text)).ToString(); } protected override void RenderWebPart(HtmlTextWriter output) { output.Write("Operando 1: "); txtOp1.RenderControl(output); output.Write("Operando 2: "); txtOp2.RenderControl(output); btnSubmit.RenderControl(output); lblResult.RenderControl(output); }
Deployment • Deployment manuale • Compilazione con strong name (opzionale) • Copia dell’assembly nel folder /bin • Registrazione come “safe control” • Preparazione e copia/importazione del file .dwp • Deployment “semi-automatico” • Compilazione con strong name (opzionale) • Preparazione del file .dwp • Preparazione di un file manifest.xml • Preparazione di un pacchetto .cab • Installazione del pacchetto .cab con stsadm.exe
Deployment manuale • Compilare un assembly con strong name significa dargli un nome univoco, per versioni diverse. Assembly con lo stesso nome possono coesistere senza essere rinominati • Creare un file con le chiavi pubblica/privata sn.exe - k c:\keypair.snk • Modificare AssemblyInfo.cs, impostando gli attributi AssemblyVersion e AssemblyKeyFile • [assembly: AssemblyKeyFile(@"c:\keypair.snk")] • [assembly: AssemblyVersion("1.0.0.0")]
Deployment manuale • Registrazione come safe control • Aggiungere una nuova entry all’interno di <SafeControls> in web.config (senza “a capo”) • Il file .dwp di descrizione <SafeControl Assembly="WebCalcWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e0cc4e02e14341c1" Namespace="WebCalcWebPart“ TypeName="*" Safe="True" /> <?xml version="1.0" encoding="utf-8"?> <WebPart xmlns="http://schemas.microsoft.com/WebPart/v2" > <Title>WebCalc</Title> <Description>Impressive beb-based calculator</Description> <Assembly>WebCalcWebPart</Assembly> <TypeName>WebCalcWebPart.WebCalc</TypeName> <!– Valori di default per proprietà... --> </WebPart>
Deployment con stsadm.exe • Stsadm.exe può installare una o più Web Part presenti all’interno di un pacchetto .cab. Si occupa di: • Copiare gli assembly in /bin • Copia i file .dwp di descrizione in /wpcatalog • Copia eventuali file di risorse in /wpresources • Registra le Web Part come safe control • Copiare il file .cab all’interno del database di configurazione
Deployment con stsadm.exe • Stsadm.exe installa un pacchetto .cab che deve contenere: • Gli assembly .dll • I file .dwp di descrizione • Eventuali file di risorse • Un file manifest.xml che elenca tutti i file • Il pacchetto .cab può essere creato da VS.NET • Setup & Deployment Projects \ CAB Project • Basta includere “Primary Output” e “Content Files” Stsadm.exe –o addwppack –filename path_to_webpart.cab • Opzione –globalInstall: installa gli assembly nella GAC • pieni permessi di esecuzione -> deployment facilitato, ma meno sicuro • Opzione –force: sovrascrive la Web Part, se già presente
Deployment • Contenuto del file manifest.xml file <?xml version="1.0"?> <WebPartManifest xmlns="http://schemas.microsoft.com/WebPart/v2/Manifest"> <Assemblies> <Assembly FileName="WebCalcWebPart.dll"> <ClassResources> <ClassResource FileName="Resource.jpg"/> </ClassResources> <SafeControls> <SafeControl Namespace="WebCalcWebPart" TypeName="*" /> </SafeControls> </Assembly> </Assemblies> <DwpFiles> <DwpFile FileName="WebCalc.dwp"/> </DwpFiles> </WebPartManifest>
Debugging • Apportare delle modifiche a web.config • debug="true" in <compilation> • mode="RemoteOnly" o mode="Off" in <customErrors> • CallStack="true" nel tag <SafeMode> • Eseguire il debug di una Web Part: • Compilare, registrare e importare la Web Part in una pagina (può essere richiesto un riavvio di IIS – iisreset) • Impostare i breakpoint • Da VS.NET selezionare “Tools / Debug Processes...” oppure “Debug / Processes...” e selezionare “w3wp.exe” • Se w3wp.exe non è elencato, assicurarsi che l’opzione “Show system processes” sia selezionata, e caricare una pagina del browser per assicurarsi che il processo parta • Caricare la pagina nel browser...l’esecuzione si fermerà al breakpoint
Risorse • SmartPart • Web part che permette di “hostare” User Control • Permette di scrivere Web Part in modo molto più immediato, riutilizzando controlli già pronti • Gli user control possono essere testati all’interno di una normale pagina ASP.NET, prima di essere aggiunti ad una pagina di SharePoint • Debug molto semplificato • Permette allo user control referenziato di esporre proprietà e di supportare connessioni, mediante implementazione di sue interfacce http://www.smartpart.info
Risorse • STSAdmWin (Microsoft) • Interfaccia grafica per stsadm.exe • Bastato file file .xml di definizioni dei comandi • Facilmente estendibile, se necessario http://download.microsoft.com/download/1/6/8/16887e30-897e-4d6c-afce-3e85a43e6eaa/stsadmWin-2go.zip
Risorse • WPPackager (Microsoft) • Crea un pacchetto .msi autoinstallante • L’utente può scegliere se installare la Web Part nella GAC • Disinstallazione standard • Può creare nuovi permission-set (utile se il pacchetto non viene installato nella GAC) • Necessita di: • Il file manifest.xml, e tutti gli altri file della libreria • Un “packaging file”, che indica proprietà del file MSI risultante, politiche di sicurezza, e il nome del manifest da includere http://www.microsoft.com/downloads/details.aspx?FamilyId=0FDA5912-C136-4B44-911A-011ADFCC66E3&displaylang=en
Tool Part • Introduzione • Sono anch’essi controlli web, usati per aggiungere funzionalità al tool pane standard • Diverse dalle Web Part • Non possono essere spostate • Poche proprietà nella classe base • Non c’è supporto per lo storage di proprietà • Rendering solo all’interno del tool pane • Il processo di rendering è simile a quello delle Web Part • Non si può fare l’override di ToolPart.Render() • Bisogna fare l’override di ToolPart.RenderToolPart()
Tool Part • Metodi importanti • ToolPart.ApplyChanges() • Chiamato quando l’utente clicca Apply / Ok dalla pagina delle proprietà • ToolPart.CancelChanges() • Chiamato quando l’utente clicca Cancel dalla pagina delle proprietà • ToolPart.SyncChanges() • Chiamato quando serve un refresh della toolpart (ad es. quando un’altra toolpart salva le sue proprietà) • WebPart.GetToolParts() • Metodo della Web Part base, usato per associare le toolpart della Web Part
ToolPart – RenderToolPart() protected override void RenderToolPart(HtmlTextWriter output) { //get a reference to the parent Web Part SpecialSayHello parentWebPart = (SpecialSayHello) this.ParentToolPane.SelectedWebPart; //print the text box HTML output.Write("Enter your age: "); output.Write("<input name='" + inputName); output.Write("' type='text' value='" + SPEncode.HtmlEncode(parentWebPart.Age) + "'>"); } public override void ApplyChanges() { //get a reference to the parent Web Part SpecialSayHello parentWebPart = (SpecialSayHello) this.ParentToolPane.SelectedWebPart; //set the Age property of the parent Web Part based on Form Input parentWebPart.Age = Page.Request.Form[inputName]; }
ToolPart – GetToolParts() public override ToolPart[] GetToolParts() { //the array that holds instances of all ToolParts ToolPart[] toolparts = new ToolPart[3]; //standard toolparts creation WebPartToolPart wptp = new WebPartToolPart(); CustomPropertyToolPart custom = new CustomPropertyToolPart(); //the toolpart that we are adding creation AgeDisplayerToolPart ad = new AgeDisplayerToolPart(); toolparts[0] = wptp; toolparts[1] = custom; toolparts[2] = ad; return toolparts; }
Connessioni • Le connessioni permettono a Web Part separate (ed indipendenti) di scambiarsi dati di tipo base: Cell, Row, List ecc. • Implementazione di un set di interfacce standard • Due Web Part possono essere collegate da browser o FrontPage
Parent / Child Master / Detail Data entry and filtering Connessioni – Scenari
Connessioni – Interfacce • ICellProvider, ICellConsumer • IRowProvider, IRowConsumer • IListProvider, IListConsumer • IFilterProvider, IFilterConsumer • IParametersOutProvider, IParametersOutConsumer • IParametersInProvider, IParametersInConsumer
Connessioni – Cell Consumer/Provider diagram Web Part Framework ICellProvider Events CellProviderInit() CellReady() Event Handlers CellConsumerInit() ICellConsumer Events CellConsumerInit() Event Handlers CellProviderInit() CellReady()
Connessioni – Codice • EnsureInterfaces() • RegisterInterface() • CanRunAt() • PartCommunicationConnect() • PartCommunicationInit() • Solleva eventi Init (Es. CellProviderInit) • PartCommunicationMain() • Solleva gli eventi rimanenti (Es. CellReady)
Connessioni – Codice • Creare la classe che implementa le interfacce • Dichiarare gli eventi public class CellProvider : WebPart, ICellProvider { // ... } // CellProviderInit Event – // provides the field name and display field name to the consumer Web Part public event CellProviderInitEventHandler CellProviderInit; // CellReady Event - occurs whenever a cell is selected or updated public event CellReadyEventHandler CellReady;
Connessioni – Codice • Fare l’override del metodo EnsureInterfaces, e al suo interno chiamare RegisterInterface • Fare l’override del metodo CanRunAt • public override void EnsureInterfaces() • { • RegisterInterface("MyCellProviderInterface_WPQ_", "ICellProvider", • WebPart.UnlimitedConnections, ConnectionRunAt.ServerAndClient, • this, • "CellProviderInterface_WPQ_", • "Fornisce singolo valore a...", • "Fornisce ad un’altra Web Part il valore inserito nella textbox" • ); • } • public override ConnectionRunAt CanRunAt() • { • return ConnectionRunAt.ServerAndClient; • }
Connessioni – Codice • Fare l’override di PartCommunicationConnect • Notifica la Web Part che è stata creata una connessione • public override void PartCommunicationConnect( • string interfaceName, WebPart connectedPart, • string connectedInterfaceName, ConnectionRunAt runAt) • { • if (runAt == ConnectionRunAt.Client) • { • _runAtClient = true; • return; • } • EnsureChildControls(); // create the Web Part's controls • // Check if this is my particular cell interface • if (interfaceName == "MyCellProviderInterface_WPQ_") • _cellConnectedCount++; // count connections • }
Connessioni – Codice • Opzionale: override del metodo PartCommunicationInit, responsabile del sollevamento degli eventi di inizializzazione • public override void PartCommunicationInit() • { • if(_cellConnectedCount > 0) • { • if (CellProviderInit != null) • { • CellProviderInitEventArgs args = • new CellProviderInitEventArgs(); • args.FieldName = _cellName; • args.FieldDisplayName = _cellDisplayName; • CellProviderInit(this, args); • } • } • }
Connessioni – Codice • Opzionale: override del metodo PartCommunicationMain, responsabile del sollevamento degli altri eventi (es: CellReady) public override void PartCommunicationMain() { if (_cellConnectedCount > 0) { if (CellReady != null) { CellReadyEventArgs args = new CellReadyEventArgs(); args.Cell = this.ctlInputBox.Text; CellReady(this, args); } } }
Connessioni – Codice • Implementare gli appropriati gestori di evento, a seconda del tipo di interfaccia che si sta implementando public void CellConsumerInit(object sender, CellConsumerInitEventArgs cellConsumerInitEventArgs) { // This is where the Provider part could see what type of "Cell" // the Consumer was expecting/requesting. }
Connessioni – Codice • Fare l’override del metodo CreateChildControls protected override void CreateChildControls() { // crea il bottone di submit e registra il suo evento Click ctlSubmitButton = new Button(); ctlSubmitButton.ID = “SubmitButton"; ctlSubmitButton.Text = “Submit"; this.Controls.Add(ctlSubmitButton); ctlSubmitButton.Click += new EventHandler(SubmitButtonClicked); // crea il controllo textBox ctlInputBox = new TextBox(); ctlInputBox.ID = “InputBox"; this.Controls.Add(ctlInputBox); cellName = “InputBox"; cellDisplayName = "InputBox Cell"; }
Connessioni – Codice • Fare l’override del metodo RenderWebPart protected override void RenderWebPart(HtmlTextWriter output) { EnsureChildControls(); if (_runAtClient) { // Render client connection code if needed } else { if (_cellConnectedCount > 0) { this.ctlInputBox.RenderControl(output); this.ctlSubmitButton.RenderControl(output); } else output.Write(“No connection is set-up."); } }
Estendere il framework • Property Builder • Pagine web (.htm) caricate all’interno di dialog del browser • Collegato alle proprietà che ne vogliono fare uso tramite attributo HtmlDesignerAttribute • Es: Color picker; picture picker, file picker, date picker (questi sono già implementati, e disponibili tramite costanti del tipo BrowserBuilderType.*)
Estendere il framework • Menu della Web Part • Possibilità di aggiungere voci custom al context menu delle proprie Web Part • Override del metodo CreateWebPartMenu() • Si possono aggiungere elementi MenuItem alla collezione WebPartMenu.MenuItems, associandovi del codice javascript client-side, e un gestore di evento server-side • Si possono referenziare le voci di menu built-in, per nasconderle, disabilitarle, cambiarle di posizione, o associarvi un comportamento diverso
Il futuro • ASP.NET 2.0 include il supporto per Web Part • Possibilità di scrivere Web Part come User Control! • Supporto per le Web Part per SharePoint già esistenti • La prossima versione di SharePoint sarà basata su ASP.NET 2.0 e potrà sfruttare i vantaggi delle sue Web Part • Microsoft intende rilasciare un aggiornamento per SharePoint che consenta il supporto delle Web Part di ASP.NET 2.0 prima di SharePoint 3.0
Domande? http://www.ugisharepoint.it http://www.dotnet2themax.it/blog