How to use ASP.NET 2.0 Profile object from web service code

You have started to use ASP.NET 2.0 Profile Provider and you are very happy with it. All your .aspx pages are full of "Profile.Something". You also introduced a lot of new properties on the profile object via web.config. Then you added a new web service. There you want to access the Profile object. You realize, you are doomed.

You cannot access the Profile object from Web Service.

At runtime, ASP.NET generates a class looking at the specification provided in web.config, which becomes the "Profile" object in .aspx pages. But this object is not available in Web service (.asmx.cs) and you cannot see the custom properties you have added in the profile object. Although HttpContext.Current.Profile will give you reference to Profile object, but it's type is ProfileBase which does not show your custom properties. Makes sense, because the class is generated at runtime. But if it can be made available in .aspx.cs, then it should also be available in .asmx.cs.

In order to overcome this problem, you have to hand code that profile class in your App_Code folder and then configure web.config so that it does not auto generate the class instead use your one. Here's what you do in web.config:

<profile enabled="true" inherits="UserProfile">

I have added a new attribute UserProfile. Now go to App_Code and make a UserProfile class like this:

public class UserProfile : System.Web.Profile.ProfileBase
{
[SettingsAllowAnonymousAttribute(true)]
public virtual int Timezone
{
get
{
return ((int)(this.GetPropertyValue("Timezone")));
}
set
{
this.SetPropertyValue("Timezone", value);
}

}

Declare all the properties like this. Don't forget to add the [SettingsAllowAnonymousAttribute(true)] on the properties which you want to be made available to anonymous users.

At the end of the class, add this method:

public virtual ProfileCommon GetProfile(string username)
{
return ((ProfileCommon)(ProfileBase.Create(username)));

}

Here's an easy way to avoid hand coding this class and generating it automatically. Before you make the changes in web.config and create the UserProfile class, run your web project as it was before. But before running it, turn off SQL Server. This will make Asp.net execution to break on first call to some Profile object's property. For ex, if you have a custom property TimeZone in the Profile object, execution will break on this line:

public virtual int Timezone
{
get
{

return ((int)(this.GetPropertyValue("Timezone")));

It will fail to load the profile object values from database because database is down. If you scroll up, you will see this is the class that ASP.NET generates at run time. You will see all the properties are declared on this class already. So, you can just copy & paste it in your own class easily!

But after copying, you will realize there's no [SettingsAllowAnonymousAttribute(true)] attribute. So, you will have to put them manually. Also after making your own custom class, you will have to remove all the custom properties declared inside <properties> node in the web.config.

Now that you have your own Profile class, inside web service, you can cast (HttpContext.Current.Profile as UserProfile) and then you can use all the custom properties.

If you don't want to enjoy strongly typed coding on web service, then you can always use the old way of accessing Profile properties via: Profile.GetPropertyValue("TimeZone"). But it's no fun.

Published Fri, Aug 18 2006 4:42 by omar
Filed under:

Comments

# re: How to use ASP.NET 2.0 Profile object from web service code

Wednesday, December 20, 2006 11:38 PM by Greg

Hi Omar,

You seriously have the best articles I have ever seen written by a developer...anyways, I am wondering what the difference is between using static or virtual...I notice that you use virtual above. What do you know about using static methods and what are benefits of making something virtual??

Thanks,

Greg

# re: How to use ASP.NET 2.0 Profile object from web service code

Wednesday, December 20, 2006 11:59 PM by omar

static and virtual are very much different. Static means global things which are not dependent on instance. Virtual means you allow the function or property to be overriden.

# re: How to use ASP.NET 2.0 Profile object from web service code

Thursday, December 21, 2006 8:26 AM by Greg

Hi Omar,

Thanks for the response, that makes sense...Is the above method still the best way to access the Profile properties from a web service?

P.S. I am going to invite you to chat over GMail...my email address is gpbenoit at gmail dot com.

Thanks,

# re: How to use ASP.NET 2.0 Profile object from web service code

Thursday, January 25, 2007 12:40 PM by Sam

Good post. I would just point out that to get this to work in a web application project (VS2005 SP1), the inherits attribute of the provider element needs to be a full type specification, as the UserProfile class will be precompiled into the project output assembly.

ie

<provider inherits="MyProject.MyComponents.UserProfile, MyProject" />

# re: How to use ASP.NET 2.0 Profile object from web service code

Thursday, January 25, 2007 12:41 PM by Sam

sorry typo, should be profile element not provider element...

# re: How to use ASP.NET 2.0 Profile object from web service code

Saturday, February 10, 2007 11:57 PM by Cameron

Thanks a bunch, this was very helpful to me, saved me loads of time in the Reflector :)

# re: How to use ASP.NET 2.0 Profile object from web service code

Thursday, February 15, 2007 3:36 AM by Aram Tutunciyan

I've been busy now for a while to find a way to access the Profile objects from a web service page without using custom classes... and it seem possible after all in the following manner:

// Find the membership user

MembershipUser user = Membership.GetUser("Aram");

if (user != null)

{

 // Create an profile object for this user

 ProfileCommon profile = (ProfileCommon)ProfileBase.Create(user.UserName, true);

 // You can access the strongly typed profile object here

}

# re: How to use ASP.NET 2.0 Profile object from web service code

Monday, February 26, 2007 2:01 AM by shamim

Hi Omar

Tanks for solution

But when I used a Group Profile I recived error in setting Property collection , Can you tell me what I do ?

# re: How to use ASP.NET 2.0 Profile object from web service code

Wednesday, April 11, 2007 9:18 AM by Chet

Great post - I also really appreciate Aram's comments, as they helped me do all of this without any custom profile classes - got it all down to just a few lines of code (since the page I'm using assumes the user is logged in and has a profile)

