StringLengthAttribute如何工作?

19

我在使用Entity Framework和ASP.NET MVC3验证模型时,使用StringLengthAttribute出现了问题。

我的模型基于一个Entity Framework实体,该实体有一个部分类,使用MetadataType属性告诉MVC在搜索元数据时要使用哪种类型。以下是代码示例:

[MetadataType(typeof(PartMetadata))]
public partial class Part { }

class PartMetadata
{
    [DisplayName("Part number")]
    [Required(ErrorMessage="* Required")]
    [StringLength(50, MinimumLength = 3, ErrorMessage = "* Part numbers must be between 3 and 50 character in length.")]
    public string Number { get; set; }

    [StringLength(255, MinimumLength=3,
        ErrorMessage="* Part descriptions must be between 3 and 255 characters in length.")]
    public string Description { get; set; }

    [DisplayName("Drawing required?")]
    public bool DrawingRequired { get; set; }
}
我遇到的问题是描述字段没有得到正确的验证。使用下面的代码,即使描述字段为空,我的模型也会被验证为OK,并且我会被重定向到控制器的索引页面。
if (ModelState.IsValid)
{
    return RedirectToAction("Index");
 }
 else
 {
     return View();
  }
如果我在描述字段上添加 RequiredAttribute,则我的模型被视为处于无效状态,我的表单被重新加载,并显示所需属性的默认错误消息。如果我随后编辑描述字段,则它会显示我在字符串长度属性中设置的验证错误消息。
这个属性应该是这样工作的吗?虽然在属性上装饰必需属性不是问题,但似乎与直觉相反,因为该字段并非必需,我只想确保如果用户输入内容,则其位于字符串长度属性的范围内。

1
据我所知,这正按照您的期望工作。它只是在验证字符串长度如果用户确实输入了内容。如果您真的希望他/她输入内容,就像您所说的那样,需要使用[Required]。您正在寻找什么行为? - Joao
1
留空被视为 null,这时会触发 [Required] 属性。 - Joao
4个回答

26

是的,这是正确的行为。StringLength验证字符串是否具有一定长度,但不要求输入该字符串。使用[Required]修饰Description,这样您既可以对字符串进行要求,StringLenght也会提供对字符串长度的限制。


1
谢谢。这真的很有道理,是空字符串让我困扰了一段时间。我已经验证过这个方法可行。谢谢。 - Benjamin Gale

1
关键字如下:

 class PartMetadata
 {
     // required keyword forces user to enter input
     [Required] 
     [DisplayName("Part number")]
     // or [Required(ErrorMessage="* Required")]

     // ErrorMessage in string only enforces when data is entered
     [StringLength(50, MinimumLength = 3, ErrorMessage = "* Part numbers must be between 3 and 50 character in length.")]
     public string Number { get; set; }

1
为什么 [Required(ErrorMessage="* Required")] 不能确保该字段是必需的,我们还需要在其前面加上 [Required] 标记? - Spyros_Spy
1
我认为前者只是在数据丢失时将DisplayName变成红色,而后者则显示错误消息。理论上,您可以打印任何您选择的错误消息。当项目丢失时,字符串长度要求也无法显示出来,即使有一个低长度> 0。最初,我以为那会起作用,然后继续尝试各种项目。还要考虑到这些属性项有时会在版本之间有所不同。 - Joseph Poirier
1
我刚刚做了一个示例,它将第二个[Required]字段标记为重复,并显示错误消息。 - Spyros_Spy
1
您的VS版本或更新已修复了该问题的错误。我有时会使用beta版并报告我认为缺乏常识的事情。我认为VS 2012没有抛出错误,但至少一个beta版因某种原因需要两者,我认为这是低效的。我不相信2013年以后的任何版本都需要两者,只需要其中之一即可。 - Joseph Poirier
1
还要考虑到原始问题是MVC 3.0,现在大多数情况下我们已经使用的是MVC 4.0或更高版本。 - Joseph Poirier

0

从标记答案到现在已经过去了十年,但是StringLength验证属性仍然不像其他验证属性一样有效。解决方法是(用于固定字符串长度验证)更改"range"验证的最小值。 当您通过StringLength构造函数设置一个值(例如36),这将设置最大值,并且无需为验证最大值设置错误消息。这个错误消息永远不会显示出来,因为您不能添加比您输入的数字更多(例如36)。另一方面,当您设置最小值时,错误消息将告诉您...

[Required(ErrorMessage = "Please enter an account Id")]
[MinLength(36, ErrorMessage = "The account Id must be {1} characters long.")]
[StringLength(36)]
[Display(Name = "Account Id")]
public string AccountId { get; set; }

0

MSDN:您可以在错误消息中使用复合格式占位符:{0} 是属性的名称;{1} 是最大长度;{2} 是最小长度。这些占位符对应于在运行时传递给 String.Format 方法的参数。

因此,您可以做什么

[StringLength(50, MinimumLength = 3, ErrorMessage = "Part {0} must be between {2} and {1} character(s) in length.")]
public string Number { get; set; }

注意 - 1 表示最大值,2 表示最小值。

^^^ 这也是关于“StringLengthAttribute 如何工作?”问题的答案的一部分。


你能解释一下为什么你可以在StringLength的构造函数中放置ErrorMessage属性吗?我找不到背后的原因。 - Duke3e33
1
@Duke3e33 https://learn.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/attributes/ 也可以参考这个 https://dev59.com/aVkS5IYBdhLWcg3wUFB0#40061119 - T.S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接