我遇到了一个我认为很有趣的问题。使用ASP.NET MVC中的自定义模型绑定器验证整数字段
取一个输入表单,它有一个整数值的输入字段(在我的情况下为成本)。我不希望将“$ 100”或“20美元”发送到数据库,因为它可能会投诉。我想向模型添加一个错误并将其发回给用户。看似简单;)。
我正在使用自定义模型绑定器,因为我在我的域模型中使用了一些继承。我有多种类型的事件,每种类型实现IEvent - 因此,我需要一个自定义模型绑定器。
我遇到的问题是,当我试图绑定成本字段,并从字符串转换为int失败时,我真的不知道如何最好地处理此问题。
我的自定义模型绑定 公共类EventModelBinder:IModelBinder { #地区IModelBinder成员
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// Trivial code ... binding other fields...
_event.ProjectedCost = GetA<int>(bindingContext, "ProjectedCost").GetValueOrDefault(-1);
return _event;
}
#endregion
// From Scott Hanselman's blog :)
private Nullable<T> GetA<T>(ModelBindingContext bindingContext, string key) where T : struct
{
if (String.IsNullOrEmpty(key)) return null;
ValueProviderResult valueResult;
Nullable<T> ret;
//Try it with the prefix...
bindingContext.ValueProvider.TryGetValue(bindingContext.ModelName + "." + key, out valueResult);
//Didn't work? Try without the prefix if needed...
if (valueResult == null && bindingContext.FallbackToEmptyPrefix == true)
{
bindingContext.ValueProvider.TryGetValue(key, out valueResult);
}
if (valueResult == null)
{
return null;
}
try
{
ret = (Nullable<T>)valueResult.ConvertTo(typeof(T));
}
catch
{
return null;
}
return ret;
}
这个作品真的很好 - 如果枚举为空或不选择,我可以验证对他们,让用户知道它是必需的。对于成本字段,如果转换失败,我会得到-1。但是,当我去验证服务器上的数据并返回到用户界面,该Model.Event.ProjectedCost字段为空
我EventService
// ...
protected bool ValidateEvent(IEvent eventToValidate)
{
if (eventToValidate.ProjectedCost < 0)
_validationDictionary.AddError("ProjectedCost", "Incorrect format");
return _validationDictionary.IsValid;
}
public bool SaveEvent(IEvent _event)
{
if (!ValidateEvent(_event))
return false;
try
{
_repository.SaveEvent(_event);
return true;
}
catch
{
return false;
}
我Edit.aspx查看
<h2>Edit</h2>
<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<p>
<label for="ProjectedCost">ProjectedCost:</label>
<%= Html.TextBox("ProjectedCost", Model.Event.ProjectedCost) %>
<%= Html.ValidationMessage("ProjectedCost", "*") %>
</p>
<% Html.RenderPartial(String.Format("~/Views/Shared/{0}Form.ascx", Model.Event.Type), Model.Event, ViewData); %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>
在我看来,Model.Event.ProjectedCost为空,如果它不验证,给我这个(54号线的罪魁祸首):
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 52: <p>
Line 53: <label for="ProjectedCost">ProjectedCost:</label>
Line 54: <%= Html.TextBox("ProjectedCost", (Model.Event.ProjectedCost == null ? 0 : Model.Event.ProjectedCost)) %>
Line 55: <%= Html.ValidationMessage("ProjectedCost", "*") %>
Line 56: </p>
我喜欢做的是发送用户输入回用户的值,但我的自定义模型联编程序和/或验证逻辑似乎设置为null?
我意识到这可能不是最简单的问题阅读,所以让我知道,如果我能以任何方式澄清!
你肯定你不能使用默认的模型绑定?因为我怀疑活页夹没有做默认的东西,这就是为什么你的值没有被验证返回 – 2010-03-03 14:38:15
我试过了,但我的视图继承自IEvent - 所以默认模型联编程序试图创建一个IEvent实例,它是不可能的,因为它是一个接口。 – Dan 2010-03-03 15:44:50