通常,类成员的ModelBinding验证可能就像这个例子一样:
public Class someclass
{
[StringLength(50)]
public string SomeValue { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
SomeValue最多限制为50个字符.
是否可以在运行时将常量(50)更改为其他内容,例如,在构造该类的每个实例期间,以便可以使用具有不同StringLength限制的不同实例?
如果是这样,那怎么做呢?
当我为一个Guid字段发布一个带有空字符串""的表单时,我收到错误"MyGuid字段是必需的".虽然我没有设置"必需"属性.
//NOT Required
public Guid MyGuid { get; set; }
Run Code Online (Sandbox Code Playgroud)
在模型绑定之后,Guid是00000000-0000-0000-0000-000000000000(因为它是默认值)并且这是正确的.但ModelState有上述错误.
我怎样才能避免这个错误?
附加信息:
[Required(AllowEmptyStrings = true)] 没有帮助
我不想让Guid为nullable(Guid?),因为这会导致很多额外的代码(检查它是否有值,映射等)
更新:
好的,我发现Guid?在我的视图模型中的更改不会导致比我预期的更多更改(一些调用MyGuid.GetValueOrDefault()或一些检查MyGuid.HasValue和调用MyGuid.Value).
但是,如果没有为post请求提供有效的Guid,则添加模型错误的原因是DefaultModelBinder尝试绑定null到Guid.解决方案是覆盖DefaultModelBinder.并且不会在模型状态中添加任何错误
public class MyModelBinder : DefaultModelBinder
{
protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
{
if (propertyDescriptor.PropertyType == typeof(Guid) && value == null)
{
value = Guid.Empty;
}
base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
} …Run Code Online (Sandbox Code Playgroud) 我想知道模型绑定在ASP.NET MVC3中是如何工作的.由于我还在等待我的专业ASP.NET MVC3书籍,我通过谷歌搜索找不到任何东西,你是我最后的希望.
我知道如何使用简单对象执行绑定,但是当涉及到ViewModels时,尤其是嵌套时List<T>,我无法执行绑定.
谢谢
弗朗切斯科
更新:
为了澄清,我的意思是从View到Action Methods的模型绑定,谢谢
我在我的模型上有一组对象,我使用EditFor函数在View中渲染,我有一个EditorTemplate,负责实际渲染每个对象.
@Html.EditorFor(model => model.MyObjects)
Run Code Online (Sandbox Code Playgroud)
这已经运行了一段时间了,当你检查html时,我的文本框以model属性为前缀,后面跟着它们来自的集合的索引.
<input class="text-box single-line" id="MyObjects_2__SomeProperty"
name="MyObjects[2].SomeProperty" type="Text" value="" />
Run Code Online (Sandbox Code Playgroud)
但是我最近开始在集合的模型元数据中使用ShowForEdit和ShowForDisplay属性,如果ShowForEdit不是真的,在我的编辑器模板的第一行,我只是跳过它.
@if (!ViewData.ModelMetadata.ShowForEdit)
{
return;
}
Run Code Online (Sandbox Code Playgroud)
但由于这些都是在html中编入索引,当我尝试通过回发将此集合保存回viewmodel时,由于依赖于索引编号而失败.当我检查它的值时,我的视图模型中缺少缺少索引后的集合中的每个项目.
在这种情况下,它实际上是我正在跳过的集合中的第一个项目,因为我不希望它在编辑视图中可见,但是因为当我回发html中的第一个索引是1(而不是0)像往常一样),但是当你尝试保存更改时这是一个问题.使用javascript更改DOM时,这也是一个问题.
当html表示集合中的一个或多个索引不存在时,有没有其他人遇到默认模型绑定器读取回发数据的能力?
是否有模型粘合剂来处理这个问题?
asp.net-mvc defaultmodelbinder model-binding modelbinders asp.net-mvc-3
我的视图模型中的某些decimal和decimal?属性被标记为"百分比"数据类型以及其他数据注释,例如:
[DataType("Percent")]
[Display(Name = "Percent of foo completed")]
[Range(0, 1)]
public decimal? FooPercent { get; set; }
Run Code Online (Sandbox Code Playgroud)
我想允许用户在输入数据方面有一些灵活性,即有或没有百分号,中间空格等.但我仍然希望使用该DefaultModelBinder行为来获取其所有功能,例如检查RangeAttribute和添加适当的验证消息.
有没有办法解析和更改模型值,然后传递它?这是我正在尝试的,但我得到一个运行时异常.(忽略实际的解析逻辑;这不是它的最终形式.此时我只对模型替换问题感兴趣.)
public class PercentModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
if (bindingContext.ModelMetadata.DataTypeName == "Percent")
{
ValueProviderResult result =
bindingContext.ValueProvider.GetValue(
bindingContext.ModelName);
if (result != null)
{
string stringValue =
(string)result.ConvertTo(typeof(string));
decimal decimalValue;
if (!string.IsNullOrWhiteSpace(stringValue) &&
decimal.TryParse(
stringValue.TrimEnd(new char[] { '%', ' ' }),
out decimalValue))
{
decimalValue /= …Run Code Online (Sandbox Code Playgroud) 我的理解是ASP.NET MVC只允许您将对象POST到Controller中的Actions,其中Action的参数接受已发布的对象作为Concrete类.
有什么方法可以解决这个问题,还是一个不错的选择?
在我的例子中,我有一个接受接口作为参数的动作:
public ActionResult SaveAdjustment(IModel model)
{
switch (model.SubsetType)
{
// factory like usage
}
}
Run Code Online (Sandbox Code Playgroud)
对于这个动作,我有很多视图,所有视图都强烈地输入到实现IModel的对象,我希望能够将这些视图发布到这个方法.
当然,运行这个给我错误:
无法创建接口的实例
有一个很好的工作吗?或者我是否需要为每个创建一个Action方法并将它们发送到这样的方法?
这与这个问题有关,但在这种情况下,它不是我要返回的东西,而是模型绑定.我正在使用Postmark来处理传入的电子邮件,这些电子邮件会发布到具有JSON有效负载的页面.
我有一个如下所示的模型和一个接受此JSON有效负载(使用application/json发布)并处理它的操作.
public class EmailModel
{
public IDictionary<string, string> Headers { get; set; }
public string From { get; set; }
public string Cc { get; set; }
public string HtmlBody { get; set; }
public string TextBody { get; set; }
public string ReplyTo { get; set; }
public string Tag { get; set; }
public string To { get; set; }
public string MessageID { get; set; }
public string MailboxHash { …Run Code Online (Sandbox Code Playgroud) model-view-controller asp.net-mvc model-binding custom-model-binder
我目前有一个ViewModel设置:
public class OurViewModel
{
public OurViewModel() { }
[Required]
public int LeadID { get; set; }
[Required]
public int Rate { get; set; }
[Required]
public bool DepositRequired { get; set; }
[RequiredIfOtherPropertyIsTrue("DepositRequired")]
public BankInfo { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
...在这种情况下,"RequiredIfOtherPropertyIsTrue"是一个验证器,它完全按照它所说的:检查另一个属性是否为真(在这种情况下,我们的布尔值表示是否需要存款),而BankInfo是另一个属性看起来像这样的模型:
public class BankInfo
{
public enum AccountTypeEnum
{
CHECKING,
SAVINGS
}
public BankAccountInfo() { }
[DisplayName("Account Number")]
[Required(ErrorMessage = "You must provide a valid bank account number")]
public String AccountNumber { get; set; }
[DisplayName("Bank Routing Number")]
[Required(ErrorMessage …Run Code Online (Sandbox Code Playgroud) 我的视图模型中有一些属性在保存时是可选的,但在提交时是必需的.总之,我们允许部分保存,但提交整个表单,我们确实希望确保所有必填字段都有值.
我现在能想到的唯一方法是:
视图模型具有所有[Required]属性.如果请求是部分保存,则在进入控制器操作时ModelState.IsValid变为false.然后我运行所有ModelState(这是一个ICollection<KeyValuePair<string, ModelState>>)错误并删除[Required]属性引发的所有错误.
但是如果请求是提交整个表单,我不会干涉ModelState和[Required]属性生效.
这个更难看.一个视图模型将包含[Required]操作方法用于提交的所有属性.但是对于部分保存,我将表单数据发布到使用相同视图模型而没有所有[Required]属性的不同操作.
显然,我最终会遇到很多重复的代码/视图模型.
我一直在考虑是否可以[SubmitRequired]为这些必需的属性创建自定义数据注释属性.并且以某种方式使得验证在部分保存时忽略它,但在提交时则忽略.
仍然没有一个明确的线索.有人可以帮忙吗?谢谢.
我正在尝试在MVC中使用自定义模型绑定程序,该绑定程序需要从IoC容器中解析。我遇到的问题是,在添加MVC服务时无法访问我的容器,因为还没有构建我的容器(并且我需要在构建容器之前添加MVC)。感觉就像是鸡/鸡蛋的问题,我确信我缺少一个简单的解决方案。
例:
services.AddMvc().AddMvcOptions(options =>
{
options.ModelBinders.Add(serviceProvider.Resolve<CustomModelBinder>());
});
Run Code Online (Sandbox Code Playgroud)
我的自定义模型活页夹如下所示:
public class CustomModelBinder : IModelBinder
{
private IServiceProvider serviceProvider;
public CustomModelBinder(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
{
var model = serviceProvider.GetService(bindingContext.ModelType);
bindingContext.Model = model;
var binder = new GenericModelBinder();
return binder.BindModelAsync(bindingContext);
}
}
Run Code Online (Sandbox Code Playgroud) model-binding ×10
asp.net-mvc ×8
c# ×4
validation ×3
action ×1
asp.net ×1
asp.net-core ×1
autofac ×1
interface ×1
modelbinders ×1
viewmodel ×1