您可以使用其控制器中的属性验证模型实例吗?

时间:2013-12-31 00:54:05

标签: c# asp.net-mvc validation

假设我有一个看起来像这样的控制器:

public class ProjectController : Controller
{
    private IProjectRepository projectRepository;

    public ProjectController()
    {
        DBContext context = new DBContext();
        this.projectRepository = new ProjectRepository(context);
    }

    public ActionResult Create(Project project)
    {
        if (ModelState.IsValid)
        {
            // do whatever
        }
        else
        {
            return View(project);
        }
    }
}

并且假设这是一个看起来像这样的模型的控制器:

public class Project : IValidatableObject
{
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        // this is where I would like to add code
    }
}

我的问题是:验证代码中是否真的没有办法在控制器上引用projectRepository对象?是的,我可以在技术上为控制器上的Create()函数添加准验证,在那里进行检查,并直接添加错误 - 但在实际情况中,有许多操作都会执行相同的验证,与您尝试创建(或编辑,复制或其他任何)的模型紧密相关。但是它与模型绑定到同一模型的其他现有实例,只有控制器知道如何查询。有没有办法解决这个问题?

(目标是检查验证中的当前模型对象是否与已存在的模型对象不同;我对其他如何做的建议持开放态度,它看起来很明显 应该是标准验证代码的工作,使用IValidatableObject或使用ValidationAttribute。但我不是.net MVC验证的专家,或者就此而言,.net MVC。)

谢谢!

3 个答案:

答案 0 :(得分:3)

IValidatableObject属于DataAnnotations命名空间。在我看来,Data Annotations非常适合输入验证。当他们开始应用复杂的业务规则时,您的域模型的有效性取决于其他域模型的状态。

当发生这种情况时,引入服务层。将所有业务规则放在那里,并允许服务调解模型之间的对话。在一天结束时,服务应该是您与模型通信的接口。

这是我经常对自己说的话,“嘿,你的应用程序现在已经达到'中等复杂度'阶段”! :)

可以在此处找到较旧但仍然相关的教程:http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs

答案 1 :(得分:1)

国际海事组织,有一个公约问题在起作用。控制器返回到客户端的模型 ViewModel ,而不是实体。当考虑哪些对象具有依赖对象的知识时,这就起到了作用。

存储库处理模型(实体),控制器处理 ViewModels 。 ViewModel实际上只是一堆数据和格式,因此在ViewModel上设置级验证没有意义。

并且真的希望业务层或存储库执行集级验证,而不是模型本身。您可以在模型创建时设置对模型库的引用,并让模型调用存储库进行集级验证。但是当你想要克隆或反序列化实体时,这就成了问题。

顺便说一下, EntityFramework 通过允许Attach断开连接的实体来解决这些问题。您可能希望使用EF而不是存储库模式。

但是对于您的直接问题,我不会尝试在实体或视图模型中执行设置级验证。

答案 2 :(得分:1)

您最好放置validation in the service layer

在线脚手架工具CamoteQ以这种方式生成模型验证码,这是自学的一个很好的参考。