Jak przypisać wartości profilu?

110

Nie wiem, czego mi brakuje, ale dodałem właściwości profilu w pliku Web.config, ale nie mogę uzyskać dostępu do profilu. Pozycja w kodzie lub utwórz nowy profil.

zsharp
źródło

Odpowiedzi:

179

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, ProfileBaseaby 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;
Joel Spolsky
źródło
10
Sam StackOverflow nie używa profili. Ten kod prawdopodobnie nie jest wystarczająco szybki dla witryny z 1 000 000 odsłon dziennie. Kiedy to pisałem, pracowałem nad innym projektem.
Joel Spolsky
1
To moja wina, ale przez długi czas zmagałem się z ustawieniem właściwości po wywołaniu CurrentUser. Ponieważ CurrentUser tworzy instancję i zwraca nowe wystąpienie za każdym razem, czy mogę zamiast tego zasugerować zdefiniowanie go jako metody? Bez zastanowienia napisałem to: AccountProfile.CurrentUser.FullName = "Snoopy"; AccountProfile.CurrentUser.OtherProperty = "ABC"; AccountProfile.CurrentUser.Save (); co nie działa. Powinien to być: AccountProfile currentProfile = AccountProfile.CurrentUser; currentProfile.FullName = "Snoopy"; currentProfile.OtherProperty = "ABC"; currentProfile.Save ();
Jeremy Gruenwald
1
Czy nie jest to sprzeczne z celem profilu? Nie możesz używać "Profile.MyProperty", musisz użyć własnej klasy domowej, która nie jest ustawiana na każdej stronie tak jak Profil automatycznie. Wszystko to pozwala korzystać z funkcji Save () bez konieczności jej kodowania.
Mike K,
7
Projekty aplikacji sieci Web nie mogą używać profilu.
Joel Spolsky
2
Jeśli przypadkowo zdefiniujesz właściwości profilu w konfiguracji sieciowej <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.
Zachary Scott
17

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.

colivier
źródło
nie mogę zapisać profilu. błąd to: „ProfileCommon” nie zawiera definicji „zapisz”
Jimmy
2
@Salman: ProfileCommon pochodzi z System.Web.Profile.ProfileBase, który ma metodę Save (). Sprawdź, czy wielkie litery są prawidłowe. Zobacz: msdn.microsoft.com/en-us/library/…
colivier
13

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();
Bede Amarasekara
źródło
1
Nie wiem, dlaczego nie otrzymało to 1000 głosów. Jest to niezwykle pomocne.
pghcpa
Chyba nikt nie zawraca sobie głowy przewijaniem tutaj. To jest złoto, dzięki Bede! Po zapisaniu powyższych danych mogę uzyskać dostęp do danych użytkownika z dowolnego miejsca, po prostu tworząc nowy ProfileBaseobiekt i wywołując GetPropertyValue("PropName")?
seebiscuit
Niesamowite, to jedyny sposób, który działa dla mnie. Thans Bede
Emanuel Pirovano
Pierwszy problem, w jaki sposób mogę użyć Get na innej stronie?
Emanuel Pirovano
8

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:

  • Utwórz bazę danych przy użyciu aspnet_regsql.exe To narzędzie jest instalowane wraz z platformą .NET.
  • Napisz klasę, która pochodzi z ProfileGroupBase lub zainstaluj program Web Profile Builder (WPB), który może wygenerować klasę na podstawie definicji w Web.Config. Używam WPB od jakiegoś czasu i do tej pory robił to, czego się od niego oczekuje. Jeśli masz wiele nieruchomości, korzystanie z WPB może zaoszczędzić sporo czasu.
  • Upewnij się, że połączenie z bazą danych jest poprawnie skonfigurowane w programie Web.Config.
  • Teraz możesz utworzyć instancję klasy swojego profilu (w kontrolerze)
  • Prawdopodobnie będziesz potrzebować wartości właściwości profilu w swoich widokach. Lubię przekazywać do widoku sam obiekt profilu (nie poszczególne właściwości).
Kapitanie Sensible
źródło
3

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.

nshaw
źródło
3
System.Web.Profile - oto przykładowy kod: weblogs.asp.net/jgalloway/archive/2008/01/19/...
nshaw
2

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: - ProfilePropertyWeb.config

Teraz napisz następujący kod: -

Kod za właściwościami profilu

Skompiluj i uruchom kod. Otrzymasz następujące dane wyjściowe: -

Wynik

Anil Purswani
źródło
1

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

  • użyj narzędzia do tworzenia profili internetowych
  • usuń wszystkie ślady!
  • nadal używaj wygenerowanej klasy profilu

LUB (nieprzetestowane, ale może po prostu działać)

  • utworzyć projekt witryny internetowej
  • stwórz swój żywioł
  • przystawki wygenerowany klasę i skopiować go do swojej strony internetowej projektu projektu

jeśli to drugie podejście zadziała, niech ktoś da mi znać na przyszłość

Simon_Weaver
źródło
1

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...

Skopać tyłek
źródło
0

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>
indy
źródło