   Private Function GetCurrentProfile() As ProfileCommon

       Dim UserName As String = HttpContext.Current.Profile.UserName

       Dim User As MembershipUser = Membership.GetUser(UserName)

       Dim profile As ProfileCommon = ProfileBase.Create(User.UserName, True)

       Return profile

   End Function

This VB.NET function returns a ProfileCommon object complete with all the custom settings defined in web.config.

# re: How to use ASP.NET 2.0 Profile object from web service code

Wednesday, May 09, 2007 4:15 PM by Mahesh

You can get access to all your custom properties in Profile object just by type casting:

[WebMethod]

public void AddStock(string symbol)

{

 ProfileCommon profile = HttpContext.Current.Profile as ProfileCommon;

 profile.StockSymbols.Add(symbol);

}

# re: How to use ASP.NET 2.0 Profile object from web service code

Thursday, May 10, 2007 6:41 PM by Mahesh

We have an existing Authentication Service, which drops an "AUTH" cookie once user is authenticated. And I want to use this cookie to identify if an user is anonymous or authenticated. I did not find any way to add this information (username and the IsAuthenticated flag) into the Profile SettingsContext.

Is there a way to do it ?

# re: How to use ASP.NET 2.0 Profile object from web service code

Wednesday, May 16, 2007 10:14 AM by Mikey D.

Excellent article, and nice feedback - all very helpful. I have a challenge to throw out to the group here - I need to actually get a reference to a user and profile (and use these methods as a foundation) BUT I am actually doing this processing from a SQL Server Integration Services package (Script Component) that doesn't even have a HTTPContext to hook into :)

This is a text file upload of users into my web application.

Anyone have any thoughts on a way to tackle this? I am *this* close.. but can't see the way...

# re: How to use ASP.NET 2.0 Profile object from web service code

Saturday, May 19, 2007 11:17 AM by omar

You will have to parse content of aspnet_profile row for the user from Script component.

# re: How to use ASP.NET 2.0 Profile object from web service code

Monday, June 04, 2007 1:34 PM by D

There is another way to avoid hand-coding the custom profile class, without having to run your application with breakpoints or disable the database, as long as you're using Visual Studio (like me :). In a page that uses your profile, or defines a variable of type ProfileCommon, just right-click on the "ProfileCommon" type identifier and select "Go To Definition." As long as your site is compiled, the IDE should open up a page like App_Code/profile.abcde123.cs.

Also, to answer Shamim's question, a ProfileGroup has to be implemented as a separate class in the file that inherits from ProfileGroupBase. The ProfileGroupBase contains the get & set properties, and then the ProfileBase contains a get method for the group, like so:

public class MyProfileGroup : System.Web.Profile.ProfileGroupBase {

