ASP.NET Profile save overwritten by old values

2019-04-07 06:30发布

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

4条回答
Melony?
2楼-- · 2019-04-07 06:55

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

查看更多
姐就是有狂的资本
3楼-- · 2019-04-07 06:56

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();
}
查看更多
别忘想泡老子
4楼-- · 2019-04-07 07:05

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.

查看更多
再贱就再见
5楼-- · 2019-04-07 07:05

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.

查看更多
登录 后发表回答