【问题标题】:Repository Pattern - Validating Object and Return Message存储库模式 - 验证对象并返回消息
【发布时间】:2017-11-07 04:32:07
【问题描述】:

我正在开发一个网站,只是想了解一下总体结构。我在后台有一个使用“存储库模式”访问的数据库。我的 UserRepository 类中有以下代码:

public bool IsValid(User user)
{
  if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress))
  {
    Message = "Email address already in use";
    return false;
  }

  return true;
}

这是在这里实现的

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(User user)
{
  if (ModelState.IsValid)
  {
    var context = new Context("DatabaseContext");
    var userRepo = new UserRepository(context);

    if (userRepo.IsValid(user))
    {
      userRepo.Add(user);
      // return to different view
    }
    else
    {
      // display userRepo.Message on page
      return View(user);
    }
  }

  return View(user);
}

我的问题是我认为我没有正确地绕过“消息”位,但我在网上找不到任何帮助我的东西(特别是在存储库周围)。我认为我应该将 IsValid 的返回类型更改为类似结果的结果(正如我在对话框中看到的那样),但我又不确定。

任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • 现在,你有一个验证标准,所以 bool 是有意义的。如果事情变得更加复杂,请考虑在错误时返回消息(字符串),然后检查它是否为空(成功时)。或者,如果需要,您可以尽可能多地使用 ModelState 在控制器中所做的工作。

标签: c# asp.net model-view-controller repository-pattern


【解决方案1】:

实现此目的的一种方法与您所建议的完全一样 - 更改IsValid的返回类型

过去,我在“业务层”中使用过类似的验证方法,它们返回 ValidationResult 的集合,其中每个返回的记录都说明模型中的验证错误,空集合将被解释为有效模型.

例如:

public class ValidationResult
{
    public string FieldName { get; set; }
    public string Message { get; set; }
}

public interface IValidator<T>
{
    IEnumerable<ValidationResult> IsValid(T model);
}

//...in your implementation
public IEnumerable<ValidationResult> IsValid(User user)
{
    //Return a new ValidationResult per validation error
    if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress))
    {
        yield return new ValidationResult
        {
            Message = "Email address already in use",
            FieldName = nameof(user.EmailAddress)
        };
    }
}

这可以由您的表示层解释以反馈给用户。

【讨论】:

  • 谢谢。您不仅给了我一个很好的解决方案,而且实际上还帮助我了解了“收益回报”的工作原理。
  • @oyyou 请检查我的答案。可能会帮助您了解更多。
【解决方案2】:

我同意你提到的问题。返回自定义类将是更好的方法 IMO。

public ValidationResult IsValid(User user)
{
  ValidationResult validationResult = new ValidationResult(true, "");
  if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress))
  {
    validationResult.Status = false;
    validationResult.Message = "Email address already in use";
    return validationResult;
  }

  return validationResult;
}

这样,StatusMessage 将为您提供所需的所有信息。首先检查状态。如果它是假的,请检查消息以获取确切的详细信息。

【讨论】:

  • 我喜欢这个。它很容易理解和实施。我将以 Mark Oliver 作为答案,因为它将让位于扩展;但这仍然有效。谢谢!
【解决方案3】:

虽然上述用户提供的解决方案很好,但我认为您这样做的方式不正确。这种验证电子邮件地址的解决方案有一些缺点。

假设如果电子邮件可用(无效,因为这无效),那么您必须返回带有错误的视图。如果所有输入的电子邮件地址都可用,那么最终用户将多次收到此错误,但整个视图将在每个请求中呈现,这不是一个好的做法。在这种情况下总是尝试使用远程验证。

在您的模型属性(电子邮件)上使用Remoteattribute,并尝试通过JsonResult 在视图中动态返回可用性消息。我给您这个演示示例,您可以随意在您的代码中实现。

[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
public JsonResult IsEmailAvailable(string emailAddress)
{
    if (!_context.Users.Any(c => c.EmailAddress == emailAddress))
    {
         return Json(true, JsonRequestBehavior.AllowGet);
    }
    return Json("Email address already taken" , JsonRequestBehavior.AllowGet);
}

OutputCacheAttribute 属性是必需的,以防止 ASP.NET MVC 缓存验证方法的结果。

并像这样装饰您的模型电子邮件属性:

//inside you model.
    [Required]
    [Remote("IsEmailAvailable", "YourControllerName")]
    [RegularExpression(@"Your email address validation regex here", ErrorMessage = "Email address is not valid .")]
    [Editable(true)]
    public string Email{ get; set; }

并在 Web.config 文件中添加这个 sn -p 以允许使用 Remote 属性:

<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

并从register 操作方法中删除以下代码。

if (userRepo.IsValid(user))
    {
      userRepo.Add(user); //write this only inside code cause you will always get valid email now.
      // return to different view
    }
    else
    {
      // display userRepo.Message on page
      return View(user);
    }

我希望这会奏效。欲了解更多信息,请阅读这篇文章。 https://msdn.microsoft.com/en-us/library/gg508808(vs.98).aspx

【讨论】:

  • 客户端验证是一个很好的补充。您仍然需要对恶意/错误请求进行服务器验证。
  • 这是提供服务器端验证。我提到客户端验证的地方。@Oliver
  • 几乎总是有一些基于业务规则的验证,例如一个电子邮件地址不能在两个用户之间重复。这就是为什么除了客户端/演示级别验证之外,业务级别验证方法是一个不错的选择。
  • 是的,我知道就是这样,所以这个答案也在做同样的事情。由于我无法在这里解释整个事情,这只是解决方案。检查 MVC 中的远程验证。这将向您展示这是如何工作的 msdn.microsoft.com/en-us/library/gg508808(vs.98).aspx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
  • 1970-01-01
  • 2012-02-15
  • 1970-01-01
  • 2020-11-30
  • 1970-01-01
相关资源
最近更新 更多