   public virtual object GroupProperty1 {

       get {

           return ((object)(this.GetPropertyValue("GroupProperty1")));

       }

       set {

           this.SetPropertyValue("GroupProperty1", value);

       }

   }

   public virtual object GroupProperty2{

       get {

           return ((object)(this.GetPropertyValue("GroupProperty2")));

       }

       set {

           this.SetPropertyValue("GroupProperty2", value);

       }

   }

}

public class MyProfileCommon : System.Web.Profile.ProfileBase {

   public virtual MyProfileGroup MyGroup {

       get {

           return ((MyProfileGroup)(this.GetProfileGroup("MyGroup")));

       }

   }

   public virtual MyProfileCommon GetProfile(string username) {

       return ((MyProfileCommon)(ProfileBase.Create(username)));

   }

}

# re: How to use ASP.NET 2.0 Profile object from web service code

Thursday, June 07, 2007 11:06 AM by vidapura

"Also after making your own custom class, you will have to remove all the custom properties declared inside <properties> node in the web.config."

In which web.config? The one in the web service or the one in the client using the web service?

Thanks

Vida

# re: How to use ASP.NET 2.0 Profile object from web service code

Tuesday, July 03, 2007 5:17 PM by Antonio

How would i architect a 3-Tier application that is physically located on different servers.  So I want the Profile object in my presentation layer, but that will not work since I can not call the database directly.  I need to create a Profile object on the web services layer that can call the database.  I am having a hard time trying to figure this out.  Can anyone help on this? Every example i see always uses 3 layer that sits on one physical server???  

# re: How to use ASP.NET 2.0 Profile object from web service code

Saturday, July 07, 2007 3:25 AM by omar

Very good question. I have always struggled with ASP.NET Membership and Provider having a 2-tier model. The solution is to build your own custom provider which uses your standard business layer on middle tier.

Here's how to make custom providers:

msdn2.microsoft.com/.../0580x1f5.aspx

You can also learn from ASP.NET default membership provider source code:

weblogs.asp.net/.../442772.aspx

# re: How to use ASP.NET 2.0 Profile object from web service code

Thursday, September 27, 2007 4:32 PM by Nathaniel D. Holcomb

Um? Where is this ProfileCommon class defined? I am soooo confused. Did I miss something?

# re: How to use ASP.NET 2.0 Profile object from web service code

Wednesday, November 07, 2007 5:29 AM by Hanno

My problem was quite similar to that of the first paragraph, except that I wanted to use my Profile in a normal class library. I'm not sure if this is relevent to webservices too, but I'm just placing the solution here, incase someone else needs it too:

System.Web.HttpContext.Current.Profile

# re: How to use ASP.NET 2.0 Profile object from web service code

Friday, April 18, 2008 5:53 AM by shakeel

All discussion is very good. I am facing a problem regarding the implementation of the Custom Profiler.

I created a OracleProfileProvider: ProfileProvider in a web project app(not a web site), overrides all required functions and properties (ApplicationName, Initialize, GetPropertyValues, SetPropertyValues, DeleteInactiveProfiles, DeleteProfiles, FindInactiveProfilesByUserName, FindProfilesByUserName, GetAllInactiveProfiles, GetAllProfiles, GetNumberOfInactiveProfiles) and also create a class for the properties of the User (UserProfile: ProfileBase). Both of these classes are defined in a namespace (abc.def). I insert the following tags in the web.config

<authentication mode="Forms">

