¿Cómo asignar valores de perfil?

Respuestas:

179

Hoy tuve el mismo problema y aprendí mucho.

Hay dos tipos de proyectos en Visual Studio: "Proyectos de sitios web" y "Proyectos de aplicaciones web". Por razones que son un completo misterio para mí, los proyectos de aplicaciones web no pueden usar Profile. directamente ... la clase fuertemente tipada no se genera mágicamente para usted desde el archivo Web.config, por lo que debe crear la suya propia.

El código de ejemplo en MSDN supone que está utilizando una Página Web del proyecto, y se dice que acaba de agregar una <profile>sección a su Web.configy fiesta en la Profile.propiedad , pero que no lo hace el trabajo en proyectos de aplicación Web.

Tienes dos opciones para tirar el tuyo:

(1) Utilice Web Profile Builder . Esta es una herramienta personalizada que agrega a Visual Studio que genera automáticamente el objeto de perfil que necesita a partir de su definición en Web.config.

Elegí no hacer esto, porque no quería que mi código dependiera de esta herramienta adicional para compilar, lo que podría haber causado problemas a alguien más en el futuro cuando intentaron construir mi código sin darse cuenta de que necesitaban esta herramienta.

(2) Cree su propia clase que se derive de ProfileBasepara representar su perfil personalizado. Esto es más fácil de lo que parece. Aquí hay un ejemplo muy muy simple que agrega un campo de perfil de cadena "FullName":

En su web.config:

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

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

</profile>

En un archivo llamado 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
    }
}

Para establecer un valor de perfil:

AccountProfile.CurrentUser.FullName = "Snoopy";

Para obtener un valor de perfil

string x = AccountProfile.CurrentUser.FullName;
Joel Spolsky
fuente
10
StackOverflow en sí no usa perfiles. Es probable que este código no sea lo suficientemente rápido para un sitio con 1,000,000 de páginas vistas al día. Estaba trabajando en otro proyecto cuando escribí esto.
Joel Spolsky
1
Es mi culpa, pero luché durante bastante tiempo con la configuración de propiedades después de llamar a CurrentUser. Dado que CurrentUser crea una instancia y devuelve una nueva instancia cada vez, ¿puedo sugerir que se defina como un método? Sin pensarlo, escribí esto: AccountProfile.CurrentUser.FullName = "Snoopy"; AccountProfile.CurrentUser.OtherProperty = "ABC"; AccountProfile.CurrentUser.Save (); que no funciona. Debe ser: AccountProfile currentProfile = AccountProfile.CurrentUser; currentProfile.FullName = "Snoopy"; currentProfile.OtherProperty = "ABC"; currentProfile.Save ();
Jeremy Gruenwald
1
¿No anula esto todo el propósito de Profile? No puedes usar "Profile.MyProperty", tienes que usar tu propia clase de cosecha propia, que no está configurada en todas las páginas de la forma en que Profile está automáticamente. Todo lo que hace es permitirle utilizar la función Guardar () sin tener que codificarla.
Mike K
7
Los proyectos de aplicaciones web no pueden utilizar el perfil.
Joel Spolsky
2
Si define accidentalmente las propiedades del perfil en la configuración web <profile ..><properties><add name="..">tanto en la clase AccountProfile como en la clase AccountProfile, obtendrá un "Esta propiedad ya ha sido definida", que se soluciona fácilmente eliminando las propiedades en web.config.
Zachary Scott
17

Los proyectos de aplicación web aún pueden usar el objeto ProfileCommon, pero solo en tiempo de ejecución. El código no se genera en el proyecto en sí, pero la clase es generada por ASP.Net y está presente en tiempo de ejecución.

La forma más sencilla de llegar al objeto es usar un tipo dinámico como se muestra a continuación.

En el archivo Web.config declare las propiedades del perfil:

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

Luego para acceder a las propiedades:

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

Para guardar cambios en las propiedades del perfil:

profile.Save();

Lo anterior funciona bien si se siente cómodo usando tipos dinámicos y no le importa la falta de verificación en tiempo de compilación e intellisense.

Si usa esto con ASP.Net MVC, tiene que hacer un trabajo adicional si pasa el objeto de perfil dinámico a sus vistas, ya que los métodos de ayuda HTML no funcionan bien con los objetos "modelo" que son dinámicos. Deberá asignar propiedades de perfil a variables escritas estáticamente antes de pasarlas a los métodos auxiliares 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

Si crea una clase de perfil personalizado, como Joel describió anteriormente, ASP.Net aún generará la clase ProfileCommon pero heredará de su clase de perfil personalizado. Si no especifica una clase de perfil personalizada, ProfileCommon heredará de System.Web.Profile.ProfileBase.

Si crea su propia clase de perfil, asegúrese de no especificar propiedades de perfil en el archivo Web.config que ya haya declarado en su clase de perfil personalizado. Si lo hace, ASP.Net dará un error de compilador cuando intente generar la clase ProfileCommon.

colivier
fuente
No puedo guardar el perfil. el error es: 'ProfileCommon' no contiene una definición para 'guardar'
Jimmy
2
@Salman: ProfileCommon se deriva de System.Web.Profile.ProfileBase que tiene un método Save (). Verifique que su uso de mayúsculas sea correcto. Ver: msdn.microsoft.com/en-us/library/…
colivier
13

