Respuestas:
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.config
y 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 ProfileBase
para 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;
<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.
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.
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();
ProfileBase
objeto e invocando GetPropertyValue("PropName")
?
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:
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.
Tutorial de MSDN para crear una clase personalizada (también conocido como método de Joel):
http://msdn.microsoft.com/en-us/magazine/cc163624.aspx
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:
Ahora, escribe el siguiente código: -
Compila y ejecuta el código. Obtendrá la siguiente salida: -
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
O (no probado, pero puede funcionar)
Si este segundo enfoque funciona, ¿alguien puede hacérmelo saber para referencia futura?
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...
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>