Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何正确地将模型验证从控制器分离到服务中? 我正在重新设计我正在做的项目。在我现有的控制器中,我确实使用了存储库模式,但我仍然执行了一些我觉得不舒服的脚手架。这和我的一些控制器可能有10多个存储库传入(通过Ninject)。因此,我决定引入一个服务层,其中我的意图是每个控制器有一个服务,而每个服务将有多个存储库注入其中,并完成我需要的工作。到目前为止,这非常有效,但我遇到了一种困惑:如何将模型验证从控制器转移到服务层_C#_Asp.net Mvc_Entity Framework_Asp.net Mvc 5_Entity Framework 6 - Fatal编程技术网

C# 如何正确地将模型验证从控制器分离到服务中? 我正在重新设计我正在做的项目。在我现有的控制器中,我确实使用了存储库模式,但我仍然执行了一些我觉得不舒服的脚手架。这和我的一些控制器可能有10多个存储库传入(通过Ninject)。因此,我决定引入一个服务层,其中我的意图是每个控制器有一个服务,而每个服务将有多个存储库注入其中,并完成我需要的工作。到目前为止,这非常有效,但我遇到了一种困惑:如何将模型验证从控制器转移到服务层

C# 如何正确地将模型验证从控制器分离到服务中? 我正在重新设计我正在做的项目。在我现有的控制器中,我确实使用了存储库模式,但我仍然执行了一些我觉得不舒服的脚手架。这和我的一些控制器可能有10多个存储库传入(通过Ninject)。因此,我决定引入一个服务层,其中我的意图是每个控制器有一个服务,而每个服务将有多个存储库注入其中,并完成我需要的工作。到目前为止,这非常有效,但我遇到了一种困惑:如何将模型验证从控制器转移到服务层,c#,asp.net-mvc,entity-framework,asp.net-mvc-5,entity-framework-6,C#,Asp.net Mvc,Entity Framework,Asp.net Mvc 5,Entity Framework 6,例如,在myOfficeController上查看此Edit方法: [HttpPost] public async Task<RedirectToRouteResult> Edit( short id, FormCollection form, [Bind(Prefix = "Office.Coordinates", Include = "Latitude,Longitude")] Coordinate[] coordinates) { if (id

例如,在my
OfficeController
上查看此
Edit
方法:

