Asp.NET MVC - 验证控制器之外的模型

时间:2013-11-19 12:57:07

标签: validation asp.net-mvc-4

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

  • 具有模型,验证,dto,逻辑等的核心项目。
  • 充当我的REST API的 ServiceStack API 项目
  • 作为UI的 ASP.NET MVC Web 项目

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

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

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

这是一个合理的设计吗?我认为是 - 但如果有什么东西闻起来,我会很高兴听到它。

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:15)

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

您正在寻找的代码是:

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

答案 1 :(得分:3)

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

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

我不是说您的设计闻起来,但我认为将表示逻辑与Core层分开是好的。

答案 2 :(得分:0)

我通过快速思考来解决这个问题的方法就是做那样的事情。在业务层创建

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作为错误列表,空列表就意味着成功。

答案 3 :(得分:0)

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

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