您的基本问题是您试图输入非 ASCII 字符作为电子邮件地址。
“ASCII 字符集”将您限制为美国英语字母表,恰好是拉丁字母表。
我不会说土耳其语,但正如http://aspnetwebstack.codeplex.com/workitem/714中指出的那样
在土耳其语中,“i”是小写,而“İ”是“i”的大写。
在您(和我)碰巧没有 IT 方面的拉丁字母表中,“i”是小写字母,而“I”是 i 的大写字母。
所以你有一个字符不是 EN-US ASCII 字符集的成员。
因此,排序规则设置会阻止您将非 ASCII 字符输入到数据库中,从而导致错误。
因此,您不应更改排序规则设置的评论(这将允许无效的邮件地址)。
正如所指出的,ToUpper(应该是 ToUpperInvariant)是罪魁祸首,因为它在幕后将 'i' 更改为 'İ',这不是有效的 ASCII 字符。
这是字符串/字符的 ToUpper 方法的常见问题。
例如,德语字母表包含字母 ß(Unicode U+00DF),也称为“双 s”,它首先没有对应的大写字符,因此如果您尝试使用 toUpper 比较字符串,它总是会失败,这就是为什么你应该总是使用 ToLower() 来比较字符串 - 另一个微软失败了。
ToUpper 也发生了类似的事情。
您首先需要做的是确保您的用户输入 ASCII 字符。
这是不可能的,因为他们有土耳其语键盘和语言环境,虽然小 i 看起来与 ASCII 小 i 相似,但它有不同的数字表示,因此有不同的大写字符(顺便说一句,小写也是)。
因此,在调用成员资格方法之前,您需要做的是“拉丁化/罗马化”您的输入字符串。
我在使用第三方提供的仅支持 ASCII 的软件时遇到了类似的问题,该软件在变音符号和法语重音字符上失败,并使用以下方法解决了这个问题。
您可能想检查土耳其 äöü 是否与我在这里使用的(瑞士)德语 äöü 没有不同的数字表示。
有关风险和副作用,请阅读包装说明书并咨询您的医生或药剂师。
// string str = ApertureSucks.Latinize("(æøå âôû?aè");
public static string Latinize(string stIn)
{
// Special treatment for German Umlauts
stIn = stIn.Replace("ä", "ae");
stIn = stIn.Replace("ö", "oe");
stIn = stIn.Replace("ü", "ue");
stIn = stIn.Replace("Ä", "Ae");
stIn = stIn.Replace("Ö", "Oe");
stIn = stIn.Replace("Ü", "Ue");
// End special treatment for German Umlauts
string stFormD = stIn.Normalize(System.Text.NormalizationForm.FormD);
System.Text.StringBuilder sb = new System.Text.StringBuilder();
for (int ich = 0; ich < stFormD.Length; ich++)
{
System.Globalization.UnicodeCategory uc = System.Globalization.CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
if (uc != System.Globalization.UnicodeCategory.NonSpacingMark)
{
sb.Append(stFormD[ich]);
} // End if (uc != System.Globalization.UnicodeCategory.NonSpacingMark)
} // Next ich
//return (sb.ToString().Normalize(System.Text.NormalizationForm.FormC));
return (sb.ToString().Normalize(System.Text.NormalizationForm.FormKC));
} // End Function Latinize
最后但同样重要的是,我不会使用内置的 ASP.NET 成员资格提供程序,因为它通过用户名 + 应用程序名将表连接到角色名,而不是使用唯一的 id。这意味着您将无法在不更改所有映射表的情况下更改用户或组/角色名称。我认为这样做是非常不可取的,而且绝对是愚蠢和粗心的,如果不是微软的完全危险的话。
我什至会说将这些垃圾释放到野外是无礼的。
下面的“东西”展示了这个问题的完全愚蠢,不应该被使用
CREATE TABLE [dbo].[UsersInRoles](
[Username] [varchar](255) NOT NULL,
[Rolename] [varchar](255) NOT NULL,
[ApplicationName] [varchar](255) NOT NULL,
CONSTRAINT [usersinroles_pkey] PRIMARY KEY CLUSTERED
(
[Username] ASC,
[Rolename] ASC,
[ApplicationName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
原因如下:
- 问题 1:字符串连接会使用户加入角色非常慢 - 对性能非常不利
- 问题 2:varchar - 应该是 nvarchar,除非你生活在一个只有英语的世界里
- 问题3:字段用户名和角色名的长度必须符合最新活动目录的最小规格,否则与活动目录同步会出现问题。Plus Active Directory 允许使用 Unicode 字符。
- 问题 4:没有对用户和角色表的外键引用 - 迟早会出现数据垃圾(通常更快)
- 问题 5:如果现在您更改用户名或组名,UserInRoles 将不会更新,并且用户的组映射将孤立 - 最终导致数据垃圾,左连接将带来空列,程序可能由于未处理的 NullReferenceException 而崩溃。
- 问题6:由于缺少外键引用,可以更改用户名/组名
- 问题7:数据垃圾迟早会导致上报/显示数据时出现多行
- 问题8:这里使用的主键应该是唯一约束
- 问题 9:只有一个组名,但例如组“管理员”需要本地化为多种语言,而成员资格提供者不支持。另外,组名属于一个映射表,因为一个组可以有N种语言的N个名称,因此必须确保组名在特定语言中是唯一的。
- 问题 10:此处不可见,但用户表包含字段电子邮件。这是一个彻底的失败,因为一个用户可以拥有 n 个电子邮件地址,而聪明的会员提供商应该考虑到这一点,而不是愚蠢地将用户限制为一个电子邮件地址。
- 问题 11:另外,提到的电子邮件字段限制为 128 个字符,这小于 rfc 中允许的电子邮件地址中允许的最大字符数。失败 - 迟早会有人无法输入他的邮件地址 - 即使他只有一个。有效电子邮件地址的最大长度是多少?
而且我确信 MS 提供的会员服务提供商的惨败还有很多问题。例如,使用快速散列算法 (MD5),这是这种情况下的反模式,因为它允许彩虹表攻击,尤其是在散列未加盐的情况下。如果 MS 会员提供者展示了一件事,那么这就是不设计会员提供者的方式。