2

我正在转换在经典 ASP.Net Membership Provider 中序列化的用户配置文件数据,以便在 SimpleMembership 中使用。我无法弄清楚如何为ProfileBase系统中的每个用户获取对象。

如果特定用户已登录,我可以执行以下操作:

MyModel myModel = 
    (MyModel)HttpContext.Current.Profile.GetPropertyValue("MyKey");

其中MyKey指的是这样建立的配置文件密钥web.config

<add name="MyModel" type="MyNS.MyModel" serializeAs="Binary" />

但是,如果没有 HTTP 上下文的好处(我试图为系统中的所有用户执行此操作,而不是登录用户),我无法弄清楚如何加载配置文件并最终MyModel为每个用户加载一个实例在系统中。

我试过了:

ProfileInfoCollection profiles = 
     ProfileManager.GetAllProfiles(ProfileAuthenticationOption.All);

foreach (var profile in profiles)
{
    var pi = (ProfileBase)profile;
    // OOPS!  Unfortunately GetAllProfiles returns 
    // ProfileInfo and not ProfileCommon or ProfileBase
}

MembershipUserCollection existingUsers = Membership.GetAllUsers();
foreach (MembershipUser mu in existingUsers)
{
    mu. // OOPS! No link to the profile from the user...
}

如何检索系统中每个配置文件的ProfileCommonProfileBase实例,从而最终MyModel与每个用户关联?

4

2 回答 2

0

由于我找不到这个问题的答案,我选择直接从 SQL 读取配置文件数据。

事实证明,格式很简单。在 aspnet_Profile 中:

  • PropertyNames 使用 NameOfProperty:TypeFlag:Offset:Length 格式(对所有属性重复)。
  • FlagType 是字符串的“S”或二进制的“B”
  • 偏移量是相应数据字段中的偏移量
  • 长度是相应数据字段中数据的长度
  • PropertyValuesString 包含所有没有分隔符的字符串属性。
  • PropertyValuesBinary 包含所有没有分隔符的二进制属性。
  • BinaryFormatter 用于序列化二进制(非字符串)属性

这是我为解析数据而编写的一小段代码:

private class Migrate_PropNames
{
    public string Name { get; set; }
    public bool IsString { get; set; }
    public int Offset { get; set; }
    public int Length { get; set; }
}
....

Dictionary<string, Migrate_PropNames> propInfo = ParsePropInfo(propertyNames);
// Example string property
string firstName = Migrate_GetString(propInfo["FirstName"], propertyValuesString);
// Example binary property
MyType myType = 
    Migrate_GetBinary<MyType>(propInfo["MyTypeKey"], propertyValuesBinary));


private T Migrate_GetBinary<T>(Migrate_PropNames propNames, byte[] propertyValuesBinary)
{
    byte[] data = new byte[propNames.Length];
    Array.Copy(propertyValuesBinary, propNames.Offset, data, 0, propNames.Length);

    var fmt = new BinaryFormatter();
    using (var ms = new MemoryStream(data))
    {
        T original = (T)fmt.Deserialize(ms);
        return original;
    }
}

private string Migrate_GetString(Migrate_PropNames propNames, string propertyNames)
{
    return propertyNames.Substring(propNames.Offset, propNames.Length);
}

private Dictionary<string, Migrate_PropNames> ParsePropInfo(string propertyNames)
{
    Dictionary<string, Migrate_PropNames> result = new Dictionary<string,Migrate_PropNames>();

    string[] parts = propertyNames.Split(new string[] { ":"}, StringSplitOptions.RemoveEmptyEntries);
    for (int i = 0; i < parts.Length; i += 4)
    {
        Migrate_PropNames pn = new Migrate_PropNames();
        pn.Name = parts[i];
        pn.IsString = (parts[i + 1] == "S");
        pn.Offset = int.Parse(parts[i + 2]);
        pn.Length = int.Parse(parts[i + 3]);

        result.Add(pn.Name, pn);
    }

    return result;
}

我希望这可以帮助别人。我很乐意接受正确显示如何使用 API 的不同答案。

于 2013-02-09T21:27:25.850 回答
0

ProfileInfoorMemberShipUser对象,您应该可以ProfileBase使用ProfileBase.Create(string username).

于 2014-10-10T12:43:16.737 回答