如何解决基于ASP.NET Core MVC中的控制器操作的对象状态验证
我正在尝试在ASP.NET Core 3.1 MVC应用程序中使用IValidatableObject
实现基于DRY的验证。我同时使用两个数据注释来验证“格式”规则,并使用Validate(ValidationContext validationContext)
方法来实现我的业务规则。
到目前为止,它运行良好,现在,我有一些基于对象状态的额外业务规则,这些规则将控制我的对象的某种工作流程,并且该工作流程将取决于要执行的控制器动作。
我想避免在控制器中添加业务规则,并希望在模型中集中进行任何验证。我想知道是否有任何标准方法可以做到这一点,否则我将实现自己的机制。
例如:
尝试使用STATUS_1删除MyObject应该会给出验证错误...
这是MyObject类:
public class MyObject : IValidatableObject
{
public MyObjectState State { get; set; }
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18,2)")]
public decimal Value{ get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
//My custom model validation here
}
public IEnumerable<ValidationResult> ValidateState(ActionExecutedContext actionContext)
{
var controllerActionDescriptor = actionContext.ActionDescriptor as ControllerActionDescriptor;
if (controllerActionDescriptor.ActionName == "Delete" && State != MyObjectState.STATE_1)
yield return new ValidationResult("You cannot delete if STATE_1");
}
}
这些可能是MyObject的状态:
public enum MyObjectState
{
STATE_1 = 1,STATE_2 = 2,STATE_3 = 3
}
这可能是具有删除操作的MyObject Controller:
public class MyObjectController: Controller
{
private readonly ApplicationDbContext _context;
public MyObjectController(ApplicationDbContext context)
{
_context = context;
}
public IActionResult Index()
{
return View();
}
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var myObject = await _context.MyObject.FindAsync(id);
var validationStateResult = myObject.ValidateState(null);
//Not sure how to provide the action context here
if (!validationStateResult)
{
return RedirectToAction(nameof(Index)).WithWarning("ALERT: ",validationStateResult.ToString());
}
return View(myObject);
}
}
解决方法
您可以在视图中使用ajax,将动作返回errormessage或MyObject转换为ajax,而ajax将提醒错误消息或重定向以删除Page。在控制器中,您可以获取actionName进行检查。以下是一个演示示例:
MyObject ValidateState(我将ActionName
更改为DeleteCheck,并且您可以使用ActionName进行检查):
public IEnumerable<ValidationResult> ValidateState(string ActionName)
{
if (ActionName == "DeleteCheck" && State == MyObjectState.STATE_1)
yield return new ValidationResult("You cannot delete if STATE_1");
}
MyObjectsController(您可以使用RouteData.Values["action"]
获取actionName):
public async Task<IActionResult> DeleteCheck(int? id)
{
if (id == null)
{
return NotFound();
}
var myObject = await _context.MyObjects.FindAsync(id);
var action =(string)RouteData.Values["action"];
var validationStateResult = myObject.ValidateState(action);
string messages = string.Join("",myObject.ValidateState(action)
.SelectMany(x => x.ErrorMessage));
TempData["Message"] = messages;
if (messages!=null&&messages != "")
{
return Json(messages);
}
return Json(myObject);
}
public IActionResult Delete(MyObject myObject) {
return View(myObject);
}
查看:
<a href="#" onclick="delete1(@item.Id)" >Delete</a>
function delete1(id) {
$.ajax({
method: 'get',url: "MyObjects/DeleteCheck?Id=" + id,dataType: "json",success: function (data) {
if (typeof data === 'object') {
window.location.href = "/MyObjects/Delete?Id=" + data.id + "&&State=" + data.state + "&&Price=" + data.price;
//alert("object");
} else {
alert(data)
}
}
});
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。