Wie ordne ich Profilwerte zu?

110

Ich weiß nicht, was mir fehlt, aber ich habe Profileigenschaften in die Datei Web.config eingefügt, kann aber nicht auf Profile zugreifen. Element im Code oder erstellen Sie ein neues Profil.

zsharp
quelle

Antworten:

179

Ich hatte heute das gleiche Problem und habe viel gelernt.

In Visual Studio gibt es zwei Arten von Projekten: "Website-Projekte" und "Webanwendungsprojekte". Aus Gründen, die mir ein Rätsel sind, können Webanwendungsprojekte Profile nicht verwenden . direkt ... die stark typisierte Klasse wird nicht auf magische Weise aus der Datei Web.config für Sie generiert, daher müssen Sie Ihre eigene rollen.

Der Beispielcode in MSDN setzt voraus, dass Sie ein Website-Projekt verwenden, und fordert Sie auf, nur einen <profile>Abschnitt zu Ihrer Web.configund der Party mit Profile.Eigenschaft hinzuzufügen , dies funktioniert jedoch nicht in Webanwendungsprojekten.

Sie haben zwei Möglichkeiten, Ihre eigenen zu würfeln:

(1) Verwenden Sie den Web Profile Builder . Dies ist ein benutzerdefiniertes Tool, das Sie zu Visual Studio hinzufügen und das automatisch das benötigte Profilobjekt aus Ihrer Definition in Web.config generiert.

Ich habe mich dagegen entschieden, weil ich nicht wollte, dass mein Code von diesem zusätzlichen Tool zum Kompilieren abhängt, was zu Problemen für andere Personen führen könnte, die versucht haben, meinen Code zu erstellen, ohne zu bemerken, dass sie dieses Tool benötigen.

(2) Erstellen Sie Ihre eigene Klasse, aus ProfileBaseder Ihr benutzerdefiniertes Profil hervorgeht. Das ist einfacher als es scheint. Hier ist ein sehr sehr einfaches Beispiel, das ein Zeichenfolgenprofilfeld "FullName" hinzufügt:

In Ihrer web.config:

<profile defaultProvider="SqlProvider" inherits="YourNamespace.AccountProfile">

<providers>
     <clear />
     <add name="SqlProvider"
          type="System.Web.Profile.SqlProfileProvider"
          connectionStringName="sqlServerMembership" />
</providers>

</profile>

In einer Datei namens 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
    }
}

So legen Sie einen Profilwert fest:

AccountProfile.CurrentUser.FullName = "Snoopy";

Um einen Profilwert zu erhalten

string x = AccountProfile.CurrentUser.FullName;
Joel Spolsky
quelle
10
StackOverflow selbst verwendet keine Profile. Dieser Code ist wahrscheinlich nicht schnell genug für eine Site mit 1.000.000 Seitenaufrufen pro Tag. Ich habe an einem anderen Projekt gearbeitet, als ich das geschrieben habe.
Joel Spolsky
1
Es ist meine eigene Schuld, aber ich hatte eine ganze Weile Probleme, Eigenschaften festzulegen, nachdem ich CurrentUser aufgerufen hatte. Da CurrentUser jedes Mal eine neue Instanz instanziiert und zurückgibt, kann ich vorschlagen, sie stattdessen als Methode zu definieren? Ohne nachzudenken, schrieb ich Folgendes: AccountProfile.CurrentUser.FullName = "Snoopy"; AccountProfile.CurrentUser.OtherProperty = "ABC"; AccountProfile.CurrentUser.Save (); was nicht funktioniert. Es sollte sein: AccountProfile currentProfile = AccountProfile.CurrentUser; currentProfile.FullName = "Snoopy"; currentProfile.OtherProperty = "ABC"; currentProfile.Save ();
Jeremy Gruenwald
1
Besiegt diese Art nicht den ganzen Zweck von Profile? Sie können "Profile.MyProperty" nicht verwenden. Sie müssen Ihre eigene Klasse verwenden, die nicht auf jeder Seite so eingerichtet ist, wie Profile automatisch ist. Damit können Sie nur die Funktion Save () verwenden, ohne sie codieren zu müssen.
Mike K
7
Webanwendungsprojekte können Profile nicht verwenden.
Joel Spolsky
2
Wenn Sie versehentlich Profileigenschaften <profile ..><properties><add name="..">in der Webkonfiguration unter sowie in der AccountProfile-Klasse definieren, erhalten Sie die Meldung "Diese Eigenschaft wurde bereits definiert", die durch Entfernen der Eigenschaften in der web.config leicht behoben werden kann.
Zachary Scott
17

Webanwendungsprojekte können das ProfileCommon-Objekt weiterhin verwenden, jedoch nur zur Laufzeit. Der Code dafür wird einfach nicht im Projekt selbst generiert, sondern die Klasse wird von ASP.Net generiert und ist zur Laufzeit vorhanden.

