0

我正在构建的 Web 应用程序的一部分是用户管理。因此我需要一个用户实体。有几个涉及用户的用例,例如:

  • 显示用户列表
  • 显示单个用户
  • 编辑用户联系信息
  • 编辑用户登录信息(用户名和密码)
  • 创建一个新用户

其中大多数需要访问相同的属性,因此在所有情况下使用相同的实体会很好。然后,如果我使用例如 DisplayName 属性,所有地方都将使用相同的显示名称:

[Display(Name = "Username")]
public string Username { get; set; }

编辑用户时,我也想使用验证属性:

[Display(Name = "Username")]
[Required(ErrorMessage = "Username must be provided.")]
public string Username { get; set; }

当我有一个编辑了某些属性但不是全部属性的视图时,就会出现问题。在“编辑用户联系信息”用例中,有些东西可以编辑(例如电话号码),但有些东西不能(例如用户名)。但是如果我使用相同的实体,所有具有验证属性的属性都将被验证。

我在 StackOverflow 上找到了一些验证问题的解决方案,但我想知道在创建实体和视图模型时是否有任何“最佳实践”?

我更喜欢尽可能多地重复使用,以确保例如显示名称和验证在整个应用程序中保持一致。但通常这会导致诸如上述问题或复杂的继承层次结构之类的问题。

我应该有:

  • 几个相似(但不相同)的实体?
  • 几个相似(但不相同)的视图模型?
  • 一个实体+验证问题等问题的解决方法?
  • ...

有什么建议么?你自己如何做到这一点?

我应该注意,我经常显示的信息不仅仅是正在编辑的内容。例如,在编辑联系信息时,我将输入一些属性(例如 PhoneNumber 和 EmailAddress),但仍将其他属性作为信息显示给用户(例如用户名)。

(如果重要的话,我正在使用 ASP.NET MVC 3)

4

3 回答 3

1

我会考虑使用每个视图方法的视图模型。虽然这看起来像是额外的工作,但我相信它会让你的控制器和视图更加简洁易懂。很清楚你在每种情况下的意图是什么,你仍然会得到强类型。

它还解决了另一个可能存在批量分配漏洞的问题(绑定包含/排除也是如此)。

最后使用这种技术不需要任何额外的编码位,有些人可能认为这些位很神奇,或者至少需要更仔细地阅读代码来了解这个视图对模型的作用与其他视图相比,与其他视图相比,因为所有三个以稍微不同的方式使用相同的模型。

于 2012-10-09T14:41:09.627 回答
1

如果验证是您唯一的问题,我建议使用 fluentvalidation (http://fluentvalidation.codeplex.com)。这样您就可以为每个场景(每个操作)设置验证规则。

我会为每个场景使用单独的视图模型,并利用 fluentmvc 中的 RuleSets 功能,这样我就不会违反 DRY。

于 2012-10-09T14:26:01.023 回答
0

要将变量验证逻辑添加到您的模型,您可以实现 IValidatableObject:

public class VariableValidationEntity : IValidatableObject
{
    public string UserName { get; set; }
    public bool ValidateMe { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (ValidateMe)
        {
            if (string.IsNullOrWhiteSpace(UserName))
            {
                yield return new ValidationResult("Username Required", new[] { "UserName" });
            }
        }
    }
}

然后,您可以根据使用模型的环境指定验证逻辑。

或者,您可以为每个用例创建一个视图模型,甚至可以从基本模型中派生出经过验证的模型:

public class NonValidatedEntity
{
    public string UserName { get; set; }
}

public class ValidatedEntity : NonValidatedEntity, IValidatableObject
{
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (string.IsNullOrWhiteSpace(UserName))
        {
            yield return new ValidationResult("Username Required", new[] { "UserName" });
        }
    }
}

在我看来,后一种选择会更干净。

于 2012-10-09T14:07:30.033 回答