ViewModel 上的 MVC2 DataAnnotations - 不明白将其与 MVVM 模式一起使用
我有一个使用 MVVM 模式的 MVC2 应用程序。我正在尝试使用数据注释来验证表单输入。
在我的 ThingsController 中,我有两种方法:
[HttpGet]
public ActionResult Index()
{
return View();
}
public ActionResult Details(ThingsViewModel tvm)
{
if (!ModelState.IsValid) return View(tvm);
try
{
Query q = new Query(tvm.Query);
ThingRepository repository = new ThingRepository(q);
tvm.Things = repository.All();
return View(tvm);
}
catch (Exception)
{
return View();
}
}
我的 Details.aspx 视图强类型化为 ThingsViewModel:
<%@ Page Title=""
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<Config.Web.Models.ThingsViewModel>" %>
ViewModel 是一个由返回的 Thing 对象的 IList 和查询字符串(在表单上提交)组成的类,并且具有所需的数据注释:
public class ThingsViewModel
{
public IList<Thing> Things{ get; set; }
[Required(ErrorMessage="You must enter a query")]
public string Query { get; set; }
}
当我运行此命令并单击表单上的提交按钮而不输入值时,我收到 YSOD 并显示以下错误:
The model item passed into the dictionary is of type
'Config.Web.Models.ThingsViewModel', but this dictionary
requires a model item of type
System.Collections.Generic.IEnumerable`1[Config.Domain.Entities.Thing]'.
如何获取数据注释以与 ViewModel 一起使用?我看不到我遗漏了什么或哪里出了问题——在我开始进行验证之前,虚拟机工作得很好。
I have an MVC2 Application that uses MVVM pattern. I am trying use Data Annotations to validate form input.
In my ThingsController I have two methods:
[HttpGet]
public ActionResult Index()
{
return View();
}
public ActionResult Details(ThingsViewModel tvm)
{
if (!ModelState.IsValid) return View(tvm);
try
{
Query q = new Query(tvm.Query);
ThingRepository repository = new ThingRepository(q);
tvm.Things = repository.All();
return View(tvm);
}
catch (Exception)
{
return View();
}
}
My Details.aspx view is strongly typed to the ThingsViewModel:
<%@ Page Title=""
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<Config.Web.Models.ThingsViewModel>" %>
The ViewModel is a class consisting of a IList of returned Thing objects and the Query string (which is submitted on the form) and has the Required data annotation:
public class ThingsViewModel
{
public IList<Thing> Things{ get; set; }
[Required(ErrorMessage="You must enter a query")]
public string Query { get; set; }
}
When I run this, and click the submit button on the form without entering a value I get a YSOD with the following error:
The model item passed into the dictionary is of type
'Config.Web.Models.ThingsViewModel', but this dictionary
requires a model item of type
System.Collections.Generic.IEnumerable`1[Config.Domain.Entities.Thing]'.
How can I get Data Annotations to work with a ViewModel? I cannot see what I'm missing or where I'm going wrong - the VM was working just fine before I started mucking around with validation.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为问题不在于验证。
改变这一行;
对此
我不知道这是什么或它有什么作用;
它接受一个字符串参数并返回某种 Linq IQueriable 或 List?如果返回其他内容,则可能会导致问题。
I don't think the problem is with the validation.
Change this line;
to this
I don't know what this is or what it does;
It takes a string parameter and returns some kind of Linq IQueriable or List? If that's returning something else it could be causing the problem.
您是否启用了客户端验证?它甚至可能是一个快速的黑客修复,但关于错误消息 - 没有额外的信息很难说。你能发布你的视图和渲染的 Html 吗?
您的详细信息路线是什么样的?
如果您在 Details 方法的开头设置断点,那么当您单击提交按钮时,断点是否会被命中?
Do you have client-side validation enabled? It might even be a quick hacky-fix, but regarding the error message - it's tough to say without extra info. Could you post your View and the rendered Html?
What does your route for Details look like?
If you set a breakpoint at the start of the Details method, does it get hit when you click on the submit button?
看起来您可以像这样声明您的 ThingsViewModel:
然后根据需要实现接口来访问事物列表。
It looks like you could just declare your ThingsViewModel like so:
and then implement the interface as appropriate to access the Things list.
我认为 ASP.NET MVC 可能会尝试将您的视图映射到错误的控制器。返回视图时,您可能需要指定您尝试使用的视图文件名。
返回视图(“视图名称”)
I think that ASP.NET MVC might be trying to map your view to the wrong controller. When you return the view you might need to specify the view file name you're trying to use.
return View("ViewName")