venerdì 20 maggio 2011
Riprendo un post trovato in rete per un esempio di come ottenere un postback su un url la cui querystring è stata modificata dinamicamente via codice.
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server"> 1:
2:
3: private String queryString;
4:
5: protected void Page_PreRender(object sender, EventArgs e) { 6: if (!String.IsNullOrEmpty(queryString)) { 7: Button1.PostBackUrl = queryString;
8: }
9: }
10:
11: protected void Page_Load(object sender, EventArgs e) { 12: queryString = "?foo=bar;a=b";
13: }
14:
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Change Response QueryString</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="PostBackWithQueryString" />
</div>
</form>
</body>
</html>
L’esempio è esattamente quello di Ting-hao Yang, autore del post citato.
In SharePoint 2010 è possibile visualizzare una lista o una document library in lingue diverse.
Per ciascuna delle lingue supportate dalla lista si può impostare il nome visualizzato (Title) delle colonne nella lingua corrente.
Per questo motivo se si vuole modificare il Title di un SPField da codice non sono più sufficienti (come in SharePoint 2007) le istruzioni:
myField.Title "My first field"
myField.Update()
Ma è ora necessario gestire le risorse associate al Title.
Confrontando la documentazione sulla proprietà Title di SharePoint 2007 e SharePoint 2010, e quindi arrivando alla pagina di descrizione del metodo SPUserResource.SetValueForUICulture ero arrivato alla conclusione che il nuovo codice fosse il seguente:
newField.TitleResource.SetValueForUICulture(newField.ParentList.ParentWeb.UICulture, "My first field")
newField.Update()
In pratica sto impostando il valore della risorsa per il titolo del campo, relativamente alla cultura di default del sito web (SPWeb.UICulture). In realtà la cosa non funziona correttamente, infatti andando poi sul sito da browser potremmo non trovare la modifica. Dico potremmo, perché in realtà il tutto dipende dalla culture corrente del thread che esegue quel codice: se la culture coincide con quella di default dell’oggetto SPWeb allora funziona, altrimenti no.
In realtà, in definitiva mi sono accorto che dipende fondamentalmente dalla Culture del thread: se questa è la stessa dell’oggetto SPWeb (o direi quella di cui vogliamo impostare il Title) allora posso usare anche lo stesso codice di SharePoinht 2007.
Conclusione, a mio modo di vedere il codice è il seguente:
Dim currentCulture As Globalization.CultureInfo = Threading.Thread.CurrentThread.CurrentUICulture
Threading.Thread.CurrentThread.CurrentUICulture = newField.ParentList.ParentWeb.UICulture
newField.Title = "My first field"
newField.Update()
Threading.Thread.CurrentThread.CurrentUICulture = currentCulture
venerdì 15 ottobre 2010
La GridView ASP.NET di default ha un problema (fra gli altri) legato alla visualizzazione nel caso di nessun elemento presente.
Il problema è che se non ci sono elementi nasconde l’header delle colonne.
Se si vuole che l’header resti si può seguire questo post: http://www.aspitalia.com/script/829/Mostrare-Header-GridView-ASP.NET-2.0-Mancanza-Dati.aspx
In pratica si deve estendere la classe GridView con una classe del tipo:
Public Class MyGridView
Inherits System.Web.UI.WebControls.GridView
Protected Overrides Function CreateRow( _
ByVal rowIndex As Integer, _
ByVal dataSourceIndex As Integer, _
ByVal rowType As System.Web.UI.WebControls.DataControlRowType, _
ByVal rowState As System.Web.UI.WebControls.DataControlRowState) As System.Web.UI.WebControls.GridViewRow
If (rowType = DataControlRowType.EmptyDataRow) Then
Return MyBase.CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)
Else
Return MyBase.CreateRow(rowIndex, dataSourceIndex, rowType, rowState)
End If
End Function
End Class
La nostra gliglia personalizzata puo’ così essere inserita nella pagina, inserendo ad esempio questa direttiva in testa:
<%@ Register TagPrefix="jvpo" Namespace="TestMyGridView" Assembly="TestMyGridView,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" %>
Quindi va dichiarato il tag EmptyDataTemplate:
<EmptyDataTemplate>Nessun elemento</EmptyDataTemplate>
In realtà il template per il caso di empty data non verrà mai renderizzato, in quanto verrà “sacrificato” per renderizzare l’header.
Però si potrà sostituirlo ad esempo con una label da visualizzare o nascondere a seconda dei casi.
mercoledì 19 maggio 2010
Se elaborando documenti e proprietà su SharePoint (2007) vi capitasse un errore come questo:
Microsoft.SharePoint.SPInvalidPropertyException: Date Times before 1/1/1970 are not supported.
Allora il problema potrebbe essere quello capitato anche a me oggi.
Il mio codice eseguiva l’upload di un documento su SharePoint e contestuale valorizzazione delle sue proprietà, il tutto tramite il metodo Add dell’oggetto SPFolder.
Se fra le proprietà c’è una data allora come valore è bene passare quello ottenuto dalla funzione SPUtility.CreateISO8601DateTimeFromSystemDateTime, ovvero una stringa con la rappresentazione UTC della data (formato ISO8601, ovvero yyyy-mm-ddThh:mm:ssZ).
Il codice corretto è il seguente.
' Crea una Hashtable delle proprietà
Dim myProps As New Hashtable()
Dim propName As String = "MyDatePropName"
' Imposta come valore una stringa con il formato UTC, ottenuta come segue:
Dim propValue As Object = SPUtility.CreateISO8601DateTimeFromSystemDateTime(New DateTime(1950, 1, 1))
' ... invece di: Dim propValue As Object = New DateTime(1950, 1, 1)
myProps.Add(propName, propValue)
' Recupera l'oggetto SPFolder dall'oggetto SPWeb corrente
Dim oFolder as SPFolder = myWeb.GetFolder(myFolderURL)
' Aggiunge il file con le proprietà
Dim objDestFile as SPFile = objDestFolder.Files.Add(myFolderURL & "/" & myFileName, myDocumentSourceStream, myProps)
Due osservazioni:
- Passando la data nuda e cruda (il datetime) si ha un errore per date inferiori all’1/1/1970, mentre per date successive funziona.
- Passando una stringa che non sia una data non succede nulla… nel senso che non c’è eccezione, il documento viene caricato e la proprietà resta vuota
Note: Grazie a Gabriele per i suggerimenti!
venerdì 14 maggio 2010
Può capitare con Vista o Windows 7 che facendo doppio click da Esplora Risorse su un file di progetto o di solution di Visual Studio non succeda nulla. Ovvero non parta Visual Studio.
Se capita, allora il motivo potrebbe essere la concomitanza di questi 2 fattori:
1) La UAC è attiva
2) Visual Studio è impostato per partire sempre As Administrator
Se è così allora si può fare una delle 2 cose seguenti:
- Togliere il flag “As Administrator” a Visual Studio, oppure
- Metterlo a “Microsoft Visual Studio Version Selector”
L’eseguibile “Microsoft Visual Studio Version Selector” è l’utility di Visual Studio associata all’estensione dei file di progetto e di solution ed ha il compito di capire di che versione di visual studio è il file e di avviare quella versione passandogli il file.
Per cui il selector parte, vede che il file sln è di VS2008, ad esempio, cerca quindi di avviare VS2008. Se questo però ha il flag As Administrator allora l’avvio non riesce.
Per impostare lo stesso flag sul selector bisogna individuarlo: si trova nella cartella (Drive C o quello che è):
[C]:\Program Files (x86)\Common Files\microsoft shared\MSEnv
L’eseguibile si chiama VSLauncher.exe, fare click con il tasto destro e aprire le Proprietà. Nel pannello Compatibility impostare il flag Run this program as an administrator:

Mi è capitato esattamente quanto descritto in questo post, ovvero ho aggiunto una service reference ad un progetto (Console), ho fatto tasto destro sul file app.config per richiamare l’editor della configurazione WCF, ma il menu contestuale “Edit WCF Configuration” non era disponibile:
Allora seguendo le indicazioni del post di cui sopra ho fatto click sul menu Tools|WCF Service Configuration Editor, in questo modo ho aperto l’editor, da qui ho aperto il file app.config (File|Open), l’ho chiuso ed il menu è finalmente comparso:

lunedì 26 aprile 2010
Tramite .Net Remoting è possibile creare un oggetto su un server tramite una chiamata dal client e fargli fare qualche cosa.
Normalmente lato server l’operazione viene eseguita con le credenziali dell’applicazione ospitante, ovvero il server. Se si vuole che venga eseguita con le credenziali del client si può procedere come segue.
Per primo creiamo una dll che sarà poi condivisa dal client e dal server, che eseguirà l’operazione desiderata. Creiamo per questo un progetto libreria di classi con il seguente codice:
using System;
using System.Security.Principal;
namespace CodeGuru.RemotingSample
{
/// <remarks>
/// Sample object to demonstrate the use of .NET remoting and IPC.
/// </remarks>
public class SampleObject : MarshalByRefObject
{
/// <summary>
/// Constructor
/// </summary>
public SampleObject()
{
}
/// <summary>
/// Return a hello message
/// </summary>
/// <returns>Hello world message</returns>
public string HelloWorld()
{
return "Hello World " + System.Security.Principal.WindowsIdentity.GetCurrent().Name;
}
}
}
Ora creiamo il progetto server. Facciamo un’applicazione console con la reference alla System.Runtime.Remoting e con il seguente codice:
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace CodeGuru.RemotingSample
{
/// <remarks>
/// Sample server to demonstrate the use of secure .NET Remoting.
/// </remarks>
public class SampleRemotingServer
{
public static void Main()
{
// Setup the configuration parameters through a dictionary
IDictionary properties = new Hashtable();
properties.Add("port", 9977);
properties.Add("secure", true);
properties.Add("impersonate", true);
// Create an instance of a channel
TcpServerChannel serverChannel =
new TcpServerChannel(properties, null);
ChannelServices.RegisterChannel(serverChannel, true);
// Register as an available service with the name HelloWorld
RemotingConfiguration.RegisterWellKnownServiceType(typeof(SampleObject),
"HelloWorldUri" ,
WellKnownObjectMode.Singleton);
Console.WriteLine("Listening on {0}", serverChannel.GetChannelUri());
Console.WriteLine("Press the enter key to exit...");
Console.ReadLine();
}
}
}
Infine creiamo il progetto client. Facciamo un’applicazione console con la reference alla System.Runtime.Remoting e con il seguente codice:
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace CodeGuru.RemotingSample
{
/// <remarks>
/// Sample client to demonstrate the use of secure .NET Remoting.
/// </remarks>
public class SampleRemotingClient
{
public static void Main()
{
// Setup the configuration parameters through a dictionary
IDictionary properties = new Hashtable();
properties.Add("secure", true);
properties.Add("connectionTimeout", 5000);
properties.Add("tokenImpersonationLevel", "Impersonation");
// Create a channel for communicating w/ the remote object
TcpClientChannel clientChannel =
new TcpClientChannel(properties, null);
ChannelServices.RegisterChannel(clientChannel, true);
// Create an instance of the remote object
RemotingConfiguration.RegisterWellKnownClientType(
typeof(SampleObject),
"Tcp://MyServerName:9977/HelloWorldUri");
SampleObject sample = new SampleObject();
Console.WriteLine("{0}", sample.HelloWorld());
Console.WriteLine("Press the enter key to exit...");
Console.ReadLine();
}
}
}
Eseguiamo il server, poi eseguiamo il client lanciandolo con le credenziali di un utente di test per verificare il risultato.
Fonte: http://www.developer.com/net/net/article.php/3522466/Improved-NET-Remoting-Part-2-Secure-TCP.htm
Lo stesso risultato lo si può ottenere tramite file di configurazione (app.config):
Lato Server
app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp"
port="9977"
secure="true"
impersonate="true"
authenticationMode="ImpersonateCallers"/>
</channels>
<service>
<wellknown mode="SingleCall" type="MyServer.SampleObject, MyServer"
objectUri="SampleObjectURI" />
</service>
</application>
</system.runtime.remoting>
</configuration>
codice per la lettura del file di configurazione:
System.Runtime.Remoting.RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, True)
Lato Client
app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp"
port="8888"
secure="true"
tokenImpersonationLevel="impersonation"/>
</channels>
<client>
<wellknown type="MyServer2.SampleObject, MyServer2" url="Tcp://MyServerName:9977/SampleObjectURI" />
</client>
</application>
</system.runtime.remoting>
</configuration>
codice per la lettura del file di configurazione:
System.Runtime.Remoting.RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, True)
Fonte http://nettecharticles.blogspot.com/2008/06/netremotingimpersonate-client-user-on.html
giovedì 22 aprile 2010
Quando si “stampa” una data bisogna fare attenzione al formato che si utilizza.
Ad esempio io faccio ampio uso del formato italiano tramite il seguente codice:
Dim dateAsString As String = Now.ToString("dd/MM/yyyy")
Purtroppo quel codice non fa esattamente quello che mi aspetto.
Infatti il carattere / ha un significato, ovvero è il separatore di sistema usato per le date. Ovvero, se nei miei settings regionali di sistema la data è scritta ad esempio così yyyy-MM-dd, allora quel ToString di cui sopra produce dd-MM-yyyy, ovvero mette il giorno, poi il mese, poi l’anno come ho specificato, ma li separa con il separatore di sistema, e non con il caratettere /.
Sono certo che tutti lo sapevano benissimo e che io sono uno dei pochi ingenui che invece non lo sapeva, ma per quegli altri pochi come me lo voglio segnalare, in modo da evitare questo errore in futuro.
Il codice corretto è il seguente:
Dim dateAsString As String = Now.ToString("dd\/MM\/yyyy")
In pratica si deve usare il carattere di escape per far mantenere il nostro /.
Lo stesso discorso vale per il ToString di un Time, in cui il carattere : viene sostituito con quello di sistema, e quindi si deve scrivere:
Dim timeAsString As String = Now.ToString("hh\:mm\:ss")
In generale le stringhe andrebbero messe fra apice o doppio apice, ad esempio:
Dim dateAsString As String = Now.ToString("dd""/""MM""/""yyyy")
Trovate tutti i dettagli a questo link.
PS:
La proprietà CustomFormat del DateTimePicker non segue questa politica, ma funziona con un meccanismo a metà, ovvero la data la posso scrivere così “dd/MM/yyyy - HH:mm” o anche così “dd/MM/yyyy’ - ‘HH:mm”, ma non così “dd\/MM\/yyyy”… insomma \ e : non sono caratteri speciali, l’escape (\) non esiste, le stringhe possono o meno andare fra apice (‘).
Non voglio indagare oltre… :(
giovedì 8 aprile 2010
Se abbiamo compilato un eseguibile in modalità Any CPU e lo lanciamo su una macchina a 64bit questo verrà ovviamente eseguito a 64bit.
Se però ci servisse poterlo avviare a 32bit possiamo sfruttare il tool CorFlags.exe.
Basta avviare il prompt dei comandi di Visual Studio e poi digitare:
corflags.exe /32bit+ filename.exe
Per ripristinare il comportamento normale:
corflags.exe /32bit- filename.exe
[Fonte]
giovedì 25 marzo 2010
Oggi mi è capitata una cosa strana.
Accedendo, tramite browser, ad una applicazione web residente su una mia macchina virtuale ho inserito le credenziali di un utente di test.
A quel punto accedendo a quella macchina ero sempre l’utente di test.
La cosa strana è che ero quell’utente sempre e per ogni tipo di operazione, comprese applicazioni client che si collegavano ad un web service su quella macchina.
Onestamente non so con certezza cos’è che ha provocato questo deciso “cambio di persona”, ma non sapevo più come ripristinare le mie vecchie credenziali.
Alla fine ho trovato le benedette credenziali di quell’utente di test nel mio Windows Vault (Windows 7, Pannello di controllo, Users Accounts, Credential Manager, sotto Windows Credentials), le ho rimosse ed ho riacquistato le mia identità!
[fonte http://en.kioskea.net/forum/affich-35879-to-disable-auto-login-network-share-folders]