Der einfachste Weg, um zum Objekt zu gelangen, ist die Verwendung eines dynamischen Typs, wie unten gezeigt.

Deklarieren Sie in der Datei Web.config die Profileigenschaften:

<profile ...
 <properties>
   <add name="GivenName"/>
   <add name="Surname"/>
 </properties>

Um dann auf die Eigenschaften zuzugreifen:

dynamic profile = ProfileBase.Create(Membership.GetUser().UserName);
string s = profile.GivenName;
profile.Surname = "Smith";

So speichern Sie Änderungen an Profileigenschaften:

profile.Save();

Das Obige funktioniert gut, wenn Sie mit dynamischen Typen vertraut sind und die fehlende Überprüfung der Kompilierungszeit und Intellisense nicht stören.

Wenn Sie dies mit ASP.Net MVC verwenden, müssen Sie zusätzliche Arbeit leisten, wenn Sie das dynamische Profilobjekt an Ihre Ansichten übergeben, da die HTML-Hilfsmethoden mit "Modell" -Objekten, die dynamisch sind, nicht gut funktionieren. Sie müssen statisch typisierten Variablen Profileigenschaften zuweisen, bevor Sie sie an HTML-Hilfsmethoden übergeben.

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

Wenn Sie eine benutzerdefinierte Profilklasse erstellen, wie Joel oben beschrieben hat, generiert ASP.Net weiterhin die ProfileCommon-Klasse, erbt jedoch von Ihrer benutzerdefinierten Profilklasse. Wenn Sie keine benutzerdefinierte Profilklasse angeben, erbt ProfileCommon von System.Web.Profile.ProfileBase.

Wenn Sie eine eigene Profilklasse erstellen, stellen Sie sicher, dass Sie in der Datei Web.config keine Profileigenschaften angeben, die Sie bereits in Ihrer benutzerdefinierten Profilklasse deklariert haben. Wenn Sie dies tun, gibt ASP.Net einen Compilerfehler aus, wenn versucht wird, die ProfileCommon-Klasse zu generieren.

Colivier
quelle
Ich kann das Profil nicht speichern. Der Fehler lautet: 'ProfileCommon' enthält keine Definition für 'Speichern'
Jimmy
2
@Salman: ProfileCommon wird von System.Web.Profile.ProfileBase abgeleitet, das über eine Save () -Methode verfügt. Bitte überprüfen Sie, ob Ihre Großschreibung korrekt ist. Siehe: msdn.microsoft.com/en-us/library/…
colivier
13

Das Profil kann auch in Webanwendungsprojekten verwendet werden. Die Eigenschaften können zur Entwurfszeit oder programmgesteuert in Web.config definiert werden. 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>

oder programmatisch, erstellen Sie den Profilabschnitt durch ein Instanziierung Profile und individuelle Eigenschaften zu schaffen unter Verwendung von ProfilePropertySettings und ProfilePropertySettingsColletion , von denen alle in System.Web.Configuration Namespace. Verwenden Sie System.Web.Profile.ProfileBase-Objekte, um diese Eigenschaften des Profils zu verwenden. Auf die Profileigenschaften kann nicht mit Profil zugegriffen werden . Syntax wie oben erwähnt, kann jedoch einfach durch Instanziieren einer ProfileBase und Verwenden von SetPropertyValue (" PropertyName ") und GetPropertyValue (" PropertyName ") wie folgt durchgeführt werden:

ProfileBase curProfile = ProfileBase.Create("MyName");

oder um auf das Profil des aktuellen Benutzers zuzugreifen:

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
quelle
1
Ich weiß nicht, warum das nicht 1000 Stimmen bekommen hat. Es ist sehr hilfreich.
pghcpa
Ich denke, niemand stört es, hier nach unten zu scrollen. Das ist Gold, danke Bede! Nachdem ich die oben genannten Daten gespeichert habe, kann ich von überall auf die Benutzerdaten zugreifen, indem ich einfach ein neues ProfileBaseObjekt erstelle und aufrufe GetPropertyValue("PropName").
Seebiscuit
Erstaunlich, das ist der einzige Weg, der für mich funktioniert. Thans Bede
Emanuel Pirovano
Erstes Problem, wie kann ich get in einer anderen Seite verwenden?
Emanuel Pirovano
8

Wenn Sie in Visual Studio ein neues Websiteprojekt erstellen, wird das von Profile zurückgegebene Objekt (automatisch) für Sie generiert. Wenn Sie ein Webanwendungsprojekt oder ein MVC-Projekt erstellen, müssen Sie Ihr eigenes rollen.

