In questo post c'e' indicata una soluzione "built-in" per impostare i permessi su un task creato all'interno di un workflow disegnato con VS2008.
La soluzione alternativa sarebbe quella di scrivere del codice custom in un eventhandler.
Molto utile.
Segnalo questo post in cui vengono indicate, tramite esempi, le best practice per quanto riguarda il "dispose" di SPSite e SPWeb.
Chi sviluppa in Sharepoint sa benissimo quanto la non corretta "chiusura" di questi oggetti possa provocare dei memory leaks che alla lunga possono incidere negativamente sulle prestazioni.
Ieri mi sono visto la sessione su MVC(PC21 ASP.NET MVC: A New Framework for Building Web Applications) tenuta allo scorso PDC 2008 da Phil Haack.
Fino a questo momento non avevo avuto tempo per poter approfondire il discorso MVC, pur cercando di seguire i post di Scott Guthrie e Simone, ma devo dire che questa sessione mi ha dato veramente tanti spunti di ispirazione.
Certo, con tutti gli avvertimenti del caso tra cui il fatto che MVC non sostituisce web form ma rappresenta un approccio utile in alcuni scenari.
Consiglio a tutti di guardarsi questa registrazione.
NB. per la prima volta mi sono visto una sessione registrata non dal portatile o dal monitor, ma direttamente dal mio televisore lcd 32 passando in streaming attaverso la PS3.Spettacolare, era come essere li :)
del.icio.us Tags:
ASP.NET,
MVC
In questo sintetico post, che voglio utilizzare più che tutto come promemoria personale, evidenzio alcuni tips utili a chi sviluppa applicazioni Sharepoint.
In particolare si tratta di alcune note che riguardano lo svilippo di List Templates con l'esigenza di creazione automatica della lista durante l'attivazione della feature:
- Creare due features distinte, una per il template della lista(ListTemplate) ed una per l'istanza della lista(ListInstance). Eventualmente avrò anche una terza feature dove creo i
content types ed i fields.
- Per velocizzare lo sviluppo del template posso utilizzare VSeWSS 1.2, tramite il progetto List Definition.
Personalmente creo il template con VSeWSS 1.2, ma migro poi i files che mi servono su un progetto di tipo "empty feature" creato tramite STSDEV 1.3, in quanto quest'ultimo mi da la massima flessibilità nel gestire la struttura della feature.
- Nella feature di definizione del template di lista posso evitare di portarmi dietro i file aspx (editform, dispform, newform, etc...) generati da VSeWSS 1.2 se questi non sono diversi da quelli di default. Per questo occore modificare il file Schema.xml nel modo seguente:
- nelle Views, per ogni View aggiungo l'attributo SetupPath="pages\viewpage.aspx"
- nelle Forms, per ogni Form aggiungo l'attributo SetupPath="pages\form.aspx"
- Nella feature che definisce l'istanza della lista devo specificare TemplateType e Id altrimenti la lista non viene creata.
Inoltre devo specificare il valore di FeatureId uguale all' id della feature che definisce il template di lista. <ListInstance
Id="MyTaskListInstance"
FeatureId="70398CC4-A413-11DD-8204-52BE56D89593"
Title="My Tasks"
Url="Lists/MyTasks"
TemplateType="107" />
Sembra strano, ma se dovete impostare una query CAML per Sharepoint usando l' Object Model e la query contiene più di due espressioni in "<And>" oppure "<Or>", avrete di ritorno uno strano errore che potrebbe bloccarvi per molto.
Ho trovato fortunamente questo utilissimo post dove viene anche descritto un possibile workaround.
Completo solo il post in questione aggiungendo che nella query CAML devo avere al massimo due espressioni per ogni "<Or>" o "<And>", ma all'interno della stessa "<Where>" è possibile aggiungere tutti gli "<And>" e gli "<Or>" che vogliamo.
Quindi non è necessario creare annidamenti ricorsivi ed è possibile rendere l'intera espressione CAML più leggibile e semplice.
Es. abbiamo una query con 6 "Or" che per evitare l'errore dovrebbe essere scritta nel modo seguente:
<Where>
<Or>
<Eq><FieldRef Name='Title'/><Value Type='Text'>***</Value></Eq>
<Eq><FieldRef Name='ProductCode'/><Value Type='Text'>***</Value></Eq>
</Or>
<Or>
<Eq><FieldRef Name='ProductDescription'/><Value Type='Text'>***</Value></Eq>
<Eq><FieldRef Name='ID'/><Value Type='Number'>***</Value></Eq>
</Or>
</Where>
Spero sia utile.
Durante la creazione di form è spesso necessario implementare un meccanismo che consenta di avvisare l'utente che i dati nella form sono cambiati ed è quindi necessario procedere al salvataggio.
Questo succede per esempio quando ho form complesse fatte a tab ed il passaggio da un tab all'altro presuppone che un messaggio avvisi l'utente che ci sono dei campi variati nel tab che si sta abbandonando ed è quindi necessario aggiornarlo.
Ipotizziamo uno scenario in cui utilizziamo ASP.NET ed Ajax dove avremo un UpdatePanel con al suo interno il TabContainer dell' AjaxControlToolkit. Ogni TabContainer conterrà la propria FormView con tutti i controlli di input necessari:
...
<ajaxToolkit:TabContainer runat="server" ID="TabContainerControl" OnClientActiveTabChanged="clientActiveTabChanged">
<ajaxToolkit:TabPanel ID="Tab1" runat="server" HeaderText="Tab 1">
<ContentTemplate>
<div id="Tab1">
<!--...ascx, formview, ...-->
</div>
</ContentTemplate>
</ajaxToolkit:TabPanel>
...
Prima di tutto agganciamo l'evento client OnClientActiveTabChanged del TabContainer ad una funzione javascript dove:
1) verificherò che qualcosa nel tab da cui provengo è cambiato
2) se ci sono dati variati e l'utente conferma, aggiorno il tab da cui provengo
function clientActiveTabChanged(sender, args) {
var activeIndex = sender.get_activeTabIndex();
if (tabChanged) {
if (window.confirm('Sono stati modificati dei dati.Prima di passare alla sezione successiva è necessario salvare le modifiche.\n\nClicca \'OK\' per procedere con il salvataggio.')) {
__doUpdateTab(exActiveIndex);
}
}
tabChanged = false;
exActiveIndex = activeIndex;
}
La funzione __doUpdateTab si occupa di effettuare una chiamata di tipo postback dove verrà gestito, lato server, l'aggiornamento del tab.La variabile javascript tabChanged indica se ci sono state modifiche in un tab.
La cosa interessante ed anche la più importante di tutto il post è l'utilizzo di JQuery per generare velocemente gli eventi di notifica su tutti i controlli di tipo input per ciascun tab:
jQuery(document).ready(
function() {
jQuery('#Tab1 :input').bind('change',
function(event) {
tabChanged = true;
});
});
Con queste poche righe di javascript, utilizzando JQuery, abbiamo agganciato l'evento client di change su tutti i controlli di tipo input che ci sono all'interno di un div che ha per id Tab1, che nel nostro caso corrisponde al div contenitore del primo TabPanel.
IMPORTANTE: se si usa tutto quando descritto all'interno di un UpdatePanel(per esempio posizionato all'interno di una master page) succede che dopo un qualsiasi postback il javascript relativo agli eventi di change non risponde più. E' quindi necessario registrare tutti i javascripts sopra direttamente da codice, utilizzando le procedure corrette.
NB. ho preso spunto da questo post di Rick Strahl.
Per chi sviluppa packages con Sql Server Integration Services , segnalo questo utile articolo del supporto Microsoft dove vengono descritti i problemi realtivi alla security che si potrebbero avere quando si effettua il deploy e l'esecuzione dei packages su una macchina differente da quella di sviluppo.
L'approccio che preferisco personalmente è quello di avvalermi di file xml di configurazione e lasciare i package con il ProtectionLevel impostato su DontSaveSensitive, anche se questa scelta dipende molto dalla tipologia di progetto e dalla configurazione di produzione che si avrà poi a disposizione.
del.icio.us Tags:
SSIS,
Sql Server 2005
SubSonic è un tool open(ci sono i sorgenti inclusi nel package di installazione) che fornisce un framework di accesso ai dati basato sul pattern ActiveRecords.
Risulta quindi una soluzione molto utile, veloce e semplice da utilizzare in progetti in cui non è un requisito l'avere una architettura per forza di cose "loosely coupled"(anche se da questo post l'autore dimostra come anche con SubSonic posso comunque realizzare architetture basate per esempio sul pattern Repository e mantenendo le indipendenze tra i vari layers).
L'ultima versione, la 2.1, presenta un bug durante l'esecuzione di stored procedures che abbiano parametri di tipo decimal con impostati lo "scale"(es. decimal(18,2)).
Qui c'e' il post relativo alla segnalazione, con relativa conferma di fix.
Purtroppo non ho trovato i sorgenti di queste ultime modifiche, che sembra saranno rilasciati in una futura versione 2.1.1.
La soluzione più veloce per me è stata quella di caricare con VS2008 i sorgenti di SubSonic(caricati come dicevo all'inizio durante l'installazione) e cercare di trovare il rimedio al bug in questione. Ecco dove correggere(la parte in bold), nella classe SubSonic.SqlDataProvider:
private static void AddParams(SqlCommand cmd, QueryCommand qry)
{
if(qry.Parameters != null)
{
foreach(QueryParameter param in qry.Parameters)
{
SqlParameter sqlParam = new SqlParameter(param.ParameterName, Utility.GetSqlDBType(param.DataType));
sqlParam.Direction = param.Mode;
//output parameters need to define a size
//our default is 50
if(sqlParam.Direction == ParameterDirection.Output || sqlParam.Direction == ParameterDirection.InputOutput)
sqlParam.Size = param.Size;
if(param.Precision != null)
sqlParam.Precision = Convert.ToByte(param.Precision);
if(param.Scale != null)
sqlParam.Scale = Convert.ToByte(param.Scale);
//fix for NULLs as parameter values
if(param.ParameterValue == null || Utility.IsMatch(param.ParameterValue.ToString(), "null"))
sqlParam.Value = DBNull.Value;
else if(param.DataType == DbType.Guid)
{
string paramValue = param.ParameterValue.ToString();
if(!String.IsNullOrEmpty(paramValue))
{
if(!Utility.IsMatch(paramValue, SqlSchemaVariable.DEFAULT))
sqlParam.Value = new Guid(param.ParameterValue.ToString());
}
else
sqlParam.Value = DBNull.Value;
}
else
sqlParam.Value = param.ParameterValue;
cmd.Parameters.Add(sqlParam);
}
}
}
E' sufficiente ricompilare ed utilizzare il nuovo assembly.
del.icio.us Tags:
Subsonic
Volevo segnalare due post interessanti per chi sviluppa web parts per Sharepoint(WSS 3.0 / MOSS 2007) ed ha la necessita di dover personalizzare la sezione di editing della web part.
EditorPart 101 descrive in breve come essere subito operativi e realizzare la propria EditorPart.
Creating custom editor parts for a SharePoint webpart , a complemento del primo post, oltre a descriviere come realizzare EditorPart illustra anche la soluzione ad alcuni problemi di sviluppo che hanno fatto perdere ore all'autore del post e risparmiare tempo a noi che leggiamo il suo prezioso post.
Share, share, share... lo metterei subito dopo lo slogan developer, developer, developer...
del.icio.us Tags:
Sharepoint,
Web Parts