业务/服务层中的 ASP.NET 复杂验证
Posted
技术标签:
【中文标题】业务/服务层中的 ASP.NET 复杂验证【英文标题】:ASP.NET complex validation in business / service layer 【发布时间】:2017-01-02 20:40:44 【问题描述】:我问这个是因为经过长时间的搜索,我还没有找到一个好的答案......
这就是我想要的:
示例:我有一个域模型“JobPosting”,如果它仍然是草稿,用户应该能够将状态更改为已发布。在发布之前,我不仅必须验证模型属性,还必须验证关于用户帐户、注册公司等的许多不同要求。所有这些验证逻辑都放入服务层。到目前为止一切顺利...
这是我的服务层的样子:
public IValidationResult ValidatePublish(JobPosting jobPosting)
...
public void Publish(JobPosting jobPosting)
jobPosting.State = JobPostingState.Published;
...
任何我的控制器:
public ActionResult Publish(PublishViewModel model)
...
var validationResult = _jobService.ValidatePublish(jobPosting);
if(validationResult.Success)
_jobService.Publish(jobPosting);
...
...
现在我的问题是:
我希望能够从控制器调用 ValidatePublish 以在视图中显示验证错误。但是,当验证失败时,我绝不能发布作业。 因此,为了让我的代码更健壮,我在服务层的 Publish 方法中添加了第二个验证检查:
public void Publish(JobPosting jobPosting)
if(ValidatePublish(jobPosting).Success)
jobPosting.State = JobPostingState.Published;
...
但我对这种方法感觉不太好,因为现在在每个控制器发布请求期间验证正常时,我会调用两次验证。
你怎么看。第二个电话太多了吗?有更好的方法吗? 我问是因为我的整个应用程序看起来像那样,如果我忘记了控制器中的验证调用,我最终可能会在数据库中得到一个不允许的域模型状态。这就是我在每个服务方法中添加第二个验证检查的原因。
提前感谢您对此的看法!!!
【问题讨论】:
“我两次调用验证”你第二次调用验证在哪里? 控制器中的第一次调用:var validationResult = _jobService.ValidatePublish(jobPosting);第二次在服务方法发布:if(ValidatePublish(jobPosting).Success) 那你为什么要在方法中再次验证?您可以直接发布。 【参考方案1】:一种快速的解决方案可能是让Publisher
类需要JobPosting
和IValidationResult
对象作为参数。
public void Publish(JobPosting jobPosting, IValidationResult validation)
if (validation.IsValid)
jobPosting.State = JobPostingState.Published;
// other work here...
然后您的Controller
可以调用Validator
,接收IValidationResult
并在需要时将其传递回表示层。否则转给Publisher
public ActionResult Publish(PublishViewModel model)
var validationResult = _jobService.ValidatePublish(jobPosting);
if(validationResult.Success) _jobService.Publish(jobPosting, validationResult);
else return View("error", validationResult);
编辑:
更简洁的解决方案可能是让Publisher
类返回PublishAttempt
结果。
public class PublishAttempt : IValidationResult
public enum AttemptOutcome get; set;
public ActionResult Publish(PublishViewModel model)
var attempt = _jobService.Publish(jobPosting);
if (attempt.Success) return View("success");
else return View("error", attempt.ValidationResults);
【讨论】:
谢谢!是的,这也是一种方法......但我不喜欢它的是我可以传递任何验证结果实例......甚至可以创建一个始终有效的新空实例。 哦,谢谢 :-) 是的,我喜欢这样...也许我将您的想法与我的最后一个答案结合起来 :-) 只是因为我需要仅调用验证方法的能力...例如当我想通过 ajax 调用服务验证以“实时”显示错误时【参考方案2】:我刚想到以下内容……你怎么看:
我将服务方法更改为:
public IValidationResult Publish(JobPosting jobPosting, bool validateOnly = false)
var validationResult = ValidatePublish(jobPosting);
if(validateOnly) return validationResult;
jobPosting.State = JobPostingState.Published;
...
return validationResult;
然后在控制器中,我总是只调用 Publish 方法,不再调用额外的 ValidatePublish:
public ActionResult Publish(PublishViewModel model)
var validationResult = _jobService.Publish(jobPosting);
if(!validationResult.Success) return View("error", validationResult);
当我只需要简单的验证时,我会这样做
var validationResult = _jobService.Publish(jobPosting, true);
这样做可以吗? 还是正常的服务调用返回IValidationResult不好看?
【讨论】:
或者你认为每个服务方法实现某种结果更好?以上是关于业务/服务层中的 ASP.NET 复杂验证的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET MVC IOC依赖注入之Autofac系列开篇