Изменение программного кода (MVC3 ASP.NET)
Скажем, у меня есть эта модель представления:
public class MyModel
{
[Range(0, 999, ErrorMessage = "Invalid quantity")]
public int Quantity { get; set; }
}
Теперь для конкретных экземпляров этой модели диапазон допустимых значений изменится: некоторые могут не быть 0, некоторые могут быть не выше 5. Значения min/max для допустимых диапазонов поступают из БД и могут меняться в любое время.
Как мне изменить свойства min/max RangeAttribute на лету? Или что это лучший способ проверить мой сценарий?
Ответы
Ответ 1
Что-то вроде этого может быть больше, чем после...
ViewModel:
public class ViewModel
{
public DateTime MinDate {get; set;}
public DateTime MaxDate {get; set;}
[DynamicRange("MinDate", "MaxDate", ErrorMessage = "Value must be between {0} and {1}")]
public DateTime Date{ get; set; }
}
Класс библиотеки или где-либо еще:
public class DynamicRange : ValidationAttribute, IClientValidatable
{
private readonly string _minPropertyName;
private readonly string _maxPropertyName;
public DynamicRange(string minPropName, string maxPropName)
{
_minPropertyName = minPropName;
_maxPropertyName = maxPropName;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var minProperty = validationContext.ObjectType.GetProperty(_minPropertyName);
var maxProperty = validationContext.ObjectType.GetProperty(_maxPropertyName);
if(minProperty == null)
return new ValidationResult(string.Format("Unknown property {0}", _minPropertyName));
if (maxProperty == null)
return new ValidationResult(string.Format("Unknown property {0}", _maxPropertyName));
var minValue = (int) minProperty.GetValue(validationContext.ObjectInstance, null);
var maxValue = (int) maxProperty.GetValue(validationContext.ObjectInstance, null);
var currentValue = (int) value;
if (currentValue <= minValue || currentValue >= maxValue)
{
return new ValidationResult(string.Format(ErrorMessage, minValue, maxValue));
}
return null;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ValidationType = "dynamicrange",
ErrorMessage = ErrorMessage
};
rule.ValidationParameters["minvalueproperty"] = _minPropertyName;
rule.ValidationParameters["maxvalueproperty"] = _maxPropertyName;
yield return rule;
}
От: MVC ненавязчивый диапазон проверки динамических значений
Ответ 2
Я думаю, что лучше всего было бы реализовать пользовательское связующее устройство для вашей конкретной модели (MyModel
). Что бы вы могли сделать, это примерно так:
public class MyModel
{
public int Quantity { get; set; }
} // unchanged Model
public class MyViewModel
{
public MyModel myModel { get; set; }
public int QuantityMin { get; set; }
public int QuantityMax { get; set; }
}
Затем вы можете установить эти значения, а в своем настраиваемом соединителе модели вы можете сравнить свое свойство myModel.Quantity
со свойствами QuantityMin
и QuantityMax
.
Пример
Model
public class QuantityModel
{
public int Quantity { get; set; }
}
ViewMode
public class QuantityViewModel
{
public QuantityModel quantityModel { get; set; }
public int QuantityMin { get; set; }
public int QuantityMax { get; set; }
}
Пользовательская привязка модели:
public class VarQuantity : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
int MinValue = Convert.ToInt32(bindingContext.ValueProvider.GetValue("QuantityMin").AttemptedValue);
int MaxValue = Convert.ToInt32(bindingContext.ValueProvider.GetValue("QuantityMax").AttemptedValue);
int QuantityValue = Convert.ToInt32(bindingContext.ValueProvider.GetValue("quantityModel.Quantity").AttemptedValue);
if (!(QuantityValue >= MinValue && QuantityValue <= MaxValue))
bindingContext.ModelState.AddModelError("Quantity", "Quantity not between values");
return bindingContext.Model;
}
}
Зарегистрировать пользовательскую привязку модели:
ModelBinders.Binders.Add(typeof(QuantityViewModel), new VarQuantity());
Методы действий тестового контроллера:
public ActionResult Quantity()
{
return View();
}
[HttpPost]
public string Quantity(QuantityViewModel qvm)
{
if (ModelState.IsValid)
return "Valid!";
else
return "Invalid!";
}
Код тестового представления:
@model MvcTest.Models.QuantityViewModel
<h2>Quantity</h2>
@using (Html.BeginForm())
{
@Html.Label("Enter Your Quantity: ")
@Html.TextBoxFor(m => m.quantityModel.Quantity)
<br />
@Html.Label("Quantity Minimum: ")
@Html.TextBoxFor(m => m.QuantityMin)
<br />
@Html.Label("Quantity Maximum: ")
@Html.TextBoxFor(m => m.QuantityMax)
<br /><br />
<input type="submit" value="Submit" />
}