Risposte:
Oggi ho avuto lo stesso problema e ho imparato molto.
Esistono due tipi di progetto in Visual Studio: "Progetti sito Web" e "Progetti applicazione Web". Per motivi che per me sono un mistero completo, i progetti di applicazioni Web non possono utilizzare il profilo. direttamente ... la classe fortemente tipizzata non viene generata magicamente per te dal file Web.config, quindi devi lanciarne una tua.
Il codice di esempio in MSDN presuppone che si sta utilizzando un Sito Web del progetto, e ti dicono solo di aggiungere una <profile>
sezione per la vostra Web.config
e festa con Profile.
proprietà , ma questo non funziona in Web progetti di applicazioni.
Hai due scelte per rotolare il tuo:
(1) Utilizza il Web Profile Builder . Si tratta di uno strumento personalizzato aggiunto a Visual Studio che genera automaticamente l'oggetto Profile necessario dalla definizione in Web.config.
Ho scelto di non farlo, perché non volevo che il mio codice dipendesse da questo strumento aggiuntivo per la compilazione, il che avrebbe potuto causare problemi a qualcun altro lungo la linea quando hanno provato a costruire il mio codice senza rendersi conto che avevano bisogno di questo strumento.
(2) Crea la tua classe che deriva da ProfileBase
per rappresentare il tuo profilo personalizzato. Questo è più facile di quanto sembri. Ecco un esempio molto semplice che aggiunge un campo di profilo stringa "FullName":
Nel tuo web.config:
<profile defaultProvider="SqlProvider" inherits="YourNamespace.AccountProfile">
<providers>
<clear />
<add name="SqlProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionStringName="sqlServerMembership" />
</providers>
</profile>
In un file denominato AccountProfile.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Profile;
using System.Web.Security;
namespace YourNamespace
{
public class AccountProfile : ProfileBase
{
static public AccountProfile CurrentUser
{
get { return (AccountProfile)
(ProfileBase.Create(Membership.GetUser().UserName)); }
}
public string FullName
{
get { return ((string)(base["FullName"])); }
set { base["FullName"] = value; Save(); }
}
// add additional properties here
}
}
Per impostare un valore di profilo:
AccountProfile.CurrentUser.FullName = "Snoopy";
Per ottenere un valore di profilo
string x = AccountProfile.CurrentUser.FullName;
<profile ..><properties><add name="..">
così come nella classe AccountProfile, otterrai un messaggio "Questa proprietà è già stata definita", facilmente risolvibile rimuovendo le proprietà nel web.config.
I progetti di applicazioni Web possono ancora utilizzare l'oggetto ProfileCommon ma solo in fase di esecuzione. Il codice per esso non viene generato nel progetto stesso, ma la classe è generata da ASP.Net ed è presente in fase di esecuzione.
Il modo più semplice per arrivare all'oggetto è usare un tipo dinamico come mostrato di seguito.
Nel file Web.config dichiarare le proprietà del profilo:
<profile ...
<properties>
<add name="GivenName"/>
<add name="Surname"/>
</properties>
Quindi per accedere alle proprietà:
dynamic profile = ProfileBase.Create(Membership.GetUser().UserName);
string s = profile.GivenName;
profile.Surname = "Smith";
Per salvare le modifiche alle proprietà del profilo:
profile.Save();
Quanto sopra funziona bene se ti senti a tuo agio nell'usare i tipi dinamici e non ti importa della mancanza di controllo in fase di compilazione e intellisense.
Se lo usi con ASP.Net MVC devi fare del lavoro aggiuntivo se passi l'oggetto profilo dinamico alle tue viste poiché i metodi helper HTML non funzionano bene con oggetti "modello" che sono dinamici. Dovrai assegnare le proprietà del profilo alle variabili tipizzate staticamente prima di passarle ai metodi di supporto HTML.
// model is of type dynamic and was passed in from the controller
@Html.TextBox("Surname", model.Surname) <-- this breaks
@{ string sn = model.Surname; }
@Html.TextBox("Surname", sn); <-- will work
Se crei una classe di profilo personalizzata, come Joel descritto sopra, ASP.Net genererà comunque la classe ProfileCommon ma erediterà dalla tua classe di profilo personalizzato. Se non specifichi una classe di profilo personalizzata, ProfileCommon erediterà da System.Web.Profile.ProfileBase.
Se crei la tua classe profilo, assicurati di non specificare le proprietà del profilo nel file Web.config che hai già dichiarato nella classe del profilo personalizzato. Se si esegue ASP.Net, verrà visualizzato un errore del compilatore quando si tenta di generare la classe ProfileCommon.
Il profilo può essere utilizzato anche nei progetti di applicazioni Web. Le proprietà possono essere definite in Web.config in fase di progettazione oa livello di programmazione. In Web.config:
<profile enabled="true" automaticSaveEnabled="true" defaultProvider="AspNetSqlProfileProvider">
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="TestRolesNProfiles"/>
</providers>
<properties>
<add name="FirstName"/>
<add name="LastName"/>
<add name ="Street"/>
<add name="Address2"/>
<add name="City"/>
<add name="ZIP"/>
<add name="HomePhone"/>
<add name="MobilePhone"/>
<add name="DOB"/>
</properties>
</profile>
oppure A livello di codice , creare la sezione del profilo creando un'istanza di ProfileSection e creando singole proprietà utilizzando ProfilePropertySettings e ProfilePropertySettingsColletion , tutti nello spazio dei nomi System.Web.Configuration. Per utilizzare queste proprietà del profilo, utilizzare System.Web.Profile.ProfileBase Objects. Non è possibile accedere alle proprietà del profilo con il profilo. sintassi come menzionato sopra, ma può essere facilmente eseguito creando un'istanza di ProfileBase e utilizzando SetPropertyValue (" PropertyName ") e GetPropertyValue {" PropertyName ") come segue:
ProfileBase curProfile = ProfileBase.Create("MyName");
oppure per accedere al profilo dell'utente corrente:
ProfileBase curProfile = ProfileBase.Create(System.Web.Security.Membership.GetUser().UserName);
curProfile.SetPropertyValue("FirstName", this.txtName.Text);
curProfile.SetPropertyValue("LastName", this.txtLname.Text);
curProfile.SetPropertyValue("Street", this.txtStreet.Text);
curProfile.SetPropertyValue("Address2", this.txtAdd2.Text);
curProfile.SetPropertyValue("ZIP", this.txtZip.Text);
curProfile.SetPropertyValue("MobilePhone", txtMphone.Text);
curProfile.SetPropertyValue("HomePhone", txtHphone.Text);
curProfile.SetPropertyValue("DOB", txtDob.Text);
curProfile.Save();
ProfileBase
oggetto e invocando GetPropertyValue("PropName")
?
Quando crei un nuovo progetto di sito Web in Visual Studio, l'oggetto restituito da Profile verrà generato (automaticamente) per te. Quando crei un progetto di applicazione Web o un progetto MVC, dovrai eseguire il rollio personale.
Questo probabilmente suona più difficile di quello che è. Devi fare quanto segue:
Se si utilizza un progetto di applicazione Web, non è possibile accedere all'oggetto Profile in fase di progettazione immediatamente. Ecco un'utilità che presumibilmente lo fa per te: http://weblogs.asp.net/joewrobel/archive/2008/02/03/web-profile-builder-for-web-application-projects.aspx . Personalmente, quell'utilità ha causato un errore nel mio progetto, quindi ho finito per eseguire il rollio della mia classe di profilo per ereditare da ProfileBase. Non è stato affatto difficile.
Procedura dettagliata MSDN per la creazione di una classe personalizzata (ovvero il metodo di Joel):
http://msdn.microsoft.com/en-us/magazine/cc163624.aspx
Stavo anche affrontando lo stesso problema. Ma invece di creare una classe che eredita da ProfileBase, ho usato HttpContext.
Specificare le proprietà nel file web.config come segue: -
Ora scrivi il seguente codice: -
Compila ed esegui il codice. Otterrai il seguente output: -
Il Web Profile Builder ha funzionato alla grande per me. La classe che ha generato contiene molto di più rispetto a quanto descritto nel post di Joel. Se sia effettivamente necessario o utile non lo so.
Ad ogni modo per coloro che cercano un modo semplice per generare la classe, ma non vogliono avere una dipendenza da uno strumento di compilazione esterno, puoi sempre
OPPURE (non testato ma potrebbe funzionare)
se questo secondo approccio funziona, qualcuno può farmelo sapere per riferimento futuro
Voglio solo aggiungere alla risposta di Joel Spolsky
Ho implementato la sua soluzione, lavorando brillantemente btw - Cudos!
Per chiunque desideri ottenere un profilo utente che non sia l'utente connesso che ho usato:
web.config:
<connectionStrings>
<clear />
<add name="LocalSqlConnection" connectionString="Data Source=***;Database=***;User Id=***;Password=***;Initial Catalog=***;Integrated Security=false" providerName="System.Data.SqlClient" />
</connectionStrings>
e
<profile defaultProvider="SqlProvider" inherits="NameSpace.AccountProfile" enabled="true">
<providers>
<clear/>
<add name="SqlProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="LocalSqlConnection"/>
</providers>
E poi la mia classe personalizzata:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Profile;
using System.Web.Security;
namespace NameSpace
{
public class AccountProfile : ProfileBase
{
static public AccountProfile CurrentUser
{
get
{
return (AccountProfile)
(ProfileBase.Create(Membership.GetUser().UserName));
}
}
static public AccountProfile GetUser(MembershipUser User)
{
return (AccountProfile)
(ProfileBase.Create(User.UserName));
}
/// <summary>
/// Find user with matching barcode, if no user is found function throws exception
/// </summary>
/// <param name="Barcode">The barcode to compare against the user barcode</param>
/// <returns>The AccountProfile class with matching barcode or null if the user is not found</returns>
static public AccountProfile GetUser(string Barcode)
{
MembershipUserCollection muc = Membership.GetAllUsers();
foreach (MembershipUser user in muc)
{
if (AccountProfile.GetUser(user).Barcode == Barcode)
{
return (AccountProfile)
(ProfileBase.Create(user.UserName));
}
}
throw new Exception("User does not exist");
}
public bool isOnJob
{
get { return (bool)(base["isOnJob"]); }
set { base["isOnJob"] = value; Save(); }
}
public string Barcode
{
get { return (string)(base["Barcode"]); }
set { base["Barcode"] = value; Save(); }
}
}
}
Funziona come un fascino ...
Ottimo post,
Solo una nota sul web.config se non specifichi l'attributo inherit nell'elemento del profilo dovrai specificare ogni proprietà del profilo individuale all'interno dell'elemento del profilo sul web.config come sotto
<properties>
<clear/>
<add name="property-name-1" />
<add name="property-name-2" />
..........
</properties>