我正在从旧的 ASP.NET Web 窗体方式转换为 ASP.NET MVC。我有一个正在处理的项目,该项目在数据库中有大约 40-50 个表。我决定使用实体框架作为我的数据访问层。我还决定在 EF 上放置一个存储库层和工作单元抽象,这样我就不会被它束缚,这样我就可以进行单元测试。最后,我想让我的控制器“瘦”,所以我正在考虑为我的业务逻辑实现一个业务“服务”层。
我正在努力解决的问题是如何将业务逻辑错误从我的服务层传播到我的 Presentation UI 层,以便显示适当的错误?请注意,我正在尝试寻找不是 MVC 特定的解决方案,因为此服务/业务逻辑层可能会用于除 MVC 应用程序(控制台应用程序、Web 服务等)之外的其他事物
关于一些代码...
可以说我有一个像这样的 POCO / 数据 / 域模型:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
// other properties (navigation, etc)...
}
一个实体框架流利的配置/映射类,如下所示:
public class CategoryMap : EntityTypeConfiguration<Category>
{
public CategoryMap()
{
this.HasKey(c => c.Id);
this.Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // auto increment identity in our DB schema
this.Property(c=> c.Name)
.IsRequired() // defined as NOT NULL in DB schema so we put a constraint here
.HasMaxLength(150); // defined as varchar(150) in DB schema so we put a constraint here
this.Property(c=> c.Description)
.IsRequired(); // defined as NOT NULL in DB schema so we put a constraint here
// fluent config for related entities (navigation properties) would go here...
}
}
一个封装多个存储库的工作单元,如下所示:
public class UnitOfWork : IUnitOfWork
{
private readonly MyDbContext context;
private CategoryRepository catRepo;
public UnitOfWork()
{
this.context = new MyDbContext();
}
public ICategoryRepository Categories
{
get { return this.catRepo?? (this.catRepo= new CategoryRepository (this.context)); }
}
}
像这样的服务/业务逻辑层:
public class CategoryService : ICategoryService
{
private readonly IUnitOfWork unitOfWork;
public CategoryService(IUnitOfWork uow) // injected by IoC
{
this.unitOfWork = uow;
}
public Category CreateNewCategory(Category category)
{
if (category == null)
{
throw new ArgumentNullException("category cannot be null");
}
// Simple business logic here to make sure another category with this name does not already exist.
int count = this.unitOfWork.Categories.Count(cat => cat.Name == category.Name);
if (count > 0)
{
// *** This is the error I want the user to see in the UI ***
throw new Exception("Sorry - a category with that name already exists!");
}
}
}
像这样的控制器:
public ManageCategoriesController : Controller
{
ICategoryService catSvc;
public ManageCategoriesController(ICategoryService svc) // injected by IoC
{
this.catSvc = svc;
}
[HttpPost]
public ActionResult(CategoryCreateModel createModel) // my View Models / Create Models have Data Annotations on them
{
if (ModelState.IsValid)
{
// use of AutoMapper to map from View Model to domain model...
Category cat = Mapper.Map<CategoryCreateModel , Category>(createModel);
this.catSvc.CreateNewCategory(cat); // ***need to get potential errors from Service and display on form.***
return this.RedirectToAction("Index");
}
}
}
首先,谁能告诉我我是否在使用视图模型的正确轨道上?我觉得每个域模型几乎都有三个视图模型(创建、编辑、视图/列表)。
其次,我的 EF 配置/映射类负责数据库约束。其中一些约束(例如最大长度)也是视图模型中的数据注释,可以很容易地显示在 UI 上。但是我在哪里可以显示我的自定义业务逻辑错误?