0

当我的网站负载很重时,我的网站会产生奇怪的影响。

我随机获取其他用户设置的属性。我有自己的配置文件系统实现,所以我想我不能责怪配置文件系统本身。

我只需要一个点来开始调试。我猜有一个 cookie 值映射到某处的 Profile 条目。有没有机会看看这个映射是如何工作的?

这是我的个人资料提供者:

using System;
using System.Text;
using System.Configuration;
using System.Web;
using System.Web.Profile;
using System.Collections;
using System.Collections.Specialized;
using B2CShop.Model;
using log4net;
using System.Collections.Generic;
using System.Diagnostics;
using B2CShop.DAL;
using B2CShop.Model.RepositoryInterfaces;
[assembly: log4net.Config.XmlConfigurator()]
namespace B2CShop.Profile
{
    public class B2CShopProfileProvider : ProfileProvider
    {
        private static readonly ILog _log = LogManager.GetLogger(typeof(B2CShopProfileProvider));
        // Get an instance of the Profile DAL using the ProfileDALFactory
        private static readonly B2CShop.DAL.UserRepository dal = new  B2CShop.DAL.UserRepository();
        // Private members
        private const string ERR_INVALID_PARAMETER = "Invalid Profile parameter:";

        private const string PROFILE_USER = "User";
        private static string applicationName = B2CShop.Model.Configuration.ApplicationConfiguration.MembershipApplicationName;

        /// <summary>
        /// The name of the application using the custom profile provider.
        /// </summary>
        public override string ApplicationName
        {
            get
            {
                return applicationName;
            }
            set
            {
                applicationName = value;
            }
        }


        /// <summary>
        /// Initializes the provider.
        /// </summary>
        /// <param name="name">The friendly name of the provider.</param>
        /// <param name="config">A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider.</param>
        public override void Initialize(string name, NameValueCollection config)
        {
            if (config == null)
                throw new ArgumentNullException("config");

            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "B2C Shop  Custom Provider");
            }

            if (string.IsNullOrEmpty(name))
                name = "b2c_shop";

            if (config["applicationName"] != null && !string.IsNullOrEmpty(config["applicationName"].Trim()))
                applicationName = config["applicationName"];

