ASP.NET MVC 4:在子对象中跳过验证

时间:2013-03-22 20:06:31

标签: c# asp.net-mvc-4 model

首先,抱歉我的英语。不是我的自然语言。

我有一个名为Category的类,如下面的代码所示。请注意,在此代码中我还有一个Category属性,我可以在其中引用父类别。它只是在类中声明的同一个类。像Inception一样。因此,这个父类别对象具有“声明他的类”的相同属性。

属性Name是必需的。记住这个属性。

public class Category
{
    public int? Id{ get; set; }

    [DisplayName("Father Category")] //NOT REQUIRED
    public Category Father { get; set; }

    [DisplayName("Category")]
    [Required(ErrorMessage = "Name is required")] //REMEMBER THIS REQUIRED PROPERTY!!
    public string Name { get; set; }

    [DisplayName("Status")]
    public bool Status { get; set; }

    [DisplayName("Description")]
    public string Description { get; set; }
}

那是我的班级。

所以,在类别视图中,我可以这样做:

注意:CompleteEditorForCompleteDropDownListFor是扩展方法,在每个字段中添加一些额外的html,仅用于调整布局。

@using (Html.BeginForm(null, null, FormMethod.Post))
{

    @Html.CompleteEditorFor(x => x.Name)
    @Html.CompleteEditorFor(x => x.Description)
    @Html.CompleteEditorFor(x => x.Status)

    @Html.CompleteDropDownListFor(x => x.Father.Id, ViewData["Categories"], "Id", "Name", "Select...")

    @Html.SubmitButton()
}

上面的代码运行得很好。

现在出现了问题:

当我点击“保存”按钮时,它会生成HttpPost,这就是Action

(下面的代码有一些修改过的消息字符串和扩展方法。) (CategoriesBLL是从数据库中获取类别的类。)

    [HttpPost]
    public ActionResult New(Category item)
    {
        ViewData.Add("Categories", CategoriesBLL.select());
        try
        {
            if (ModelState.IsValid)//PROBLEM IS HERE!!!!!!!!!
            {
                if (CategoryBLL.insert(item) != 0)
                {

                    ViewData.AddSuccess("Some Success Message");


                    return View(new Category());
                }
                else
                {
                    ModelState.AddError("Some error message");
                    return View(item);
                }
            }
            else
            {
                ModelState.AddError("Some SERIOUS error message");
                return View(item);
            }
        }
        catch (Exception ex)
        {
            ModelState.AddError("Some EVEN MORE SERIOUS message");
            return View(item);
        }

    }

问题出在if (ModelState.IsValid)行。

为什么?

因为我的Category类有一个名为Name的必需属性。我不需要这个属性来做我正在做的事情,我只需要Id属性的Father。我可以在View:

的这一行中获得此Id
@Html.CompleteDropDownListFor(x => x.Father.Id, ViewData["Categories"], "Id", "Name", "Select...")

这很有效。

但是Name属性是null,并且是必需的,但它仅在我通知Child类时才需要。不是父班。

我甚至不知道如何在Google或StackOverflow上搜索它......

任何人都可以帮助我吗?

4 个答案:

答案 0 :(得分:2)

您可能需要考虑在模型上创建类IValidatableObject接口而不是属性装饰器。如果你真的想使用一个属性装饰器,那么你可能会对自定义装置进行修改。

答案 1 :(得分:2)

您需要使用View Models。您的视图模型应包含视图中所需的所有字段,减去父属性。然后在您的控制器中,您需要将视图模型映射到模型。您可以使用Automapper轻松完成此操作。 (但是,不推荐从视图到域模型的直接映射,但稍后会对其进行排序)

我知道,起初这可能看起来像拖累,但相信我。您的视图与您的域模型不同。接下来你会知道,你需要在视图上添加某种下拉菜单,以及在域模型中没有的其他额外复选框。此外,如果您使用视图模型,您的安全性将得到改善。如果有兴趣,我会告诉你一些关于它的信息。

答案 2 :(得分:1)

public class Category : IValidatableObject
{
    public int? Id{ get; set; }

    [DisplayName("Father Category")] //NOT REQUIRED
    public Category Father { get; set; }

    [DisplayName("Category")]
    [Required(ErrorMessage = "Name is required")] //REMEMBER THIS REQUIRED PROPERTY!!
    public string Name { get; set; }

    [DisplayName("Status")]
    public bool Status { get; set; }

    [DisplayName("Description")]
    public string Description { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var results = new List<ValidationResult>();
        if (this.Enable)
        {
            Validator.TryValidateProperty(this.Name ,
                new ValidationContext(this, null, null) { MemberName = "Name" },
                results);
            Validator.TryValidateProperty(this.Status,
                new ValidationContext(this, null, null) { MemberName = "Status" },
                results);
        }
        return results;
    }
}

public void Validate()
{
        var toValidate = new Category()
        {
            Name = "Just a name",
            Status = true
        };

        bool validateAllProperties = false;

        var results = new List<ValidationResult>();

        bool isValid = Validator.TryValidateObject(
            toValidate,
            new ValidationContext(toValidate, null, null),
            results,
            validateAllProperties);
}

答案 3 :(得分:1)

OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES

ModelState.Remove("PropertyNameInModel");