7

I am using the Profile feature of ASP.NET in a website. Updating a profile is working weirdly! A user can't update his/her own profile, neither the web site user nor the administrator, but, the administrator is able to update profiles of other users.

In the backend, after Profile's save() is called, SQL Server traces show that aspnet_Profile_SetProperties stored procedure is called twice. First, with new values, then, with old values. The second execution is done after page unload. My code has nothing to do with transactions.

Why is it working so weirdly?

Could there be an issue with aspnet_regsql's installation as I have installed uninstalled and again installed it!?

Code

web.config

<authentication mode="Forms">
    <forms name="FormsAuthentication" loginUrl="~/Login.aspx" defaultUrl="~/Login.aspx" timeout="20"/>
</authentication>
<membership defaultProvider="CustSqlMembershipProvider">
    <providers>
        <add connectionStringName="connString" applicationName="/space_online" minRequiredPasswordLength="5" minRequiredNonalphanumericCharacters="0" name="CustSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider"/>
    </providers>
</membership>
<roleManager enabled="true" defaultProvider="CustSqlRoleProvider">
    <providers>
        <add connectionStringName="connString" applicationName="/space_online" name="CustSqlRoleProvider" type="System.Web.Security.SqlRoleProvider"/>
    </providers>
</roleManager>
<anonymousIdentification cookieless="AutoDetect" enabled="true"/>
<profile defaultProvider="CustSqlProfileProvider" enabled="true">
    <providers>
        <add name="CustSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="connString" applicationName="/space_online"/>
    </providers>
    <properties>
        <add name="FirstName" type="System.String"/>
        <add name="LastName" type="System.String"/>
        <add name="Email" type="System.String"/>
        <group name="Address">
            <add name="Street" type="System.String"/>
            <add name="City" type="System.String"/>
            <add name="PostalCode" type="System.String"/>
        </group>
        <group name="Contact">
            <add name="Phone" type="System.String"/>
            <add name="Mobile" type="System.String"/>
            <add name="Fax" type="System.String"/>
        </group>
        <add name="ShoppingCart" type="psb.website.BLL.Store.ShoppingCart" serializeAs="Binary" allowAnonymous="true"/>
    </properties>
</profile>

Code behind

private void UpdateProfile(ProfileCommon myprofile)
{
    myprofile.FirstName = tbFirstName.Text.Trim();
    myprofile.LastName = tbLastName.Text.Trim();
    myprofile.Email = tbEmail.Text.Trim();
    myprofile.Address.Street = tbStreetPhysical.Text.Trim();
    myprofile.Address.City = tbCity.Text.Trim();
    myprofile.Address.PostalCode = tbPostalCode.Text.Trim();
    myprofile.Contact.Phone = tbPhone1.Text.Trim();
    myprofile.Contact.Mobile = tbMobile.Text.Trim();
    myprofile.Save();
}
private ProfileCommon GetProfile()
    {
        ProfileCommon profile = this.Profile;
        if (Request.QueryString["UserName"] != null && HttpContext.Current.User.IsInRole("Admin"))
            profile = this.Profile.GetProfile(Request.QueryString["UserName"].ToString());
        else
            profile = this.Profile.GetProfile(HttpContext.Current.User.Identity.Name);
        return profile;
    }
protected void tbUpdateProfile_Click(object sender, ImageClickEventArgs e)
    {
        UpdateProfile(GetProfile());
    }
Null Head
  • 2,877
  • 13
  • 61
  • 83
  • please post your web.config section related to profiles. try to get a stack trace for the second save of the profile! – user492238 Jun 03 '11 at 04:58
  • In callstack window, I can just see Master page rendering controls and once that is done, aspnet_Profile_SetProperties procedure is getting executed. Couldn't find the caller source. – Null Head Jun 03 '11 at 05:15
  • Can you show where and how you call UpdateProfile()? – ibram Jun 03 '11 at 06:14
  • @ibram: myprofile.Save() – Null Head Jun 03 '11 at 22:46
  • @Reddy S R myprofile.Save() is called FROM UpdateProfile() where are you calling UpdateProfile() – ashelvey Jun 09 '11 at 07:40
  • @ibram, got your question wrong. UpdateProfile is called in button click event protected void tbUpdateProfile_Click(object sender, ImageClickEventArgs e) { UpdateProfile(GetProfile()); } – Null Head Jun 10 '11 at 03:29
  • You write that the admin saves the profile of other users, but in your code you get and update the profile of the current user. I don't understand this. – ibram Jun 10 '11 at 06:26
  • @ibram Added full code. Hope that helps. – Null Head Jun 10 '11 at 07:37
  • Did you tried the clear tag in your profile definition? – ibram Jun 10 '11 at 12:06

4 Answers4

5

The profile is by default automatically saved at the end of the execution of an ASP.NET page, see the profile Element (ASP.NET Settings Schema) documentation on this. This explains the second "mysterious" save that you observe.

You can try to change automaticSaveEnabled to false.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • Your solution worked like charm! Thanks a heap. Just wondering why autosave is overwriting my save! After Profile.save() is called, I tried redirecting page with endresponse flag set to true, but, it too did not work. Any idea on it Simon? Thanks again! – Null Head Jun 10 '11 at 07:02
  • I have another application where this kind of override is not happening! I cant see any changes between that application and this one. – Null Head Jun 10 '11 at 07:16
  • Link you posted in your answer doesn't exist anymore. With that, value of this answer drops a lot. – Rahul Jun 04 '15 at 12:22
  • Thank You Simon for updating the link. – Rahul Jun 04 '15 at 17:18
  • Life saver. Thank you. – Martin Aug 24 '15 at 10:53
0

all the transactions must be done before page unload. if page is unloaded then its all function calls will also be removed or stopped in midway.

Syed_Adeel
  • 430
  • 5
  • 14
  • Cant recall any code addressing transactions in here. Also, administrator is able to update other users profiles. How is the transaction passing in this case and not while updating self's profile? – Null Head Jun 03 '11 at 22:52
0

Access to ProfileCommon should be done through HttpContext.Current.Profile as that is a reference to the current user's profile (logged in or anonymous) and you don't need to explicitly call Save. Try this:

private void UpdateProfile()
{
    var myprofile = HttpContext.Current.Profile as ProfileCommon;

    if (profile == null) {
        throw new InvalidOperationException("HttpContext.Current.Profile is not of type ProfileCommon for some reason!");
    }

    myprofile.FirstName = tbFirstName.Text.Trim();
    myprofile.LastName = tbLastName.Text.Trim();
    myprofile.Email = tbEmail.Text.Trim();
    myprofile.Address.Street = tbStreetPhysical.Text.Trim();
    myprofile.Address.City = tbCity.Text.Trim();
    myprofile.Address.PostalCode = tbPostalCode.Text.Trim();
    myprofile.Contact.Phone = tbPhone1.Text.Trim();
    myprofile.Contact.Mobile = tbMobile.Text.Trim();
}
Sumo
  • 4,066
  • 23
  • 40
0

You may need to clear the default provider in your web.config. Like this:

<profile defaultProvider="CustSqlProfileProvider" enabled="true">
    <providers>
        <clear /><!-- here -->
        <add name="CustSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="connString" applicationName="/space_online"/>
    </providers>
    <properties>
        <...>
    </properties>
</profile>

Here is a good explanation for this: Removing existing profile providers

And here is another good site: http://odetocode.com/articles/440.aspx

Community
  • 1
  • 1
ibram
  • 4,414
  • 2
  • 22
  • 34