Odpowiedzi:
Miałem dzisiaj ten sam problem i wiele się nauczyłem.
W programie Visual Studio istnieją dwa rodzaje projektów - „Projekty witryn sieci Web” i „Projekty aplikacji sieci Web”. Z powodów, które są dla mnie kompletną tajemnicą, projekty aplikacji internetowych nie mogą korzystać z profilu. bezpośrednio ... silnie wpisana klasa nie jest generowana w magiczny sposób z pliku Web.config, więc musisz utworzyć własną.
Przykładowy kod w MSDN zakłada, że korzystasz z projektu witryny sieci Web i mówi ci, aby po prostu dodać <profile>
sekcję do swojej właściwościWeb.config
i współpracować z nią , ale to nie działa w projektach aplikacji sieci Web.Profile.
Masz dwie możliwości wyboru własnego:
(1) Użyj narzędzia do tworzenia profili internetowych . Jest to niestandardowe narzędzie dodawane do programu Visual Studio, które automatycznie generuje potrzebny obiekt profilu z definicji w pliku Web.config.
Zdecydowałem się tego nie robić, ponieważ nie chciałem, aby mój kod zależał od tego dodatkowego narzędzia do kompilacji, co mogło spowodować problemy u kogoś innego, gdy próbował zbudować mój kod, nie zdając sobie sprawy, że potrzebuje tego narzędzia.
(2) Utwórz własną klasę, która pochodzi od, ProfileBase
aby reprezentować Twój niestandardowy profil. To jest łatwiejsze niż się wydaje. Oto bardzo, bardzo prosty przykład, który dodaje pole profilu ciągu „FullName”:
W twoim web.config:
<profile defaultProvider="SqlProvider" inherits="YourNamespace.AccountProfile">
<providers>
<clear />
<add name="SqlProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionStringName="sqlServerMembership" />
</providers>
</profile>
W pliku o nazwie 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
}
}
Aby ustawić wartość profilu:
AccountProfile.CurrentUser.FullName = "Snoopy";
Aby uzyskać wartość profilu
string x = AccountProfile.CurrentUser.FullName;
<profile ..><properties><add name="..">
w klasie AccountProfile, a także w klasie AccountProfile, otrzymasz komunikat „Ta właściwość została już zdefiniowana”, którą można łatwo naprawić, usuwając właściwości w pliku web.config.
Projekty aplikacji sieci Web mogą nadal używać obiektu ProfileCommon, ale tylko w czasie wykonywania. Kod po prostu nie jest generowany w samym projekcie, ale klasa jest generowana przez ASP.Net i jest obecna w czasie wykonywania.
Najprostszym sposobem dotarcia do obiektu jest użycie typu dynamicznego, jak pokazano poniżej.
W pliku Web.config zadeklaruj właściwości profilu:
<profile ...
<properties>
<add name="GivenName"/>
<add name="Surname"/>
</properties>
Następnie, aby uzyskać dostęp do właściwości:
dynamic profile = ProfileBase.Create(Membership.GetUser().UserName);
string s = profile.GivenName;
profile.Surname = "Smith";
Aby zapisać zmiany we właściwościach profilu:
profile.Save();
Powyższe działa dobrze, jeśli czujesz się komfortowo w korzystaniu z typów dynamicznych i nie przeszkadza Ci brak sprawdzania czasu kompilacji i inteligencji.
Jeśli używasz tego z ASP.Net MVC, musisz wykonać dodatkową pracę, jeśli przekażesz obiekt profilu dynamicznego do swoich widoków, ponieważ metody pomocnicze HTML nie działają dobrze z obiektami „modelowymi”, które są dynamiczne. Będziesz musiał przypisać właściwości profilu do statycznie wpisanych zmiennych przed przekazaniem ich do metod pomocniczych 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
Jeśli utworzysz niestandardową klasę profilu, jak opisał Joel powyżej, ASP.Net nadal będzie generować klasę ProfileCommon, ale będzie dziedziczyć z niestandardowej klasy profilu. Jeśli nie określisz niestandardowej klasy profilu, ProfileCommon będzie dziedziczyć po System.Web.Profile.ProfileBase.
Jeśli tworzysz własną klasę profilu, upewnij się, że nie określasz właściwości profilu w pliku Web.config, które zostały już zadeklarowane w niestandardowej klasie profilu. Jeśli to zrobisz, ASP.Net wyświetli błąd kompilatora podczas próby wygenerowania klasy ProfileCommon.
Profil może być również używany w projektach aplikacji sieci Web. Właściwości można zdefiniować w pliku Web.config w czasie projektowania lub programowo. W 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>
lub Programowo utwórz sekcję profilu, tworząc wystąpienie ProfileSection i tworząc indywidualne właściwości przy użyciu ProfilePropertySettings i ProfilePropertySettingsColletion , z których wszystkie znajdują się w przestrzeni nazw System.Web.Configuration. Aby użyć tych właściwości profilu, użyj obiektów System.Web.Profile.ProfileBase. Nie można uzyskać dostępu do właściwości profilu za pomocą profilu. jak wspomniano powyżej, ale można to łatwo zrobić, tworząc wystąpienie ProfileBase i używając SetPropertyValue (" PropertyName ") i GetPropertyValue {" PropertyName ") w następujący sposób:
ProfileBase curProfile = ProfileBase.Create("MyName");
lub aby uzyskać dostęp do profilu bieżącego użytkownika:
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
obiekt i wywołując GetPropertyValue("PropName")
?
Podczas tworzenia nowego projektu witryny sieci Web w programie Visual Studio obiekt zwracany przez profil zostanie (automatycznie) wygenerowany. Podczas tworzenia projektu aplikacji sieci Web lub projektu MVC będziesz musiał utworzyć własny.
Prawdopodobnie brzmi to trudniej niż w rzeczywistości. Musisz wykonać następujące czynności:
Jeśli używasz projektu aplikacji sieci Web, nie możesz uzyskać dostępu do obiektu profilu w czasie projektowania po wyjęciu z pudełka. Oto narzędzie, które podobno robi to za Ciebie: http://weblogs.asp.net/joewrobel/archive/2008/02/03/web-profile-builder-for-web-application-projects.aspx . Osobiście to narzędzie spowodowało błąd w moim projekcie, więc skończyło się na rolowaniu mojej własnej klasy profilu, aby dziedziczyć z ProfileBase. Nie było to wcale trudne.
Przewodnik MSDN dotyczący tworzenia klasy niestandardowej (aka metoda Joela):
http://msdn.microsoft.com/en-us/magazine/cc163624.aspx
Miałem też ten sam problem. Ale zamiast tworzyć klasę, która dziedziczy po ProfileBase, użyłem HttpContext.
Określ właściwości w pliku web.config w następujący sposób: -
Teraz napisz następujący kod: -
Skompiluj i uruchom kod. Otrzymasz następujące dane wyjściowe: -
Web Builder profilu pracował wielki dla mnie. Klasa, którą wygenerował, zawiera o wiele więcej niż opisano w poście Joela. Nie wiem, czy jest rzeczywiście potrzebny lub przydatny.
W każdym razie dla tych, którzy szukają łatwego sposobu na wygenerowanie klasy, ale nie chcą mieć zależności od zewnętrznego narzędzia do kompilacji, zawsze możesz
LUB (nieprzetestowane, ale może po prostu działać)
jeśli to drugie podejście zadziała, niech ktoś da mi znać na przyszłość
Chcę tylko dodać do odpowiedzi Joela Spolsky'ego
Wdrożyłem jego rozwiązanie, przy okazji działając znakomicie - Cudos!
Dla każdego, kto chce uzyskać profil użytkownika, który nie jest zalogowanym użytkownikiem, którego użyłem:
web.config:
<connectionStrings>
<clear />
<add name="LocalSqlConnection" connectionString="Data Source=***;Database=***;User Id=***;Password=***;Initial Catalog=***;Integrated Security=false" providerName="System.Data.SqlClient" />
</connectionStrings>
i
<profile defaultProvider="SqlProvider" inherits="NameSpace.AccountProfile" enabled="true">
<providers>
<clear/>
<add name="SqlProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="LocalSqlConnection"/>
</providers>
A potem moja klasa niestandardowa:
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(); }
}
}
}
Działa jak marzenie...
Wspaniały post,
Tylko uwaga w pliku web.config, jeśli nie określisz atrybutu inherit w elemencie profilu, będziesz musiał określić każdą indywidualną właściwość profilu wewnątrz elementu profile w pliku web.config, jak poniżej
<properties>
<clear/>
<add name="property-name-1" />
<add name="property-name-2" />
..........
</properties>