我正在使用Entity Framework,我想验证我的模型。
示例服务:
var user = _userRepository.GetUser(...);
var order = user.MakeOrder(); //<- this is some business logic in Rich Domain Model
_userRepository.Update(user);
_orderRepository.Add(order);
数据库操作可能会抛出DbEntityValidationException
。我可以抓住它并做一些工作来向用户提出错误:
try
{
_userRepository.Update(user);
_orderRepository.Add(order);
}
catch(DbEntityValidationException ex)
{
var error = ex.EntityValidationErrors();
//Pass errors to Controller
}
但我知道,例外很慢。有没有办法做同样的事情而没有例外(例如某种返回值)以获得更好的性能?
答案 0 :(得分:2)
1)您必须实现模型IValidatableObject接口,然后在Validate方法
中定义验证规则2-)使用ModelState.IsValid属性。不需要尝试捕获块
3-)为页面元素添加验证消息块
了解更多详情
http://weblogs.asp.net/scottgu/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3
附加
您可以使用流畅的验证 https://fluentvalidation.codeplex.com/wikipage?title=mvc
基本示例http://www.jerriepelser.com/blog/using-fluent-validation-with-asp-net-mvc-part-1-the-basics
答案 1 :(得分:0)
您可以使用DbContext.SaveChanges
内部使用的相同方法。它是公开的 - DbContext.GetValidationErrors
:
验证跟踪的实体并返回包含验证结果的DbEntityValidationResult集合。
当然,您应该以某种方式通过您的存储库公开它。
PS 但请注意,事实上这可能会导致性能下降,因为SaveChanges
会再次这样做(并注意此方法包含DetectChanges
调用,如备注中所述),因为验证错误应该是一个例外情况,可能最好将它们作为例外情况处理,就像在原始代码中一样。
答案 2 :(得分:0)
如果您想避免页面往返,请尝试向模型添加验证并尝试添加客户端验证。使用JQuery验证进行客户端验证以获得更好的性能。
有关客户端验证的更多详细信息。尝试通过以下链接:
答案 3 :(得分:-1)
我建议在尝试保存到数据库之前使用内置模型验证。
此示例来自asp.net mvc模板中构建的登录功能。
public class LoginViewModel
{
[Required]
[Display(Name = "Email")]
[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
然后在控制器中:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
在视图中:
@using WebApplication1.Models
@model LoginViewModel
@{
ViewBag.Title = "Log in";
}
<h2>@ViewBag.Title.</h2>
<div class="row">
<div class="col-md-8">
<section id="loginForm">
@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<h4>Use a local account to log in.</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
<p>
@Html.ActionLink("Register as a new user", "Register")
</p>
@* Enable this once you have account confirmation enabled for password reset functionality
<p>
@Html.ActionLink("Forgot your password?", "ForgotPassword")
</p>*@
}
</section>
</div>
<div class="col-md-4">
<section id="socialLoginForm">
@Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { ReturnUrl = ViewBag.ReturnUrl })
</section>
</div>
</div>
Html帮助器方法,ValidationMessageFor将使用显示注释中的文本来通知错误。