简体   繁体   English

在 C# MVC 中的表单验证中使用外键对象

[英]Use foreign key object in form validation in C# MVC

I have created a class named Subject which has Department as a foreign key.我创建了一个名为Subject的类,它有Department作为外键。 ShortNameValidation is a ValidationAttribute which validates ShortName 's format (the third character of ShortName must be equals to the first character of Department 's SingleKey property). ShortNameValidationValidationAttribute这验证ShortName的格式(的第三个字符ShortName必须等于的第一个字符DepartmentSingleKey属性)。 The validation is used inside a controller which creates a new subject by typing a name, a short name and choosing a department from the predefined drop-down list of departments.验证在控制器内部使用,该控制器通过键入名称、短名称并从预定义的部门下拉列表中选择部门来创建新主题。

I tried accessing subject.Department directly inside IsValid method, but it was null .我尝试直接在IsValid方法中访问subject.Department ,但它是null The only solution I have at the moment is to fetch the department by reading it manually from the database using the DepartmentId .我目前唯一的解决方案是通过使用DepartmentId从数据库中手动读取来获取部门。

Is there a more elegant solution to inject subject.Department automatically?是否有更优雅的解决方案来自动注入subject.Department

Code:代码:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Example.Models
{
    public class Subject
    {
        public int Id { get; set; }

        [Required]
        public int Name { get; set; }

        [Required]
        [MinLength(4)]
        [MaxLength(15)]
        [ShortNameValidation]
        public string ShortName { get; set; }

        [ForeignKey("Department")]
        public int DepartmentId { get; set; }

        public virtual Department Department { get; set; }
    }

    internal class ShortNameValidationAttribute : ValidationAttribute
    {
        private AppContext _appContext = new AppContext();

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            Subject subject = validationContext.ObjectInstance as Subject;
            // subject.Department returns null - fetch the department from the database
            Department department = _appContext.Departments.Find(subject.DepartmentId);

            if (subject.ShortName[2] != department.SingleKey[0])
            {
                return new ValidationResult("Invalid short name");
            }

            return ValidationResult.Success;
        }
    }
}

View:看法:

@model Example.Models.Subject

@{
    ViewBag.Title = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Create</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Subject</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ShortName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ShortName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.ShortName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.DepartmentId, "DepartmentId", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownList("DepartmentId", null, htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.DepartmentId, "", new { @class = "text-danger" })
            </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>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Make sure you are populating Department on GET确保您在 GET 上填充 Department

[HttpGet]
public ActionResult Create()
{
 // example only
 Subject subject = new Subject 
 {
     Id = 1,
     DepartmentId = 1,
     Name = 1,
     Department = new Department() { SingleKey = "Science" }, 
     ShortName = "Science"
 };
 return View(subject);
}

Then in your form make sure you have a hidden property for Department然后在你的表格中确保你有一个隐藏的Department属性

 @Html.HiddenFor(m => m.Department.SingleKey) // now this will model bind nicely

Now after you post your form inside your ShortNameValidationAttribute you will have Department populated现在,在您的ShortNameValidationAttribute发布表单后,您将填充Department

Subject subject = validationContext.ObjectInstance as Subject;
if(subject.Department != null)
{
   // do validation
}

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM