首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将服务验证传递回控制器?

如何将服务验证传递回控制器?
EN

Stack Overflow用户
提问于 2011-02-27 14:08:09
回答 2查看 452关注 0票数 1

我想我在这里遗漏了一些基本的东西,但我已经挖掘了两个多小时,一定是忽略了显而易见的东西。如果是这样的话,我道歉。

我有一个MVC3站点,我有一个服务层供控制器与之通信,还有一个存储库供我的服务层与之通信(所有这些都是使用IoC容器解耦的,但这在这里是无关紧要的)。我的域模型是EF4实体,在控制器、服务和存储库之间共享。

我有一个用于注册的视图模型,如下所示:

代码语言:javascript
运行
复制
public class SignupViewModel
{
    [DisplayName("Email")]
    [Required, RegularExpression(@"^.+@.+\..+$")]
    public string Email { get; set; }

    [DisplayName("Password")]
    [Required]
    public string Password { get; set; }

    [DisplayName("Confirm password")]
    [Required, Compare("Password")]
    public string PasswordConfirmation { get; set; }
}

我的用户域模型如下所示:

代码语言:javascript
运行
复制
public class User
{
    public int Id { get; set; }
    public string Email { get; set; }
    public string PasswordHash { get; set; }
    public string PasswordSalt { get; set; }
}

我有一个用于注册用户的服务方法,如下所示:

代码语言:javascript
运行
复制
public void Register(User user, string planTextPassword)
{
    //Make sure the email address is not taken.
    bool emailIsTaken = IsEmailTaken(user.Email);

    if (emailIsTaken)
    {
        //What do I do here?
    }
    else
    {
        //Create the user.
    }
}

最后,我的控制器操作将它们联系在一起:

代码语言:javascript
运行
复制
public ActionResult Signup(SignupViewModel signupViewModel)
{
    if (ModelState.IsValid)
    {
        _accountService.Register(Mapper.Map<SignupViewModel, User>(signupViewModel), signupViewModel.Password);
        _unitOfWork.Commit();
    }

    return View(signupViewModel);
}

正如您在我的服务方法中的注释中所看到的,当服务级别验证失败时,我该怎么办?正如在this question中所讨论的,我不应该抛出异常。但我不确定我是否理解了Ryan的建议,或者这是否仍然适用(例如,现在有没有更好的方法来处理MVC3,或者现在可用的其他工具,比如Fluent Validation)。

就像我说的,我想在这一点上我不能只见树木不见森林,但在过去的两三个小时里,我试图自己解决这个问题,我想我可能会有更好的运气,只是问了一个问题。

提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-27 14:38:10

我曾经试过做Ryan所说的事情。他所说的基本上是你的服务应该是这样的:

代码语言:javascript
运行
复制
public class TheService{
  ValidationResult Validate(YourType item);
  Save(YourType item);
}

其用法是首先调用Validate,如果保存成功,则调用ValidationResult。Save将再次验证实体,以确保您没有忘记验证它。不同之处在于,如果在Save调用validate时出现错误,则会抛出异常。

就我个人而言,我已经这样做过一次,以后不会再这样做了。我认为只要抛出一个异常就可以让一切变得更清晰,并且只需要更少的代码来维护。

要将错误信息返回给控制器,您需要创建自己的异常。它可能看起来像这样:

代码语言:javascript
运行
复制
public class RulesException : Exception{
   public IEnumerable<ErrorInfo> Errors {get;set;}
}

public class ErrorInfo{
  public string PropertyName {get;set;}
  public string ErrorMessage {get;set;}
}

沿着这些路线的一些东西是一个开始。要获得更好的实现,请查看xVal的源代码

注意:如果使用异常,请尽量避免在循环内执行try/catch时编写代码。当涉及到异常时,这是要避免的最重要的事情,因为它们更昂贵,但与数据库调用相比,例如,它是便宜的。

票数 2
EN

Stack Overflow用户

发布于 2011-02-27 14:29:50

如果您不想使用异常,那么除了让您的服务方法返回某种丰富的错误消息对象之外,您实际上别无选择。在链接的帖子中,我唯一强烈同意的观点是,异常(本身)不太可能产生好的错误消息。他们所做的事情是他们很难被忽视,所以你很可能意识到你有一个问题。

此外,无论如何您都必须处理异常,因为即使您在服务代码中完全避免了它们,您的代码也不是唯一可能导致抛出异常的东西。

也就是说,您可以返回一个可以表示成功或失败的类的实例,而不是让Register具有void返回类型,并且在失败的情况下有另一个列出错误的属性。这是一件有原则的事情--例如,在像Haskell这样的语言中这是很常见的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5131745

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档