注意:这里的所有代码都被解释为一个例子,因为我无法显示真实的代码。
我有一个看起来像
的视图模型类public SearchViewModel
{
public string Term
{
get; set;
}
public SearchResult Result
{
get; set;
}
public List<Filter> Filters
{
get; set;
}
}
这绑定到常规控制器,一切正常:
public ActionResult Search (SearchViewModel model)
{
if (ModelState.IsValid)
{
model.Result = _searchService.Search(model.Term);
return View(model);
}
}
我还有另一个操作来处理从包含复选框的表单中获取POST。此控制器处理创建过滤器类并重定向到“搜索”操作。
类似的东西:
public ActionResult Filter(FormCollection formParams)
{
return RedirectToAction("Search", new SearchViewModel
{
Term = formParams["Term"],
Filters =
formParams.Keys
.Cast<String>()
.Where(k => k.Contains("filter"))
.Select(k => Filter.Build(k, formParams[k]))
.ToList()
});
}
这会传递一个ViewModel,并将List集合填充回搜索操作。
但是,在搜索操作中,ModelState.IsValid现在返回false。这是因为模型绑定器抛出了这个异常:
从类型转换参数 'System.String'键入'Filter' 失败因为没有类型转换器可以 在这些类型之间转换。
查看ModelState中“过滤器”的原始值,显示为字符串:
System.Collections.Generic.List`1[Filter]
似乎在动作之间的转换过程中List的实际内容丢失了,可能是因为它只在属性成员上调用了ToString()。
此时,我有一个模糊的想法,为什么这是失败的,我想我可以写一个自定义模型绑定器或类型转换器,使其工作,但是,我觉得这种方法闻起来,这是可能是微不足道的事情,我只是接近它错了。
那么,将一组复杂类型从一个动作传递到另一个动作的适当的ASP.NET MVC 3是什么?
答案 0 :(得分:0)
RedirectToAction只是一个HTTP 302重定向。您确定需要浏览器重新申请新页面吗?
例如,您是否希望通过触发“重新提交发布数据”对话框来避免页面重新加载? (参见POST-REDIRECT-GET模式)
为什么不使用:
public ActionResult Filter(FormCollection formParams)
{
return Search(new SearchViewModel{
Term = formParams["Term"],
Filters =
formParams.Keys
.Cast<String>()
.Where(k => k.Contains("filter"))
.Select(k => Filter.Build(k, formParams[k]))
.ToList()
});
}
或者,您可以使用TempData在请求之间存储状态,或者如果合适,可以使用客户端cookie。
如果您希望搜索结果页面在用户浏览器中可收藏,则需要使用REST或某种形式的序列化字符串(例如JSON)在URL中表示搜索参数的状态
答案 1 :(得分:0)
导致此错误的常见原因之一是使用某种reserve words
,例如&#34;操作,评论,过滤等等&#34; 。因此,使用其他名称(即&#34; ApplyFilter&#34; )更改Action
名称&#34;过滤&#34; 可能会解决问题。希望这会有所帮助...