     <forms loginUrl="Logon.aspx" defaultUrl="Forms/Default.aspx" name=".ASPXAUTH" timeout ="5">

     </forms>

   </authentication>

   <authorization>

     <deny users="?" />

   </authorization>

   <profile enabled="true" defaultProvider="OracleProfileProvider" inherits="abc.def.UserProfile" >

     <providers>

       <clear />

       <add name="OracleProfileProvider" type="abc.def.OracleProfileProvider, Web" description="Profile Provider"/>

     </providers>

   </profile>

I didn't find the Profile property in aspx page, After reading this article, I declared a Profile object (protected abc.def.UserProfile Profile = System.Web.HttpContext.Current.Profile as abc.def.UserProfile;) in MyPage class which is inherited from the System.Web.UI.Page, and When I tried to access the Profile object in the aspx page (inherited from MyPage) I got that Profile object has null value. Please tell me what's is wrong in it or what I have to do to overcome this problem.

Thanks a lot.

# re: How to use ASP.NET 2.0 Profile object from web service code

Tuesday, May 13, 2008 12:28 PM by Kevin

I am having an issue with attempting to use Profile groups in my custom user profile object.  When I attempt to access a property from the group, I get the following exception:

System.Configuration.Provider.ProviderException was unhandled by user code

 Message="The profile group 'Preferences' has not been defined."

 Source="System.Web"

 StackTrace:

      at System.Web.Profile.ProfileBase.GetProfileGroup(String groupName)

      at TODv2.Core.Profile.TODUserProfile.get_Preferences() in C:\Programming\Projects2008\TODv2\TODv2.Core\Profile\TODUserProfile.cs:line 40

      at TODv2.Core.Base.BasePage.OnPreInit(EventArgs e) in C:\Programming\Projects2008\TODv2\TODv2.Core\Base\BasePage.cs:line 75

      at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

I have scoured Google, but there doesn't seem to be much information on this configuration.  Or I need to brush up on my Googling skills.

Can anyone point out what I'm missing?  Below is the code for the profile group and profile itself.

Thanks!

public class TODUserProfilePreferencesGroup : ProfileGroupBase {

 [SettingsAllowAnonymous(false)]

 public virtual string Theme {

   get { return (string)this.GetPropertyValue("Theme"); }

   set { this.SetPropertyValue("Theme", value); }

 }

 [SettingsAllowAnonymous(false)]

 public virtual int Timezone {

   get { return (int)this.GetPropertyValue("Timezone"); }

   set { this.SetPropertyValue("Timezone", value); }

 }

}

public class TODUserProfile : ProfileBase {

 public virtual TODUserProfilePreferencesGroup Preferences {

   get { return (TODUserProfilePreferencesGroup)(this.GetProfileGroup("Preferences")); }

 }

