【问题标题】:Asp.NET MVC - Validate a Model Outside of the ControllerAsp.NET MVC - 在控制器之外验证模型
【发布时间】:2013-11-19 12:57:06
【问题描述】:

我正在构建一个 ASP.NET MVC 项目并采用以下架构:

  • 一个具有模型、验证、dto、逻辑等的Core项目。
  • 作为我的 REST API 的 ServiceStack API 项目
  • 作为 UI 的 ASP.NET MVC Web 项目

所以,假设我想添加一个用户。我在 Core 项目中定义了一个NewUserInputModel。我给它一些数据注解,比如[Required]。完成此操作后,Web 项目将根据这些注释执行客户端验证。

我的问题是关于服务器端验证。我想使用客户端上使用的相同规则验证NewUserInputModel,并且我想运行验证天气NewUserInputModel来自API网络项目。

我意识到我可以从 Web 项目中的控制器调用 ModelState.IsValid - 但我想从 Core 项目中调用该验证,以便所有验证逻辑都存在在核心中。这样,无论这个模型如何进入 Core 逻辑,我总是调用相同的验证。我不想将System.Web 引用泄露到我的Core 项目中。

这是一个合理的设计吗?我想是的 - 但如果它有什么味道,我会很高兴听到它。

提前感谢您的帮助。

【问题讨论】:

    标签: validation asp.net-mvc-4


    【解决方案1】:

    我认为你的方法很好。将一组模型映射到另一组可能会带来一些错误。

    您要查找的代码是:

    using System.ComponentModel.DataAnnotations;
    
    var context = new ValidationContext(model, serviceProvider: null, items: null);
    var results = new List<ValidationResult>();
    var isValid = Validator.TryValidateObject(model, context, results);
    if (!isValid)
        throw new Exception("Model is not valid because " + string.Join(", ", results.Select( s => s.ErrorMessage).ToArray()));
    

    详情见http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationcontext.aspxhttp://odetocode.com/blogs/scott/archive/2011/06/29/manual-validation-with-data-annotations.aspx

    【讨论】:

      【解决方案2】:

      我通常将我的视图模型保存在 Web 项目中,并使用ModelState 属性在控制器中进行输入 验证。如果成功,我将它们映射到域模型(位于核心层)并将它们发送到服务(也可能是核心)层中的服务。服务层验证业务规则,如果成功,它会调用存储库来执行所需的操作并将操作结果返回给控制器。

      将视图模型保留在 Web 项目中还允许您使用 MVC 验证属性,例如 RemoteAttribute

      我并不是说你的设计有味道,但我确实认为将表示逻辑与核心层分开是件好事。

      【讨论】:

        【解决方案3】:

        我通过快速思考的方法是做类似的事情。在业务层创建

        public class ValidationMessage
        {
            public ValidationMessage(string message, ValidationMessageType messageType)
            {
                Message = message;
                MessageType = messageType;
            }
        
            public string Message { get; private set; }
            public ValidationMessageType MessageType { get; private set; }
        }
        
        public enum ValidationMessageType
        {
            Info,
            Warning,
            Error,
        }
        

        现在有一个服务示例

        public interface ISomeService
        {
            List<ValidationMessage> Edit(SomeModel item);
        }
        

        现在在控制器中调用服务并将验证消息传递给视图。可能需要使用 ViewBag 并传递整个列表。在视图中,您可以突出显示信息、警告、错误。例如,您可以返回一些带有 Info 类型的成功消息,或者什么都不返回,然后在控制器中创建成功消息。

        通常,这种方法编码更多,但灵活性更高。理想情况下,服务会验证所有内容,但对于较小的项目,为了避免验证重复,正如 Henk Mollema 在他的回答中所说,您可以通过 ViewModel 进行用户输入验证,并且在服务中只验证关键业务规则。

        ValidationMessageType 也可能有点过头了,所以可以只从服务中返回 List 作为错误列表,而空列表意味着成功。

        【讨论】:

          【解决方案4】:

          进行混合验证也很有用,因此将 DataAnnotations 与自定义验证逻辑混合

          这可能会有所帮助 http://www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2

          【讨论】:

            猜你喜欢
            • 2021-12-29
            • 1970-01-01
            • 1970-01-01
            • 2015-02-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-12-24
            • 1970-01-01
            相关资源
            最近更新 更多