El perfil también se puede utilizar en proyectos de aplicaciones web. Las propiedades se pueden definir en Web.config en tiempo de diseño o mediante programación. En 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>

o mediante programación, cree la sección de perfil creando una instancia de ProfileSection y creando propiedades individuales usando ProfilePropertySettings y ProfilePropertySettingsColletion , todos los cuales están en System.Web.Configuration Namespace. Para usar esas propiedades del perfil, use System.Web.Profile.ProfileBase Objects. No se puede acceder a las propiedades del perfil con el perfil. sintaxis como se mencionó anteriormente, pero se puede hacer fácilmente creando una instancia de ProfileBase y usando SetPropertyValue (" PropertyName ") y GetPropertyValue {" PropertyName ") de la siguiente manera:

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

o para acceder al perfil del usuario actual:

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
fuente
1
No sé por qué esto no obtuvo 1000 votos. Es de gran ayuda.
pghcpa
Supongo que nadie se molesta en desplazarse hasta aquí. ¡Esto es Gold, gracias Bede! Después de guardar los datos anteriores, puedo acceder a los datos del usuario desde cualquier lugar simplemente creando un nuevo ProfileBaseobjeto e invocando GetPropertyValue("PropName")?
biscuit
Increíble, esta es la única forma que funciona para mí. Thans Bede
Emanuel Pirovano
Primer problema, ¿cómo puedo usar get en otra página?
Emanuel Pirovano
8

Cuando crea un nuevo proyecto de sitio web en Visual Studio, el objeto que se devuelve desde Profile se generará (automáticamente) para usted. Cuando creas un proyecto de aplicación web o un proyecto MVC, tendrás que desarrollar el tuyo propio.

Probablemente esto suene más difícil de lo que es. Debes hacer lo siguiente:

  • Cree una base de datos usando aspnet_regsql.exe Esta herramienta se instala junto con el marco .NET.
  • Escriba una clase que se derive de ProfileGroupBase o instale Web Profile Builder (WPB) que puede generar la clase para usted a partir de la definición en Web.Config. He estado usando WPB por un tiempo y hasta ahora ha hecho lo que se esperaba de él. Si tiene muchas propiedades, usar WPB puede ahorrar bastante tiempo.
  • Asegúrese de que la conexión a la base de datos esté configurada correctamente en Web.Config.
  • Ahora está configurado para crear una instancia de su clase de perfil (en el controlador)
  • Probablemente necesitará los valores de propiedad del perfil en sus vistas. Me gusta pasar el objeto de perfil a la vista (no propiedades individuales).
Capitán Sensible
fuente
3

Si está utilizando un proyecto de aplicación web, no puede acceder al objeto Perfil en el momento del diseño listo para usar. Aquí hay una utilidad que supuestamente lo hace por usted: http://weblogs.asp.net/joewrobel/archive/2008/02/03/web-profile-builder-for-web-application-projects.aspx . Personalmente, esa utilidad causó un error en mi proyecto, así que terminé rodando mi propia clase de perfil para heredar de ProfileBase. No fue difícil de hacer.

nshaw
fuente
3
System.Web.Profile: aquí hay un código de muestra: weblogs.asp.net/jgalloway/archive/2008/01/19/…
nshaw
2

También estaba pasando por el mismo problema. Pero en lugar de crear una clase que hereda de ProfileBase, utilicé HttpContext.

Especifique las propiedades en el archivo web.config de la siguiente manera: ProfilePropertyWeb.config

Ahora, escribe el siguiente código: -

Propiedades de perfil de código subyacente

Compila y ejecuta el código. Obtendrá la siguiente salida: -

Salida

Anil Purswani
fuente
1

El creador de perfiles web funcionó muy bien para mí. La clase que generó tiene mucho más de lo que describe la publicación de Joel. Si es realmente necesario o útil, no lo sé.

De todos modos, para aquellos que buscan una forma fácil de generar la clase, pero no quieren tener una dependencia de la herramienta de compilación externa, siempre pueden

  • utilizar el creador de perfiles web
  • ¡borre todo rastro de ella!
  • seguir usando la clase de perfil generada

O (no probado, pero puede funcionar)

  • crear un proyecto de sitio web
  • crea tu elemento
  • ajustar la clase generada y copiarla a su proyecto de proyecto web

Si este segundo enfoque funciona, ¿alguien puede hacérmelo saber para referencia futura?

Simon_Weaver
fuente
1

Solo quiero agregar a la respuesta de Joel Spolsky

Implementé su solución, trabajando brillantemente por cierto - ¡Cudos!

Para cualquiera que desee obtener un perfil de usuario que no sea el usuario registrado que utilicé:

web.config:

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

y

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

Y luego mi clase personalizada:

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

Funciona de maravilla...

Patear el culo
fuente
0

Buena publicación,

Solo una nota en web.config si no especifica el atributo de herencia en el elemento de perfil, deberá especificar cada propiedad de perfil individual dentro del elemento de perfil en web.config como se muestra a continuación.

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

 </properties>
indy
fuente