ASP.NET MVC中使用FluentValidation驗證實體

風靈使發表於2019-01-03

1、FluentValidation介紹

FluentValidation是與ASP.NET DataAnnotataion Attribute驗證實體不同的資料驗證元件,提供了將實體與驗證分離開來的驗證方式,同時FluentValidation還提供了表示式鏈式語法。

2、安裝FluentValidation

FluentValidation地址:http://fluentvalidation.codeplex.com/

使用Visual Studio的管理NuGet程式包安裝FluentValidationFluentValidation.Mvc

3、通過ModelState使用FluentValidation驗證

專案解決方案結構圖:
在這裡插入圖片描述
實體類Customer.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Libing.Portal.Web.Models.Entities
{
    public class Customer
    {
        public int CustomerID { get; set; }
        public string CustomerName { get; set; }
        public string Email { get; set; }
        public string Address { get; set; }
        public string Postcode { get; set; }
        public float? Discount { get; set; }
        public bool HasDiscount { get; set; }
    }
}

資料驗證類CustomerValidator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using FluentValidation;

using Libing.Portal.Web.Models.Entities;

namespace Libing.Portal.Web.Models.Validators
{
    public class CustomerValidator : AbstractValidator<Customer>
    {
        public CustomerValidator()
        {
            RuleFor(customer => customer.CustomerName).NotNull().WithMessage("客戶名稱不能為空");
            RuleFor(customer => customer.Email)
                .NotEmpty().WithMessage("郵箱不能為空")
                .EmailAddress().WithMessage("郵箱格式不正確");
            RuleFor(customer => customer.Discount)
                .NotEqual(0)
                .When(customer => customer.HasDiscount);
            RuleFor(customer => customer.Address)
                .NotEmpty()
                .WithMessage("地址不能為空")
                .Length(20, 50)
                .WithMessage("地址長度範圍為20-50位元組");
        }
    }
}

控制器類CustomerController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using FluentValidation.Results;

using Libing.Portal.Web.Models.Entities;
using Libing.Portal.Web.Models.Validators;

namespace Libing.Portal.Web.Controllers
{
    public class CustomerController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Create(Customer customer)
        {
            CustomerValidator validator = new CustomerValidator();
            ValidationResult result = validator.Validate(customer);

            if (!result.IsValid)
            {
                result.Errors.ToList().ForEach(error =>
                {
                    ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
                });
            }

            if (ModelState.IsValid)
            {
                return RedirectToAction("Index");
            }

            return View(customer);
        }
    }
}

View頁面Create.cshtml,該頁面為在新增View時選擇Create模板自動生成:


@model Libing.Portal.Web.Models.Entities.Customer

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Create</title>
</head>
<body>
    @using (Html.BeginForm()) 
    {
        @Html.AntiForgeryToken()
        
        <div class="form-horizontal">
            <h4>Customer</h4>
            <hr />
            @Html.ValidationSummary(true)
    
            <div class="form-group">
                @Html.LabelFor(model => model.CustomerName, new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.CustomerName)
                    @Html.ValidationMessageFor(model => model.CustomerName)
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Email, new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Email)
                    @Html.ValidationMessageFor(model => model.Email)
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Address, new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Address)
                    @Html.ValidationMessageFor(model => model.Address)
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Postcode, new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Postcode)
                    @Html.ValidationMessageFor(model => model.Postcode)
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Discount, new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Discount)
                    @Html.ValidationMessageFor(model => model.Discount)
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.HasDiscount, new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.HasDiscount)
                    @Html.ValidationMessageFor(model => model.HasDiscount)
                </div>
            </div>
    
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-default" />
                </div>
            </div>
        </div>
    }
</body>
</html>

執行效果:
在這裡插入圖片描述

4、通過設定實體類Attribute與驗證類進行驗證

修改實體類Customer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using FluentValidation.Attributes;

using Libing.Portal.Web.Models.Validators;

namespace Libing.Portal.Web.Models.Entities
{
    [Validator(typeof(CustomerValidator))]
    public class Customer
    {
        public int CustomerID { get; set; }
        public string CustomerName { get; set; }
        public string Email { get; set; }
        public string Address { get; set; }
        public string Postcode { get; set; }
        public float? Discount { get; set; }
        public bool HasDiscount { get; set; }
    }
}

修改Global.asax.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

using FluentValidation.Attributes;
using FluentValidation.Mvc;

namespace Libing.Portal.Web
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            // FluentValidation設定
            DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
            ModelValidatorProviders.Providers.Add(new FluentValidationModelValidatorProvider(new AttributedValidatorFactory()));
        }
    }
}

相關文章