Das klingt wahrscheinlich schwieriger als es ist. Sie müssen Folgendes tun:

  • Erstellen Sie eine Datenbank mit aspnet_regsql.exe Dieses Tool wird zusammen mit dem .NET Framework installiert.
  • Schreiben Sie eine Klasse, die von ProfileGroupBase abgeleitet ist, oder installieren Sie den Web Profile Builder (WPB), der die Klasse aus der Definition in Web.Config für Sie generieren kann. Ich benutze WPB seit einer Weile und bis jetzt hat es getan, was von ihm erwartet wird. Wenn Sie viele Eigenschaften haben, kann die Verwendung von WPB viel Zeit sparen.
  • Stellen Sie sicher, dass die Verbindung zur Datenbank in Web.Config ordnungsgemäß konfiguriert ist.
  • Jetzt können Sie eine Instanz Ihrer Profilklasse erstellen (im Controller).
  • Wahrscheinlich benötigen Sie die Profileigenschaftswerte in Ihren Ansichten. Ich möchte das Profilobjekt selbst an die Ansicht weitergeben (keine einzelnen Eigenschaften).
Captain Sensible
quelle
3

Wenn Sie ein Webanwendungsprojekt verwenden, können Sie zur Entwurfszeit nicht sofort auf das Profilobjekt zugreifen. Hier ist ein Dienstprogramm, das es angeblich für Sie erledigt: http://weblogs.asp.net/joewrobel/archive/2008/02/03/web-profile-builder-for-web-application-projects.aspx . Persönlich verursachte dieses Dienstprogramm einen Fehler in meinem Projekt, sodass ich meine eigene Profilklasse rollte, um sie von ProfileBase zu erben. Es war überhaupt nicht schwer zu tun.

nshaw
quelle
3
System.Web.Profile - Hier ist ein Beispielcode: weblogs.asp.net/jgalloway/archive/2008/01/19/…
nshaw
2

Ich habe auch das gleiche Problem durchlaufen. Aber anstatt eine Klasse zu erstellen, die von ProfileBase erbt, habe ich den HttpContext verwendet.

Geben Sie die Eigenschaften in der Datei web.config wie folgt an: - ProfilePropertyWeb.config

Schreiben Sie nun den folgenden Code: -

Code hinter Profileigenschaften

Kompilieren Sie den Code und führen Sie ihn aus. Sie erhalten folgende Ausgabe: -

Ausgabe

Anil Purswani
quelle
1

Der Web Profile Builder hat bei mir hervorragend funktioniert. Die Klasse, die es generiert hat, enthält viel mehr als in Joels Beitrag beschrieben. Ob es tatsächlich benötigt oder nützlich ist, weiß ich nicht.

Auf jeden Fall für diejenigen, die nach einer einfachen Möglichkeit suchen, die Klasse zu generieren, aber keine externe Build-Tool-Abhängigkeit haben möchten, die Sie immer haben können

  • Verwenden Sie den Webprofil-Generator
  • lösche alle Spuren davon!
  • Verwenden Sie weiterhin die generierte Profilklasse

ODER (ungetestet, funktioniert aber möglicherweise nur)

  • Erstellen Sie ein Website- Projekt
  • Erstelle dein Element
  • schnappen die erzeugte Klasse und kopieren Sie über Ihre Web - Projekt Projekt

Wenn dieser zweite Ansatz funktioniert, kann mich jemand zum späteren Nachschlagen informieren

Simon_Weaver
quelle
1

Ich möchte nur Joel Spolskys Antwort hinzufügen

Ich habe seine Lösung implementiert und übrigens hervorragend gearbeitet - Cudos!

Für alle, die ein Benutzerprofil erhalten möchten, das nicht der angemeldete Benutzer ist, den ich verwendet habe:

web.config:

  <connectionStrings>
    <clear />
    <add name="LocalSqlConnection" connectionString="Data Source=***;Database=***;User Id=***;Password=***;Initial Catalog=***;Integrated Security=false" providerName="System.Data.SqlClient" />
  </connectionStrings>

und

<profile defaultProvider="SqlProvider" inherits="NameSpace.AccountProfile" enabled="true">
  <providers>
    <clear/>
    <add name="SqlProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="LocalSqlConnection"/>
  </providers>

Und dann meine benutzerdefinierte Klasse:

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(); }
        }
    }
}

Klappt wunderbar...

Super
quelle
0

Guter Eintrag,

Nur ein Hinweis in der web.config Wenn Sie das ererbte Attribut im Profilelement nicht angeben, müssen Sie jede einzelne Profileigenschaft innerhalb des Profilelements in der web.config wie folgt angeben

 <properties>
    <clear/>
    <add name="property-name-1" />
    <add name="property-name-2" />
    ..........

 </properties>
Indy
quelle