这可能是一个过于自以为是的问题,但寻求帮助!
我一直在尝试优化我的ASP.NET MVC程序结构。我刚刚在预览版5中开始使用它,这是我第一次涉足业务应用程序开发 - 所以每次都是新的!
在控制器级别,我有一个服务对象负责与存储库通信并负责所有业务逻辑。在动作级别,我有一个对象,它包含所有视图数据 - 用户输入和生成的输出 - 我将其称为视图对象(这是一个通用术语吗?)。与我看到的大多数示例不同,此对象不是数据库对象,而是特定于视图的对象。
所以现在我想添加用户验证。问题是,我不知道该把它放在哪里。在Service层中,我最有意义。 Service层负责所有业务逻辑,验证是业务逻辑。另一方面,我看到的大多数验证框架都用于验证对象,这使我认为视图对象应该是验证感知的。最后,有一些验证方法需要数据库连接(例如,检查用户输入字段是否具有相应的数据库记录),并且视图对象没有数据库的概念,只有服务。
所以我看到的一些选项是:
我相信还有更多。我很好奇其他人如何处理MVC意义上的用户输入验证。我以前使用过企业验证块,并且喜欢能够为所有东西使用股票验证器,但我不确定如何使它适合单独的视图对象和服务层。如果他们(查看对象/服务)是同一个对象,这可能很容易,这可能是人们做的事情?就像我说的那样,它对我来说是全新的,我正在寻找最佳实践/模式。
答案 0 :(得分:6)
我通常在提交表单时在控制器操作中进行基本验证(必填字段,电子邮件格式等)。然后我让业务层处理需要业务知识的验证。我通常也会仔细检查业务层中的基本内容,因此如果我通过Web服务公开该逻辑或稍后在其他应用程序中使用它,我仍然会在最重要的地方进行验证(IMO)。
答案 1 :(得分:4)
这个
有一些有趣的链接就个人而言,我已将验证添加到我的服务层对象(前两个链接)。这样,如果任何控制器中的任何方法决定调用我的服务方法..逻辑全部被检查并在一个位置装箱。 DRY
那说,我也有一些UI验证(第3个链接)..减少往返时间。
最后,当前的MVC dll能够将错误消息传递回UI ..因此视图可以很好地显示它们。退房: -
HTH!
答案 2 :(得分:2)
查看以下博文
http://blog.codeville.net/2008/09/08/thoughts-on-validation-in-aspnet-mvc-applications/ http://www.emadibrahim.com/2008/09/08/client-server-side-validation-in-aspnet-mvc/
答案 3 :(得分:1)
看一下S#arp架构项目。在模型上处理验证,以确保在无效状态下没有实体持久保存到数据库。它通过使用NHibernate.Validator并将其附加到NHibernate的保存和更新事件来实现。
就个人而言,这种方法对我来说最有意义,因为您不必在多个控制器中复制验证逻辑。
答案 4 :(得分:1)
我担心我的帖子没有回复,很高兴出错!
我之前已经阅读过这些链接,但可能是一个月或更久以前,并且用我现在理解的内容重新阅读这些链接非常有帮助。我非常喜欢史蒂夫桑德森的滑动比例,但希望他能展示一个在频谱右端验证某些东西的例子。
作为他博客中的一个例子,他说:“'用户名必须是唯一'可能会在您的数据库中强制实施”。那会是这样的:
public static void SavePerson(Person person)
{
// make sure it meets some format requirement
// in this case the object is responsible for validation and the service layer is the caller
person.EnsureValid();
// todo: action to verify username is unique by checking database
// in this case the service layer is responsible for calling and implementing validation
// todo: action to save to database
}
这是有道理的,并且我会很难掌握验证的位置,因为它位于服务层(非常独特的名称)和视图对象(验证格式)中。
我所担心的另一个问题是服务层开始使用验证逻辑进行演示。也许把它分成不同的类或什么?在我的情况下,一些验证逻辑可能在服务之间共享,所以我想想一个DRY方式来实现它。有趣的事情要考虑!
Emad Ibrahim的链接很棒,一旦我开始更多地了解这个过程,我就会寻找一种方法来使用相同的规则集生成javascript客户端验证,而不必重复代码。他已经有了:))我听说过S#arp,但没有坐下来看看它是如何工作的(我不确定是否有很多演示方式,或者下载代码是演示!)。我不确定是否只对数据库模型进行验证就足够了。在我看来,有关数据库的大量有效模型状态,业务逻辑会说这些状态是无效的(例如日期范围/必须在/之前/之后等)。这些是破坏我大脑的案例:)
另外,我喜欢的一个链接(在我看到Emad用BLL回复Steves帖子并且不知道它意味着什么之后用Google搜索了...呃):
http://en.wikipedia.org/wiki/Business_logic_layer
所以我不知道,但我认为这是我写的模型:处理数据交互的业务流程对象,以及逻辑模型而不是数据库模型的业务实体。我想我需要开始阅读一些更基本的模式和实践,以便更好地理解这些概念(看起来很多这是Java人与.NET人员编写的东西)。可能是退一步的时候了:))
答案 5 :(得分:0)
我在最近的一个项目中遇到过同样的问题。首先,为了重申这个问题,我试图遵循DDD的以域为中心的方法。我将实体组成聚合,可以自我验证,并且存储库验证保存时的有效性。 UI还可以从聚合中获取有效性信息,以便向客户端显示错误反馈。一般方法是尽可能利用ASP.NET MVC的模型绑定和验证/表单UI帮助程序。这创建了简单的UI流程:1)绑定,2)验证,3)如果有效,保存,否则重新填充视图。
但是,当涉及DDD服务时,如何利用ASP.NET MVC以及这个简单的流程并不是直接明显的。最初,我开发了我的服务:
public class SomeProcessService
{
public Result Execute(int anAggregateID, int anotherAggregateID, string someData)
{
// validate input
// if invalid, return failures
// else
// modify aggregates
// using (transaction)
// {
// save aggregates
// commit
// }
// return success
}
}
问题在于验证和保存在方法中有着千丝万缕的联系。为了利用MVC模型绑定,我们需要一些用作绑定模型的东西。我正在重构这个:
public class SomeProcessService
{
public class Request : IValidateable
{
public int AggregateID {get;set;}
public int AnotherAggregateID {get;set;}
public string SomeData {get;set;}
public Result Validate()
{
// validation
}
}
public void Execute(Request request)
{
// validate input by calling request.Validate()
// if invalid, throw new ValidationException(request)
// else
// modify aggregates
// using (transaction)
// {
// save aggregates
// commit
// }
// return success
}
}
这会将Parameter Object pattern重新用于单独的方法输入验证。我可以绑定到控制器中的SomeProcessService.Request对象,并在那里获取验证信息。如果一切顺利,我可以从我的控制器使用Request对象作为参数启动服务调用。这种方法似乎很乐意将DDD服务与ASP.NET MVC验证要求结合起来。