2013-02-08 59 views
2

我正在轉換在SimpleMembership中使用的經典ASP.Net成員提供程序中序列化的用戶配置文件數據。我無法弄清楚如何爲系統中的每個用戶獲取ProfileBase對象。加載沒有HTTP的配置文件上下文

如果特定用戶登錄時,我可以這樣做:

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

回答

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​​的不同答案。

0

ProfileInfoMemberShipUser對象中,您應該可以使用ProfileBase.Create(string username)獲得ProfileBase一個對象。