[HttpPost]
public async Task<RedirectToRouteResult> Edit(
    short id,
    FormCollection form,
    [Bind(Prefix = "Office.Coordinates", Include = "Latitude,Longitude")] Coordinate[] coordinates) {
    if (id > 0) {
        Office office = await this.OfficesService.GetOfficeAsync(id);

        if ((office != null)
            && base.TryUpdateModel(office, "Office", new string[2] {
                "Name",
                "RegionId"
            }, form)
            && base.ModelState.IsValid) {
            this.OfficesService.UpdateOfficeAsync(office, coordinates);
        }

        return base.RedirectToAction("Edit", new {
            id = id
        });
    }

    return base.RedirectToAction("Default");
}
[HttpPost]
公共异步任务编辑(
短id,
表格收集表格,
[Bind(Prefix=“Office.Coordinates”,Include=“纬度,经度”)]坐标[]坐标{
如果(id>0){
Office=等待这个.officeservice.GetOfficeAsync(id);
if((office!=null)
&&base.TryUpdateModel(office,“office”,新字符串[2]{
“姓名”,
“区域ID”
},表格)
&&base.ModelState.IsValid){
this.officeservice.UpdateOfficeAsync(办公室,坐标);
}
return base.RedirectToAction(“编辑”,新建{
id=id
});
}
return base.RedirectToAction(“默认”);
}
与控制器的方法相比,它的问题在于我仍然从数据库中获取
Office
对象,进行更新、验证,然后再次保存。在这种情况下,复杂性增加而不是减少。以前,我在方法中调用了存储库,现在我调用调用存储库的服务来执行相同的功能。到目前为止,复杂性的增加只在我的
Edit
方法中表现出来,而在其他任何地方复杂性都大幅降低,这正是我想要的

那么,什么才是移动验证的正确方法呢?现在我想起来了,模型更新逻辑从控制器转移到服务中?欢迎推荐

以下是我的项目的结构,以供参考:

  • 数据:包含我的所有模型类
  • Data.Google.Maps:包含反序列化特定Kml所需的所有类
  • 数据.模型:包含我的数据库上下文、配置、视图模型和局部视图模型
  • 数据。存储库:包含与DbContext对话的所有存储库。因为EF本身就是一个伪存储库,所以我利用我的“存储库”作为查询数据的更具体的方式。例如:
    FindTechnicians()
    FindActivity()
  • 数据服务:包含我将使用的所有服务。这些服务将有一个或多个存储库注入其中,并在将完整的视图模型传递回控制器之前执行我需要完成的所有逻辑
  • 标识:包含我的ASP.NET标识实现
  • Web.Private:包含实际的MVC项目

如果您还没有读过以下两篇文章,请阅读:

你的问题的答案是依赖和装饰

使用它,您可以执行以下操作:

private readonly IExecuteCommands _commands;

[HttpPost]
public async Task<RedirectToRouteResult> Edit(short id, UpdateOffice command) {

    // with FV.NET plugged in, if your command validator fails,
    // ModelState will already be invalid
    if (!ModelState.IsValid) return View(command);

    await _commands.Execute(command);
    return RedirectToAction(orWhateverYouDoAfterSuccess);
}
public class UpdateOffice
{
    public int OfficeId { get; set; }
    public int RegionId { get; set; }
    public string Name { get; set; }
}
。。。还有魔法验证器:

public class ValidateUpdateOfficeCommand : AbstractValidator<UpdateOffice>
{
    public ValidateUpdateOfficeCommand(DbContext dbContext)
    {
        RuleFor(x => x.OfficeId)
            .MustFindOfficeById(dbContext);

        RuleFor(x => x.RegionId)
            .MustFindRegionById(dbContext);

        RuleFor(x => x.Name)
            .NotEmpty()
            .Length(1, 200)
            .MustBeUniqueOfficeName(dbContext, x => x.OfficeId);
    }
}
public类ValidateUpdateOfficeCommand:AbstractValidator
{
公共ValidateUpdateOfficeCommand(DbContext DbContext)
{
规则(x=>x.OfficeId)
.MustFindOfficeById(dbContext);
规则(x=>x.RegionId)
.MustFindRegionById(dbContext);
RuleFor(x=>x.Name)
.NotEmpty()
.长度(1200)
.MustBeUniqueOfficeName(dbContext,x=>x.OfficeId);
}
}
这些验证规则中的每一条都将在执行操作方法之前运行,前提是您已经为依赖项注入设置了验证程序,并且您正在使用FV MVC验证提供程序。如果存在验证错误,ModelState.IsValid将为false


您还刚刚解决了控制器层和(可能)服务层中的过度注入问题。您可以运行任何查询、执行任何命令或验证任何对象,但只需3个接口依赖项。

您的服务有多少个存储库依赖项?你是把依赖项过度注入问题移到了还是解决了?我只是把它移到了服务层,因为我知道我必须用一些存储库的结果做一些更复杂的事情,然后将完成的模型传递给控制器。我今天早些时候读了第一篇文章,没有读第二篇文章,主要是因为史蒂夫的文章相当冗长。就您所引用的FluentValidation.NET而言,它与EF Fluent API有何不同?如果我使用EF Fluent API,它还有什么好处?EF Fluent API用于将关系模式映射到概念对象模型,其验证是最小的。您可以将字段设为必填字段并指定最大长度,但仅此而已。在上面,您的验证器进行检查,以确保您的所有其他业务规则没有被破坏。在SQL中,您必须使用触发器来实现这一点,而EF对触发器没有流畅的API。