            base.Initialize(name, config);

        }

        /// <summary>
        /// Returns the collection of settings property values for the specified application instance and settings property group.
        /// </summary>
        /// <param name="context">A System.Configuration.SettingsContext describing the current application use.</param>
        /// <param name="collection">A System.Configuration.SettingsPropertyCollection containing the settings property group whose values are to be retrieved.</param>
        /// <returns>A System.Configuration.SettingsPropertyValueCollection containing the values for the specified settings property group.</returns>
        public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
        {

            string username = (string)context["UserName"];
            bool isAuthenticated = (bool)context["IsAuthenticated"];
            //if (!isAuthenticated) return null;
            int uniqueID = dal.GetUniqueID(username, isAuthenticated, false, ApplicationName);



            SettingsPropertyValueCollection svc = new SettingsPropertyValueCollection();

            foreach (SettingsProperty prop in collection)
            {
                SettingsPropertyValue pv = new SettingsPropertyValue(prop);

                switch (pv.Property.Name)
                {
                    case PROFILE_USER:
                        if (!String.IsNullOrEmpty(username))
                        {
                            pv.PropertyValue = GetUser(uniqueID);
                        }
                        break;
                    default:
                        throw new ApplicationException(ERR_INVALID_PARAMETER + " name.");
                }

                svc.Add(pv);
            }
            return svc;
        }


        /// <summary>
        /// Sets the values of the specified group of property settings.
        /// </summary>
        /// <param name="context">A System.Configuration.SettingsContext describing the current application usage.</param>
        /// <param name="collection">A System.Configuration.SettingsPropertyValueCollection representing the group of property settings to set.</param>
        public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
        {

            string username = (string)context["UserName"];
            CheckUserName(username);
            bool isAuthenticated = (bool)context["IsAuthenticated"];

            int uniqueID = dal.GetUniqueID(username, isAuthenticated, false, ApplicationName);
            if (uniqueID == 0)
            {
                uniqueID = dal.CreateProfileForUser(username, isAuthenticated, ApplicationName);
            }

            foreach (SettingsPropertyValue pv in collection)
            {

                if (pv.PropertyValue != null)
                {
                    switch (pv.Property.Name)
                    {
                        case PROFILE_USER:
                            SetUser(uniqueID, (UserInfo)pv.PropertyValue);
                            break;
                        default:
                            throw new ApplicationException(ERR_INVALID_PARAMETER + " name.");
                    }
                }
            }

            UpdateActivityDates(username, false);
        }


        // Profile gettters
        // Retrieve UserInfo
        private static UserInfo GetUser(int userID)
        {
            return dal.GetUser(userID);
        }




        // Update account info
        private static void SetUser(int uniqueID, UserInfo user)
        {
            user.UserID = uniqueID;
            dal.SetUser(user);
        }


        // UpdateActivityDates
        // Updates the LastActivityDate and LastUpdatedDate values 
        // when profile properties are accessed by the
        // GetPropertyValues and SetPropertyValues methods. 
        // Passing true as the activityOnly parameter will update
        // only the LastActivityDate.
        private static void UpdateActivityDates(string username, bool activityOnly)
        {
            dal.UpdateActivityDates(username, activityOnly, applicationName);
        }

        /// <summary>
        /// Deletes profile properties and information for the supplied list of profiles.
        /// </summary>
        /// <param name="profiles">A System.Web.Profile.ProfileInfoCollection of information about profiles that are to be deleted.</param>
        /// <returns>The number of profiles deleted from the data source.</returns>
        public override int DeleteProfiles(ProfileInfoCollection profiles)
        {

            int deleteCount = 0;

            foreach (ProfileInfo p in profiles)
                if (DeleteProfile(p.UserName))
                    deleteCount++;

            return deleteCount;
        }

        /// <summary>
        /// Deletes profile properties and information for profiles that match the supplied list of user names.
        /// </summary>
        /// <param name="usernames">A string array of user names for profiles to be deleted.</param>
        /// <returns>The number of profiles deleted from the data source.</returns>
        public override int DeleteProfiles(string[] usernames)
        {

            int deleteCount = 0;

            foreach (string user in usernames)
                if (DeleteProfile(user))
                    deleteCount++;

            return deleteCount;
        }

        // DeleteProfile
        // Deletes profile data from the database for the specified user name.
        private static bool DeleteProfile(string username)
        {
            CheckUserName(username);
            return dal.DeleteAnonymousProfile(username, applicationName);   
        }

        // Verifies user name for sise and comma
        private static void CheckUserName(string userName)
        {
            if (string.IsNullOrEmpty(userName) || userName.Length > 256 || userName.IndexOf(",") > 0)
                throw new ApplicationException(ERR_INVALID_PARAMETER + " user name.");
        }

        /// <summary>
        /// Deletes all user-profile data for profiles in which the last activity date occurred before the specified date.
        /// </summary>
        /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are deleted.</param>
        /// <param name="userInactiveSinceDate">A System.DateTime that identifies which user profiles are considered inactive. If the System.Web.Profile.ProfileInfo.LastActivityDate value of a user profile occurs on or before this date and time, the profile is considered inactive.</param>
        /// <returns>The number of profiles deleted from the data source.</returns>
        public override int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
        {

            string[] userArray = new string[0];
             dal.GetInactiveProfiles((int)authenticationOption, userInactiveSinceDate, ApplicationName).CopyTo(userArray, 0);

            return DeleteProfiles(userArray);
        }

        /// <summary>
        /// Retrieves profile information for profiles in which the user name matches the specified user names.
        /// </summary>
        /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are returned.</param>
        /// <param name="usernameToMatch">The user name to search for.</param>
        /// <param name="pageIndex">The index of the page of results to return.</param>
        /// <param name="pageSize">The size of the page of results to return.</param>
        /// <param name="totalRecords">When this method returns, contains the total number of profiles.</param>
        /// <returns>A System.Web.Profile.ProfileInfoCollection containing user-profile information
        //     for profiles where the user name matches the supplied usernameToMatch parameter.</returns>
        public override ProfileInfoCollection FindProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {

            CheckParameters(pageIndex, pageSize);

            return GetProfileInfo(authenticationOption, usernameToMatch, null, pageIndex, pageSize, out totalRecords);
        }

        /// <summary>
        /// Retrieves profile information for profiles in which the last activity date occurred on or before the specified date and the user name matches the specified user name.
        /// </summary>
        /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are returned.</param>
        /// <param name="usernameToMatch">The user name to search for.</param>
        /// <param name="userInactiveSinceDate">A System.DateTime that identifies which user profiles are considered inactive. If the System.Web.Profile.ProfileInfo.LastActivityDate value of a user profile occurs on or before this date and time, the profile is considered inactive.</param>
        /// <param name="pageIndex">The index of the page of results to return.</param>
        /// <param name="pageSize">The size of the page of results to return.</param>
        /// <param name="totalRecords">When this method returns, contains the total number of profiles.</param>
        /// <returns>A System.Web.Profile.ProfileInfoCollection containing user profile information for inactive profiles where the user name matches the supplied usernameToMatch parameter.</returns> 
        public override ProfileInfoCollection FindInactiveProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
        {

            CheckParameters(pageIndex, pageSize);

            return GetProfileInfo(authenticationOption, usernameToMatch, userInactiveSinceDate, pageIndex, pageSize, out totalRecords);
        }

        /// <summary>
        /// Retrieves user profile data for all profiles in the data source.
        /// </summary>
        /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are returned.</param>
        /// <param name="pageIndex">The index of the page of results to return.</param>
        /// <param name="pageSize">The size of the page of results to return.</param>
        /// <param name="totalRecords">When this method returns, contains the total number of profiles.</param>
        /// <returns>A System.Web.Profile.ProfileInfoCollection containing user-profile information for all profiles in the data source.</returns>      
        public override ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords)
        {
            CheckParameters(pageIndex, pageSize);

            return GetProfileInfo(authenticationOption, null, null, pageIndex, pageSize, out totalRecords);
        }

        /// <summary>
        /// Retrieves user-profile data from the data source for profiles in which the last activity date occurred on or before the specified date.
        /// </summary>
        /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are returned.</param>
        /// <param name="userInactiveSinceDate">A System.DateTime that identifies which user profiles are considered inactive. If the System.Web.Profile.ProfileInfo.LastActivityDate of a user profile occurs on or before this date and time, the profile is considered inactive.</param>
        /// <param name="pageIndex">The index of the page of results to return.</param>
        /// <param name="pageSize">The size of the page of results to return.</param>
        /// <param name="totalRecords">When this method returns, contains the total number of profiles.</param>
        /// <returns>A System.Web.Profile.ProfileInfoCollection containing user-profile information about the inactive profiles.</returns>
        public override ProfileInfoCollection GetAllInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
        {
            CheckParameters(pageIndex, pageSize);

            return GetProfileInfo(authenticationOption, null, userInactiveSinceDate, pageIndex, pageSize, out totalRecords);
        }

        /// <summary>
        /// Returns the number of profiles in which the last activity date occurred on or before the specified date.
        /// </summary>
        /// <param name="authenticationOption">One of the System.Web.Profile.ProfileAuthenticationOption values, specifying whether anonymous, authenticated, or both types of profiles are returned.</param>
        /// <param name="userInactiveSinceDate">A System.DateTime that identifies which user profiles are considered inactive. If the System.Web.Profile.ProfileInfo.LastActivityDate of a user profile occurs on or before this date and time, the profile is considered inactive.</param>
        /// <returns>The number of profiles in which the last activity date occurred on or before the specified date.</returns>
        public override int GetNumberOfInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
        {

            int inactiveProfiles = 0;

            ProfileInfoCollection profiles = GetProfileInfo(authenticationOption, null, userInactiveSinceDate, 0, 0, out inactiveProfiles);

            return inactiveProfiles;
        }

        //Verifies input parameters for page size and page index.
        private static void CheckParameters(int pageIndex, int pageSize)
        {
            if (pageIndex < 1 || pageSize < 1)
                throw new ApplicationException(ERR_INVALID_PARAMETER + " page index.");
        }

        //GetProfileInfo
        //Retrieves a count of profiles and creates a 
        //ProfileInfoCollection from the profile data in the 
        //database. Called by GetAllProfiles, GetAllInactiveProfiles,
        //FindProfilesByUserName, FindInactiveProfilesByUserName, 
        //and GetNumberOfInactiveProfiles.
        //Specifying a pageIndex of 0 retrieves a count of the results only.
        private static ProfileInfoCollection GetProfileInfo(ProfileAuthenticationOption authenticationOption, string usernameToMatch, object userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
        {

            ProfileInfoCollection profiles = new ProfileInfoCollection();

            totalRecords = 0;

            // Count profiles only.
            if (pageSize == 0)
                return profiles;

            int counter = 0;
            int startIndex = pageSize * (pageIndex - 1);
            int endIndex = startIndex + pageSize - 1;

            DateTime dt = new DateTime(1900, 1, 1);
            if (userInactiveSinceDate != null)
                dt = (DateTime)userInactiveSinceDate;

            /*
            foreach(CustomProfileInfo profile in dal.GetProfileInfo((int)authenticationOption, usernameToMatch, dt, applicationName, out totalRecords)) {
                if(counter >= startIndex) {
                    ProfileInfo p = new ProfileInfo(profile.UserName, profile.IsAnonymous, profile.LastActivityDate, profile.LastUpdatedDate, 0);
                    profiles.Add(p);
                }

                if(counter >= endIndex) {
                    break;
                }

                counter++;
            }
            */
            return profiles;
        }
    }
}