 public virtual TODUserProfile GetProfile(string username) {

   return (TODUserProfile)ProfileBase.Create(username);

 }

}

# re: How to use ASP.NET 2.0 Profile object from web service code

Thursday, May 22, 2008 3:31 PM by mei

Having the same problem as Kevin. Looking for solution.

# re: How to use ASP.NET 2.0 Profile object from web service code

Thursday, June 12, 2008 7:04 AM by Hari Krishna

Hi,

If I run my application from IIS the why HttpContext.Current.Profile value is null. If I run from IDE the value is not null. Is it the problem with IIS or SQl Server. SQLExpress is running on my machine. Please let me know the problem. Thanks in advance.

# re: How to use ASP.NET 2.0 Profile object from web service code

Tuesday, July 01, 2008 12:41 AM by Santosh Kumar

Hi Omar,

thanks, giveing the great article for Asp.net Profile, this is the best way to access the Profile properties from a web service?

Santosh Kumar

www.operativesystems.com

# re: How to use ASP.NET 2.0 Profile object from web service code

Wednesday, July 09, 2008 11:46 AM by ray

Same problem as mei and kevin-  any other thoughts on the ProfileGroup issue?  

# re: How to use ASP.NET 2.0 Profile object from web service code

Tuesday, September 09, 2008 3:31 PM by chad

Im having the same issue with the profile groups. Has anyone had any luck figuring it out?

# re: How to use ASP.NET 2.0 Profile object from web service code

Thursday, October 09, 2008 11:44 AM by Scott

I also am having the same problem using the Profile groups

# re: How to use ASP.NET 2.0 Profile object from web service code

Saturday, December 13, 2008 4:28 PM by Jim Black

I'm having the same problem on groups.   My definition of the group looks like this:

Public Class CG_ProfGrpWorkPhone : Inherits System.Web.Profile.ProfileGroupBase

   ' Defines business object layer component for the WorkPhone number

   Public Overridable Property CountryCode() As String

       Get

           Return CType(Me.GetPropertyValue("CountryCode"), String)

       End Get

       Set(ByVal value As String)

           Me.SetPropertyValue("CountryCode", value)

       End Set

   End Property

   Public Overridable Property AreaCode() As String

       Get

           Return CType(Me.GetPropertyValue("AreaCode"), String)

       End Get

       Set(ByVal value As String)

           Me.SetPropertyValue("AreaCode", value)

       End Set

   End Property

   Public Overridable Property Phone1() As Integer

       Get

           Return CType(Me.GetPropertyValue("Phone1"), Integer)

       End Get

       Set(ByVal value As Integer)

           Me.SetPropertyValue("Phone1", value)

       End Set

   End Property

   Public Overridable Property Phone2() As Integer

       Get

           Return CType(Me.GetPropertyValue("Phone2"), Integer)

       End Get

       Set(ByVal value As Integer)

           Me.SetPropertyValue("Phone2", value)

       End Set

   End Property

End Class

... and my attempt to include this group in my custom profile object looks like this:

Public Overridable ReadOnly Property WorkPhone() As CG_ProfGrpWorkPhone

       Get

           Return CType(Me.GetProfileGroup("WorkPhone"), CG_ProfGrpWorkPhone)

       End Get

   End Property

Whenever I run this, I get the error message:

The profile group 'WorkPhone' has not been defined.

When I run it in the debugger right before I hit the exception, I see that all of my non-group properties are returning values but the group property has an error System.Web.Profile.ProfileBase.GetProfileGroup(String groupName).

So it look like ASP.NET is ignoring my group class definition.   Is there some trick in web.config to tell it to pay attention to that class.  I played around with the "inherits" key word in the <profile> tag, but that didn't work.

# re: How to use ASP.NET 2.0 Profile object from web service code

Saturday, December 13, 2008 4:30 PM by Jim Black

Note that there is a similar blog with a similar group of people "stuck" on this issue at Jon Galloway's blog:

weblogs.asp.net/.../writing-a-custom-asp-net-profile-class.aspx

# ASP.NET profile grouping, based on role

Sunday, February 01, 2009 11:30 AM by David Ross

Jim - not just Galloway, and Omar here, but also K Scott Allen:

odetocode.com/.../2653.aspx [comments blocked]

I use profile groups for stuff that is specific to membership role. I understand that "multiple profiles based on role" is ILLEGAL in ASP.NET, but we can use groups for this encapsulation. I ended up doing away with my custom groups and going back to web.config just for these groups.

But I also have role-specific static members (to fill in ObjectDataSource and the like). Since I can no longer rely on my own profile grouping classes, I created a new class inheriting from ProfileCommon for these static members.

I would much rather have stuck them in the same class as the profile groups.

Leave a Comment

(required) 
(required) 
(optional)
(required)