如何在.net core mvc中使用ModelState包装类分离业务逻辑层
Posted
技术标签:
【中文标题】如何在.net core mvc中使用ModelState包装类分离业务逻辑层【英文标题】:How to separate business logic layer using ModelState wrapper class in .net core mvc 【发布时间】:2020-09-19 23:36:09 【问题描述】:我正在使用 ASP.Net MVC 5(.net 框架)开发 Web 应用程序,现在尝试使用 .NET Core 3.1 和实体框架 Core(使用代码优先方法)开发我的下一个项目。
我正在一个单独的 Wrapper 类中尝试单独的业务逻辑,例如:
public interface IValidationDictionary
void AddError(string key, string errorMessage);
bool IsValid get;
public class ModelStateWrapper : IValidationDictionary
private ModelStateDictionary _modelState;
public ModelStateWrapper(ModelStateDictionary modelState)
_modelState = modelState;
#region IValidationDictionary Members
public void AddError(string key, string errorMessage)
_modelState.AddModelError(key, errorMessage);
public bool IsValid
get return _modelState.IsValid;
#endregion
在 EmployeeRepo 类中:
private Models.IValidationDictionary _modelState;
public EmployeeRepo(Models.IValidationDictionary modelState)
_modelState = modelState;
public int Create(Models.Employee ObjToCreate)
if (!Validate(ObjToCreate))
return 0;
_context.Employee.Add(ObjToCreate);
_context.SaveChanges();
return ObjToCreate.Id;
protected bool Validate(Models.Employee objToValidate)
if (objToValidate.Name.Trim().Length == 0)
_modelState.AddError("Name", "Name is required.");
if (null == objToValidate.DOB)
_modelState.AddError("DOB", "DOB is required");
return _modelState.IsValid;
在控制器中:
private Repository.IEmployeeRepo repo;
public EmployeesController(ApplicationDbContext context)
_context = context;
repo = new Repository.EmployeeRepo(new Models.ModelStateWrapper(this.ModelState));
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create([Bind("Name,DOB,Department")] Employee employee)
var respId = repo.Create(employee);
if (0 != respId.Id)
return RedirectToAction(nameof(Details), new id = respId.Id );
return View(employee);
我希望 ModelState 错误会在由包装类添加的控制器中更新,但模型验证错误不会在控制器中更新。
感谢您的宝贵时间和任何回复。
致以最诚挚的问候, 拉朱·穆克吉
【问题讨论】:
我建议你在Create
方法中加个断点来测试,确认员工是否收到了对应的数据,然后再确认是哪一段代码有问题,看不到如何在自定义 Create 方法中调用 _context
。
@YongqingYu 在调试检查期间,我发现 EmployeeRepo 的 Validate() 方法为空 DOB 和 ModelState.IsValid 添加了模型错误,如预期的那样,但当它返回 0 到 Controller 时仍然没有 ModelState更新即 ModelState.IsValid 为 True 且 EmployeeRepo 添加的错误无法在视图中显示。对于 _context 我删除了计时代码,因为我在 Repo 类创建 DbContext 对象期间发现错误,因为这部分由在 CORE MVC 的 Startup.cs 类中配置的 DI 管理...谢谢
您提到错误无法在视图中显示,所以请提供您的视图代码供我们参考,并且Create方法最终返回一个int类型,我认为respId.Id是错误的。跨度>
@YongqingYu 正如提到的在存储库中添加的模型错误未反映在控制器中,因此无法出现在用户视图中。 (respId.Id 错误,一旦我从 Create 返回 Employee 对象类型,请忽略它)查看代码供您参考:' '
【参考方案1】:
你只想用自定义的验证方式来验证这两个 领域,对吧?
你写的方法太复杂了。
要绑定对应的报错信息,需要在[Required]
等对应字段上方添加自定义验证属性。
其实只需要继承ValidationAttribute
方法,重写IsValid
方法即可。
public class Employee
public int Id get; set;
[CustomValidate]
public string Name get; set;
[CustomValidate]
public string DOB get; set;
public string Department get; set;
自定义方法:
public class CustomValidateAttribute : ValidationAttribute
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
if (value == null || string.IsNullOrEmpty(value.ToString().Trim()))
return new ValidationResult(validationContext.DisplayName + " is required.");
return ValidationResult.Success;
创建:
[HttpPost]
public IActionResult Create([Bind("Name,DOB,Department")]Employee employee)
if (ModelState.IsValid)
_context.Employee.Add(employee);
_context.SaveChanges();
return RedirectToAction(nameof(Details), new id = employee.Id );
return View(employee);
这是测试结果:
【讨论】:
请参考主题,我实际上是在尝试让 Repository 类负责业务逻辑验证(与服务层或 BLL 相同)。仅使用数据注释或自定义验证验证少数字段不是此 POC 项目的目的:如果我添加类似 ' if (null == employee.DOB) ModelState.AddModelError("DOB", "Date ofbirth is required") 之类的代码;'在 Controller Post Create 方法中,如果 DOB 字段为 null 提供,我得到 ModelState.IsValid FALSE 和模型验证错误,在 Repository 类中写入相同并期望相同的结果。 请建议您是否有任何简单的解决方案来完成同样的任务,代码在 .NetFramework 4.5 中使用 ASP.Net MVC 5 多年来运行良好 @raju1208,如果你必须根据你提供的方法显示错误信息,我建议你可以使用jquery ajax
调用Create动作,然后在成功方法中添加相应的信息ajax通过action返回的内容,你能接受这个方案吗?如果可能,我会更新我的帖子。
对于大型项目,这将不起作用,无论如何出现错误消息不是目标,问题是开发具有良好实践的应用程序,以便将来易于维护和增强。以上是关于如何在.net core mvc中使用ModelState包装类分离业务逻辑层的主要内容,如果未能解决你的问题,请参考以下文章
如何在.net core mvc中使用ModelState包装类分离业务逻辑层
如何在 ASP.NET Core MVC 中使用 ADO.NET 向存储过程添加参数?
如何在 ASP.NET Core MVC 中使用依赖注入设计存储库模式?
如何使用 C# 在 ASP.NET Core 3.1 MVC 中使用会话变量
如何在带有 ADO.NET 的 ASP.NET Core MVC 中使用 jQuery Ajax 自动完成
ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)