这就是我在控制器中使用它的方式:

    public ActionResult AddTyreToCart(CartViewModel model)
    {

        string profile = Request.IsAuthenticated ? Request.AnonymousID : User.Identity.Name;

    }

我想调试:提供不同cookie的2个用户如何获得相同的profileid?

编辑

这是 getuniqueid 的代码

public int GetUniqueID(string userName, bool isAuthenticated, bool ignoreAuthenticationType, string appName)
{

  SqlParameter[] parms = {
            new SqlParameter("@Username", SqlDbType.VarChar, 256),
            new SqlParameter("@ApplicationName", SqlDbType.VarChar, 256)};
  parms[0].Value = userName;
  parms[1].Value = appName;

  if (!ignoreAuthenticationType)
  {
    Array.Resize(ref parms, parms.Length + 1);
    parms[2] = new SqlParameter("@IsAnonymous", SqlDbType.Bit) { Value = !isAuthenticated };
  }

  int userID;

  object retVal = null;
  retVal = SqlHelper.ExecuteScalar(ConfigurationManager.ConnectionStrings["SQLOrderB2CConnString"].ConnectionString, CommandType.StoredProcedure, "getProfileUniqueID", parms);

  if (retVal == null)
    userID = CreateProfileForUser(userName, isAuthenticated, appName);
  else
    userID = Convert.ToInt32(retVal);
  return userID;
}

