使用displayfor时,在ViewModel中删除验证

时间:2012-09-13 19:47:05

标签: asp.net-mvc

我正在使用一个viewmodel,为某些属性指定了必需的字段验证。我能够使用“displayfor”创建相同模型的只读版本。在页面中,除了这个只读视图外,还有其他控件以及提交。现在,当我点击“提交”时,它将被验证并且ModelState无效。如果我们仅使用模型进行显示,如何删除验证。

视图模型

public class CustomerVM
{
 [Required]
 public string Name {get;set;}
}

查看

@using (Html.BeginForm("CreateCustomer, "Customer", FormMethod.Post))
{   
 @Html.DisplayFor(o => o.Name)

 @..other input controls.@

 <input id="btnSave" type="submit" value="Save" />
}

Model.State无效,因为name呈现为label而httppost没有该值。

3 个答案:

答案 0 :(得分:1)

您可以为此“只读”视图使用具有不同验证要求的其他视图模型。或者您可以在控制器中使用ModelState.Remove()方法来消除您不想验证的属性的错误。 IMO单独的视图模型方法更好。

看到你的代码后编辑

添加隐藏

@Html.DisplayFor(o => o.Name)
@Html.HiddenFor(o => o.Name)

那会将数据传回给帖子上的控制器并导致ModelState.IsValid == true

答案 1 :(得分:1)

这是MetadataTypeAttribute派上用场的地方:

public class MyModel
{
  public string Name { get; set; }
}

public interface IMyModelValidation
{
  [Required]
  public string Name { get; set; }
}

[MetadataType(typeof(IMyModelValiation))]
public class MyModelValidation : MyModel { }

现在MyModel没有验证,MyModelValidation确实有验证,几乎可以互换使用。

  • MetadataType
  

MetadataTypeAttribute属性使您可以将类与数据模型分部类相关联。在此关联类中,您提供了不在数据模型中的其他元数据信息。

     

例如,在关联的类中,您可以将RequiredAttribute属性应用于数据字段。这会强制为字段提供值,即使数据库模式不需要此约束。

答案 2 :(得分:-1)

我不是说这是最好的方法,但我必须做类似的事情,所以我设置验证组。我创建了一个属性,我放置在定义其验证组的每个模型属性上。然后在回发时,我在ViewDataDictionary上调用了一个扩展方法,并传入了我想要运行验证的验证组。这将删除所有其他组的任何验证消息。以下是一些示例代码:

属性:

/// <summary>
/// Attribute that assigns the property on a model to a given
/// validation group. By using the ValidationGroupExtension 
/// and calling ValidateGroup on the ViewData validation errors
/// for properties that are not included in the validation group 
/// will be removed.
/// </summary>
public class ValidationGroup : Attribute
{
    /// <summary>
    /// The unique name of the group.
    /// </summary>
    public String Group { get; set; }

    public ValidationGroup(String group)
    {
        this.Group = group;
    }
}

扩展名:

/// <summary>
/// Used in conjunction with the ValidationGroup attribute to 
/// specify which fields in a model should be validated. The 
/// ValidateGroup extension should be called on ViewData before 
/// checking whether the model is valid or not.
/// </summary>
public static class ValidationGroupExtension
{
    /// <summary>
    /// Remove all validation errors that are assocaited with 
    /// properties that do not have the ValidationGroup attribute
    /// set with the specified group name.
    /// 
    /// This only handles flat models.
    /// </summary>
    /// <param name="viewData">View Data</param>
    /// <param name="model">Data model returned</param>
    /// <param name="group">Name of the validation group</param>
    /// <returns></returns>
    public static ViewDataDictionary ValidateGroup(this ViewDataDictionary viewData, Object model, String group)
    {
        //get all properties that have the validation group attribut set for the given group
        var properties = model.GetType().GetProperties()
            .Where(x => x.GetCustomAttributes(typeof(ValidationGroup), false)
                            .Where(a => ((ValidationGroup)a).Group == group).Count() > 0)
                            .Select(x => x.Name);

        //find all properties that don't match these properties
        var matchingProperties = viewData.ModelState.Where(x => !properties.Contains(x.Key)).ToList();

        //remove any property that isn't in the gorup
        foreach (var matchingProperty in matchingProperties)
        {
            viewData.ModelState.Remove(matchingProperty.Key);
        }

        return viewData;
    }
}

在PostBack上:

ViewData.ValidateGroup(model, "my validation group name");
if (ModelState.IsValid)
{
    ...
}

在ViewModel上:

[Required]
[DisplayName("Name")]
[ValidationGroup("my validation group name")]
public string Name { get; set; }