自定义服务器端Profile Service支持

间隙填充
正睿科技  发布时间:2008-06-30 08:57:11  浏览数:1928

  在ScriptManager中指定Profile Service的Path

  在ASP.NET AJAX的客户端脚本中,如果没有使用Sys.Services.ProfileService.set_path方法来指定一个提供Profile Service的地址,就会使用默认的地址,它会使ASP.NET AJAX的Profile Service使用程序集中特定的类。一般来说,我们不需要手动调用Sys.Services.ProfileService.set_path方法,只需要在ScriptManager中指定即可。如下:

<asp:ScriptManager ID="ScriptManager1" runat="server" ScriptMode="Debug">
<ProfileService Path="CustomProfileService.asmx" />
</asp:ScriptManager>

  打开页面后,可以在页面中发现如下的JavaScript代码:

Sys.Services.ProfileService.set_path('/CustomProfileService.asmx');

  出现“/”是因为我测试的页面在根目录下。因此,Profile Service就会使用指定的Web Service,而不是默认的Web Service类。


  实现自己的Web Service类

  指定了自己的Web Service类,自然就要实现自己的类了。事实上,我们要实现的就是3个方法。就这个方面来说,ASP.NET AJAX中Profile Service使用的默认的Web Service类Microsoft.Web.Profile.ProfileService是我们绝佳的参考。因此,我们在这里分析一下这些方法,对于我们的自定义工作是非常有帮助的。

  可能需要注意的一点是,我们在实现这些方法时,从理论上来讲参数类型不用完全和 Microsoft.Web.Profile.ProfileService中的方法完全相同。ASP.NET AJAX的能够根据参数的类型尽可能地将获得的JSON字符串转换成需要的类型。不过事实上,似乎 Microsoft.Web.Profile.ProfileService里那些方法的参数选择已经是非常合理的。另外,由于客户端Profile Service代码不太容易修改(事实上客户端也不是不能扩展,最极端的情况,不就是我们自己实现一个ProfileService吗?),为了保持返回的JSON字符串能够被正确处理,这些方法的返回值一般来说可以不变。

  GetAllPropertiesForCurrentUser方法

  这个方法的作用是获得当前用户所有的Profile信息,它没有输入的参数,返回的JSON字符串形式如下:

{
'ZipCode' : ...,
'Address.City' : ...,
'Address.State' : ...
}

  它通过GroupName.ProfileName的形式来表示Profile Group,Group中的每一个Profile需要分别列出,而“...”则表示对应Profile值的JSON字符串。

  在Microsoft.Web.Profile.ProfileService里,这个方法的代码如下:

[WebMethod]
public IDictionary<string, object> GetAllPropertiesForCurrentUser()
{
ProfileService.CheckProfileServicesEnabled();
return ProfileService.GetProfile(HttpContext.Current, null);
}

  GetPropertiesForCurrentUser方法

  这个方法的作用是获得当前用户指定的Profile信息,它的输入JSON字符串形式如下:
  ['ZipCode', 'Address.City', 'Address.State']

  它的返回值的JSON字符串和GetAllPropertiesForCurrentUser相同,就不再赘述了。

  在类中,这个方法的代码如下:

[WebMethod]
public IDictionary<string, object> GetPropertiesForCurrentUser(string[] properties)
{
ProfileService.CheckProfileServicesEnabled();
return ProfileService.GetProfile(HttpContext.Current, properties);
}
  可以看到,GetAllPropertiesForCurrentUser和GetPropertiesForCurrentUser中都是使用了ProfileService.GetProfile静态方法来获得结果的,我们来仔细看一下这个方法的实现。如下:
GetProfile静态方法
1 internal static IDictionary<string, object> GetProfile(HttpContext context, string[] properties)
2 {
3     // 当前用户的Profile
 4     ProfileBase profile = context.Profile;
5
6     // 如果没有profile,则返回null
 7     if (profile == null)
8     {
9         return null;
10     }
11
12     // 作为结果返回的字典
13     IDictionary<string, object> dictResult = new Dictionary<string, object>();
14
15     // 如果properties为null,表示需要返回所有的参数
16     if (properties == null)
17     {
18         // 枚举web.config中注册的每一个Profile属性设置
19         foreach (SettingsProperty property in ProfileBase.Properties)
20         {
21             // 获得Profile属性名称
22             string name = property.Name;
23
24             // 如果web.config配置文件里没有定义ReadAccessProperties,
25             // 或者该Profile属性被定义在ReadAccessPropeties中。
26             if ((ProfileService._allowedGet != null) && ProfileService._allowedGet.ContainsKey(name))
27             {
28                 // 则准备输出
29                 dictResult.Add(name, profile[name]);
30             }
31         }
32
33         // 返回结果
34         return dictResult;
35     }
36
37     // 枚举参数的每一项,它们是需要输出的Profile信息
38     foreach (string prop in properties)
39     {
40         // 如果web.config配置文件里没有定义ReadAccessProperties,
41         // 或者该Profile属性被定义在ReadAccessPropeties中。
42         if ((ProfileService._allowedGet != null) && ProfileService._allowedGet.ContainsKey(prop))
43         {
44             // 则准备输出
45             dictResult.Add(prop, profile[prop]);
46         }
47     }
48
49     // 返回结果
50     return dictResult;
51 }

  SetPropertiesForCurrentUser方法

  这个方法的作用是保存当前用户的Profile信息,它的输入JSON字符串形式如下:

{
'ZipCode' : ...,
'Address.City' : ...,
'Address.State' : ...
}

  而它返回的则是正确保存的Profile数量。代码如下:

[WebMethod]
public int SetPropertiesForCurrentUser(IDictionary<string, object> values)
{
ProfileService.CheckProfileServicesEnabled();
return ProfileService.SetProfile(HttpContext.Current, values);
}
  起关键作用的方法是ProfileService.SetProfile静态方法,我们来仔细看一下这个方法:
SetProfile静态方法
1 internal static int SetProfile(HttpContext context, IDictionary<string, object> profileValues)
2 {
3     // 如果没有提供保存的Profile值,则返回0
 4     if ((profileValues == null) || (profileValues.Count == 0))
5     {
6         return 0;
7     }
8
9     // 获取当前用户的Profile值
10     ProfileBase profile = context.Profile;
11
12     // 如果当前没有Profile,也返回0
13     if (profile == null)
14     {
15         return 0;
16     }
17
18     int count = 0;
19
20     // 获得当前的Serializer,
21     // 以获取JavaScriptTypeResolver和JavaScriptConverter的支持
22     WebServiceData data = WebServiceData.GetWebServiceData(context, context.Request.FilePath);
23     JavaScriptSerializer serializer = data.Serializer;
24
25     // 枚举提供的每一个Profile的值
26     foreach (KeyValuePair<string, object> pair in profileValues)
27     {
28         // 获得Profile的名称
29         string name = pair.Key;
30         if ((ProfileService._allowedSet != null) && ProfileService._allowedSet.ContainsKey(name))
31         {
32             // 通过Profile名称获得在web.config中的Profile定义
33             SettingsProperty property = ProfileBase.Properties[name];
34             // 如果存在这个Profile属性
35             if (property != null)
36             {
37                 // 获得Profile属性的类型
38                 Type type = property.PropertyType;
39                 // 调用内部的ObjectConverter.ConvertObjectToType方法进行转换,
40                 // 然后赋值给相应的Profile
41                 profile[name] = ObjectConverter.ConvertObjectToType(pair1.Value, type, serializer);
42
43                 // 已经保存的Profile属性数量加1
44                 count++;
45                 continue;
46             }
47         }
48     }
49
50     return count;
51 }