大家好!我很混淆实现一段代码来在asp.net mvc 3中创建工作.net数据注释,在几种情况下使用具有不同必需字段的模型(6)。 我有一个模特:
public class OpportunityModel
{
public Guid OpportunityId { get; set; }
[Display(Name = "Value")]
[RegularExpression(@"^[-+]?\d{1,10}(\.\d{0,4})?$", ErrorMessage = "Must be a number")]
public decimal? ActualValue { get; set; }
[Display(Name = "Name")]
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
public string Product { get; set; }
[Display(Name = "Estimated Date")]
public DateTime? EstimateDate { get; set; }
public bool? Sales6ixFallDown { get; set; }
[Display(Name = "Stage")]
public Stages Sales6ixStage { get; set; }
public DateTime? Sales6ixDateInBoard { get; set; }
public DateTime? Sales6ixDateInCurrentStage { get; set; }
public DateTime? Sales6ixNextAppointmentDate { get; set; }
[Display(Name = "Description")]
public string Description { get; set; }
public string Sales6ixNextAppointmentDescription { get; set; }
public int NewColumn { get; set; }
public Guid? CustomerId { get; set; }
public string CustomerName { get; set; }
}
我需要的是动态改变其中所需的封地的可能性。经过一些谷歌搜索,这是不可能的,并开始使用模型继承。我的意思是:我有一个像这样的基础模型:
public class BaseOpportunityModel
{
public Guid OpportunityId { get; set; }
public virtual decimal? ActualValue { get; set; }
public virtual string Name { get; set; }
public string Product { get; set; }
public DateTime? EstimateDate { get; set; }
public bool? Sales6ixFallDown { get; set; }
[Display(Name = "Stage")]
public Stages Sales6ixStage { get; set; }
public DateTime? Sales6ixDateInBoard { get; set; }
public DateTime? Sales6ixDateInCurrentStage { get; set; }
public DateTime? Sales6ixNextAppointmentDate { get; set; }
[Display(Name = "Description")]
public string Description { get; set; }
public string Sales6ixNextAppointmentDescription { get; set; }
public int NewColumn { get; set; }
public Guid? CustomerId { get; set; }
public string CustomerName { get; set; }
}
其中虚拟属性是可能是必填字段的属性。然后我从这个基地得到了几个派生模型:
public class OpportunityModel0: BaseOpportunityModel
{
[Display(Name = "Value")]
[Required(ErrorMessage = "Name is required")]
[RegularExpression(@"^[-+]?\d{1,10}(\.\d{0,4})?$", ErrorMessage = "Must be a number")]
public override decimal? ActualValue { get; set; }
[Display(Name = "Name")]
[Required(ErrorMessage = "Name is required")]
public override string Name { get; set; }
}
然后我就可以在View和Controller基础模型BaseOpportunityModel中使用了。但我遇到了以下问题:
我错了什么?有人能引导我朝着正确的方向前进吗?还是帮我解决这个问题?提前谢谢。
答案 0 :(得分:1)
此提示应在mvc 3中适用于THIS。可能有问题的一件事是你的后期行动。您应该在后期操作中将继承的模型指定为param。
public ActionResult MyPostAction(OpportunityModel0 model)
如果基本模型是参数,则验证将无效。
答案 1 :(得分:1)
我通过使用自定义RequiredIfValidator来解决模型的不同重新验证问题。所以现在我只有一个模型和一个视图。这是代码,可能是某些人发现它很有用:
的 RequiredIfAttribute:强>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace Infrastructure.Extensions
{
public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
{
private RequiredAttribute _innerAttribute = new RequiredAttribute();
public string DependentProperty { get; set; }
public object TargetValue { get; set; }
public RequiredIfAttribute(string dependentProperty, object targetValue)
{
this.DependentProperty = dependentProperty;
this.TargetValue = targetValue;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
// get a reference to the property this validation depends upon
var containerType = validationContext.ObjectInstance.GetType();
var field = containerType.GetProperty(this.DependentProperty);
if (field != null)
{
// get the value of the dependent property
var dependentvalue = field.GetValue(validationContext.ObjectInstance, null);
// compare the value against the target value
if ((dependentvalue == null && this.TargetValue == null) ||
(dependentvalue != null && dependentvalue.Equals(this.TargetValue)))
{
// match => means we should try validating this field
if (!_innerAttribute.IsValid(value))
// validation failed - return an error
return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
}
}
return ValidationResult.Success;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule()
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "requiredif",
};
string depProp = BuildDependentPropertyId(metadata, context as ViewContext);
// find the value on the control we depend on;
// if it's a bool, format it javascript style
// (the default is True or False!)
string targetValue = (this.TargetValue ?? "").ToString();
if (this.TargetValue.GetType() == typeof(bool))
targetValue = targetValue.ToLower();
rule.ValidationParameters.Add("dependentproperty", depProp);
rule.ValidationParameters.Add("targetvalue", targetValue);
yield return rule;
}
private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
{
// build the ID of the property
string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(this.DependentProperty);
// unfortunately this will have the name of the current field appended to the beginning,
// because the TemplateInfo's context has had this fieldname appended to it. Instead, we
// want to get the context as though it was one level higher (i.e. outside the current property,
// which is the containing object (our Person), and hence the same level as the dependent property.
var thisField = metadata.PropertyName + "_";
if (depProp.StartsWith(thisField))
// strip it off again
depProp = depProp.Substring(thisField.Length);
return depProp;
}
}
}
的 RequiredIfValidator 强>
namespace Infrastructure.Extensions
{
public class RequiredIfValidator : DataAnnotationsModelValidator<RequiredIfAttribute>
{
public RequiredIfValidator(ModelMetadata metadata, ControllerContext context, RequiredIfAttribute attribute)
: base(metadata, context, attribute)
{
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
return base.GetClientValidationRules();
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
// get a reference to the property this validation depends upon
var field = Metadata.ContainerType.GetProperty(Attribute.DependentProperty);
if (field != null)
{
// get the value of the dependent property
var value = field.GetValue(container, null);
// compare the value against the target value
if ((value == null && Attribute.TargetValue == null) ||
(value.Equals(Attribute.TargetValue)))
{
// match => means we should try validating this field
if (!Attribute.IsValid(Metadata.Model))
// validation failed - return an error
yield return new ModelValidationResult { Message = ErrorMessage };
}
}
}
}
}
客户端验证
/// <reference path="jquery-1.4.4-vsdoc.js" />
/// <reference path="jquery.validate.unobtrusive.js" />
$.validator.addMethod('requiredif',
function (value, element, parameters) {
var id = '#' + parameters['dependentproperty'];
// get the target value (as a string,
// as that's what actual value will be)
var targetvalue = parameters['targetvalue'];
targetvalue =
(targetvalue == null ? '' : targetvalue).toString();
// get the actual value of the target control
// note - this probably needs to cater for more
// control types, e.g. radios
var control = $(id);
var controltype = control.attr('type');
var actualvalue =
controltype === 'checkbox' ?
control.is(":checked").toString() :
//control.attr('checked').toString() :
control.val();
actualvalue = actualvalue.toLocaleLowerCase();
// if the condition is true, reuse the existing
// required field validator functionality
if (targetvalue === actualvalue)
return $.validator.methods.required.call(
this, value, element, parameters);
return true;
}
);
$.validator.unobtrusive.adapters.add(
'requiredif',
['dependentproperty', 'targetvalue'],
function (options) {
options.rules['requiredif'] = {
dependentproperty: options.params['dependentproperty'],
targetvalue: options.params['targetvalue']
};
options.messages['requiredif'] = options.message;
});