我发送的是这样的JSON:
[
{col1: 'value', col2: 'value'},
{col1: 'value2', col2: 'value2'},
...
]
我的控制器中的操作有一个List参数,需要自定义模型绑定器,如下所示:
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var contentType = controllerContext.HttpContext.Request.ContentType;
String bodyText;
Stream stream = null;
try
{
stream = controllerContext.HttpContext.Request.InputStream;
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(stream))
{
stream = null;
bodyText = reader.ReadToEnd();
}
}
finally
{
if (stream != null)
stream.Dispose();
}
if (string.IsNullOrEmpty(bodyText))
{
return null;
}
var model = new JavaScriptSerializer().Deserialize<T>(bodyText);
return model;
// return base.BindModel(controllerContext, bindingContext);
}
它正在工作,除了它没有考虑验证的数据注释(必需,范围等)。
如何使用验证?
更新
控制器操作
[HttpPost]
public ActionResult ActionName([ModelBinder(typeof(JsonArrayValidationModelBinder<List<EntityName>>))]List<EntityName> viewModel)
实体
public class EntityName
{
[Display(Name = "Data Entrada")]
[DataType(DataType.Date)]
[Required]
public DateTime? DataEntrada { get; set; }
// ....
}
答案 0 :(得分:0)
从DefaultModelBinder
派生会给你你想要的东西。在你的覆盖中,调用基本方法,如此
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// base BindModel should validate your model
base.BindModel(controllerContext, bindingContext);
// (optional) Capture validation result
bool ModelIsValid = bindingContext.ModelState.IsValid;
var contentType = controllerContext.HttpContext.Request.ContentType;
[...]
}
答案 1 :(得分:0)
我修改了我的答案。我试图让这个工作时遇到了一些问题。下面详述的是我使用的问题和解决方案。
json: 您提供的json与您提供的Model
不符。所以我假设json字符串应该包含这样的内容:
`DataEntrada: "1/1/2014"`
模型: 您的模型仅描述EntityName
。反序列化的json是一个列表。这是两件不同的事情。所以我将json修改为一个定义EntityNames
(EntityName
列表)的对象,如下所示:
`data = { EntityNames: [{ DataEntrada: "1/1/2014" }] };`
然后我实现了这个类..这将是反序列化的结果:
public class EntityInfo
{
public EntityName[] EntityNames { get; set; }
}
最后修改了ActionMethod
,如此:
public JsonResult SaveActionName([ModelBinder(typeof(JsonArrayValidationModelBinder<EntityInfo>))]EntityInfo viewModel)
验证 :验证EntityNames并不像我想象的那样容易实现。在模型绑定期间(作为列表的成员),我无法获取EntityName的验证属性。所以,我实现了一个源自&#39; ValidationAttribute&#39;的自定义验证器。像这样:
public class EntityNamesValidation : ValidationAttribute
{
public override bool IsValid(object value)
{
EntityName[] list = (EntityName[])value;
foreach (EntityName e in list)
{
if (string.IsNullOrEmpty(e.DataEntrada.ToString()))
return false;
// more checks performed here
}
return true;
}
}
然后我将EntityNamesValidation
属性应用于EntityNames
和EntityInfo
,如下所示:
[EntityNamesValidation]
public EntityName[] EntityNames { get; set; }
绑定期间模型不正确 :JsonArrayValidationModelBinder
使用的bindingContext
没有任何实例。如果您在BindModel
之前调试base.BindModel
,您会看到bindingContext.Model
为空。所以我做的是在反序列化之后和调用bindingContext.ModelMetadata.Model = model
之前设置base.BindModel
。我还在代码中移动base.BindModel
,以便在返回model
之前触发...见下文
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
[...]
bindingContext.ModelMetadata.Model = model;
base.BindModel(controllerContext, bindingContext);
return model;
}
验证 :我没有对此进行单元测试,但我确实在ActionMethod
中放置了一个断点。然后我使用了以下json:
data = { EntityNames: [{ DataEntrada: "1/1/2014" }, { DataEntrada: null }] };
当代码到达断点时,ModelState.IsValid
为false。然后我把json更改为:
data = { EntityNames: [{ DataEntrada: "1/1/2014" }, { DataEntrada: "2/19/2014" }] };
当代码到达断点时,ModelState.IsValid
为真。
这种方法有效,但并不理想。我认为您希望在不创建自定义代码的情况下进行验证,并使用MVC来处理此问题。
我希望这会让你更进一步。
的的javascript 强> 的
data = { EntityNames: [{ DataEntrada: "1/1/2014" }, { DataEntrada: null }] };
var jsonOfLog = JSON.stringify(data);
$.ajax({
type: 'POST',
dataType: 'text',
url: "/EntityData/SaveActionName",
data: jsonOfLog,
success: function (data) {
alert(data);
},
error: function (result) {
alert(result);
}
,
async: false
});
的模型强> 的
public class EntityInfo
{
[EntityNamesValidation]
public EntityName[] EntityNames { get; set; }
}
public class EntityName
{
[Display(Name = "Data Entrada")]
[DataType(DataType.Date)]
[Required]
public DateTime? DataEntrada { get; set; }
}
自定义验证器
public class EntityNamesValidation : ValidationAttribute
{
public override bool IsValid(object value)
{
EntityName[] list = (EntityName[])value;
foreach (EntityName e in list)
{
if (string.IsNullOrEmpty(e.DataEntrada.ToString()))
return false;
// more checks performed here
}
return true;
}
}
BindModel
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var contentType = controllerContext.HttpContext.Request.ContentType;
String bodyText;
Stream stream = null;
try
{
stream = controllerContext.HttpContext.Request.InputStream;
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(stream))
{
stream = null;
bodyText = reader.ReadToEnd();
}
}
finally
{
if (stream != null)
stream.Dispose();
}
if (string.IsNullOrEmpty(bodyText))
{
return null;
}
var model = new JavaScriptSerializer().Deserialize<T>(bodyText);
bindingContext.ModelMetadata.Model = model;
base.BindModel(controllerContext, bindingContext);
return model;
}
的 ActionMethod 强> 的
[HttpPost]
public JsonResult SaveActionName([ModelBinder(typeof(JsonArrayValidationModelBinder<EntityInfo>))]EntityInfo viewModel)