这是SP:

CREATE  PROCEDURE [dbo].[getProfileUniqueID]

@Username VarChar( 256),
@ApplicationName VarChar( 256),
@IsAnonymous bit = null
AS
BEGIN

    SET NOCOUNT ON;
/*
[getProfileUniqueID]

created 
08.07.2009  mf

Retrive unique id for current user

*/
SELECT UniqueID FROM dbo.Profiles WHERE Username = @Username 
AND ApplicationName = @ApplicationName
AND IsAnonymous = @IsAnonymous or @IsAnonymous = null

END
4

4 回答 4

1

我没有深入研究这一点,但有一件事确实让我眼前一亮。

在您的 where 子句中更改

@IsAnonymous = null

@IsAnonymous IS NULL

当@IsAnonymous 为空时,你想发生什么?您可能需要在 where 子句中添加一些括号。

SELECT UniqueID FROM dbo.Profiles 
WHERE Username = @Username 
    AND ApplicationName = @ApplicationName
    AND (IsAnonymous = @IsAnonymous OR @IsAnonymous IS NULL)

你们两个收到相同个人资料数据的用户吗?如果是这样,从那里开始。我会先通过存储过程运行它们。这将是容易和快速的。

于 2010-03-02T15:36:18.960 回答
1

这是一种非常难以解决的问题。我们在 ASP.NET 应用程序(不是 MVC)中遇到了类似的问题。我建议您可以先设置一个单独的 cookie 来识别用户,完全绕过 ASP.NET 配置文件系统。然后,您可以检查该 cookie 中的身份是否与配置文件中的身份相匹配。如果没有,那么您可以 1) 注销用户,以便至少他们无法访问其他人的数据,以及 2) 收集一些诊断信息 - 完整的 HTTP 请求详细信息将是一个开始。如果这没有建立任何类型的模式,您可以开始记录用户的所有 HTTP 请求,以查看他们的请求历史记录中是否有模式可以帮助您重现问题。

在我们的案例中,问题最终变成了一种愚蠢的本土缓存机制。应用程序将尝试在 ASP.NET 中缓存静态文件(例如图像),并且 cookie 与它们一起缓存。在重负载下,用户有时会使用其他用户的 cookie 加载图像并假设其他用户的身份。您的情况可能完全不同,但这可能会给您一些关于要寻找的事物类型的线索。

于 2010-03-02T00:19:38.563 回答
0

每当发生此类问题时...我已经看到以下原因...

  1. 缓存
  2. 静态变量

您可以尝试在没有静态变量的情况下编写此代码并检查问题是否解决?

问候, 拉胡尔

于 2010-03-08T14:34:32.933 回答
0

给定的来源似乎没问题,但如果没有所有相应的源代码(例如,B2CShop.DAL.UserRepository 类的所有使用方法),甚至可能是数据库方案,我就无法做出深刻的陈述。

首先是检查数据库中的数据是否已损坏,也就是说,某些用户可能实际上拥有相同的唯一 ID 或相同的用户名/应用程序/同名组合。如果 uniqueid 是主键,则可以排除此项。

于 2010-03-02T15:10:38.743 回答