C# 如何让后期操作方法将原始viewmodel的子对象作为参数?
这是我的模型:C# 如何让后期操作方法将原始viewmodel的子对象作为参数?,c#,asp.net-mvc,viewmodel,C#,Asp.net Mvc,Viewmodel,这是我的模型: public class IndexViewModel { public FilterConditions conditions { get; set } public IEnumerable<SelectListItem> Countries { get; set } } public class FilterConditions { public string condition11 { get; set } // ... }
public class IndexViewModel
{
public FilterConditions conditions { get; set }
public IEnumerable<SelectListItem> Countries { get; set }
}
public class FilterConditions
{
public string condition11 { get; set }
// ...
}
该视图以filterconditions作为输入类型呈现窗体
现在,我希望通过以下操作方法处理来自该表单的帖子:
[HttpPost]
public ActionResult Index(FilterConditions model)
{
// do some magic with model and return another view here
}
这实际上是可行的,我在方法中放了一个断点,然后调用它,但是我的模型的属性总是空的默认值,而它们应该包含表单发布的值
当我修改动作方法时,如下所示:
[HttpPost]
public ActionResult Index(IndexViewModel model)
{
// do some magic with model.conditions and return another view here
}
[HttpPost]
public ActionResult Index(FilterConditions filterConditions)
{
// do some magic with model and return another view here
// now the filterConditions variable actually contains values!
}
这一切都像它应该的那样工作,但这不是正确的IMHO,因为我不需要返回的“国家”列表,我只需要选择的国家,这是条件之一
在不必将整个原始viewmodel作为输入参数的情况下,实现此功能的最佳实践方法是什么
顺便说一句,我使用的是ASP.NET MVC 2,我认为这并不重要,因为我认为MVC 3中也存在同样的问题,但我不能完全确定这一点
我一直在互联网上寻找关于asp.net mvc中DropDownList和viewmodels的最佳实践,但我发现不同的建议并不完全一致,很多建议也已经过时。我没有找到官方的最佳实践。我希望我正在朝着正确的方向前进,将列表作为我的viewmodel的一部分,如果我没有这样做,请随时纠正我的错误。如果您知道任何关于这方面的最佳实践,请随时向我指出
更新:
我发现我可以使用带有filterconditions前缀的[Bind]属性。这确实适用于这种观点。但我承认我原来的问题,它并没有包括在我的问题并没有解决
碰巧,这个特定的操作方法也从另一个视图调用。这是一个ajax调用,它没有前缀,在这种情况下,它现在不再工作了。有什么建议吗?嗨,fretje:现在我可以用你的方式来解决你的问题,首先我有两个模型IndexViewModel&Index,DropDownlit不重要,只提供下拉项:
public class IndexViewModel : Index
{
//public int value { get; set; }
public List<System.Web.Mvc.SelectListItem> items { get; set; }
}
public class Index
{
public int value { get; set; }
}
class DropDownList
{
public List<System.Web.Mvc.SelectListItem> GetDropDownList()
{
List<System.Web.Mvc.SelectListItem> result = new List<System.Web.Mvc.SelectListItem>();
result.Add(new System.Web.Mvc.SelectListItem
{
Value = "1",
Text = "Apple"
});
result.Add(new System.Web.Mvc.SelectListItem
{
Value = "2",
Text = "Milk"
});
return result;
}
}
测试的观点是:
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-field">
<%: Html.DropDownListFor(m=>m.value, Model.items )%>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
嗨~
您不需要将整个SelectListItem组合到ViewModel,实际上您的ViewModel只有一个字段来存储用户的选项、整数或字符串,然后使用DropDownList进行类似操作:
<%: Html.DropDownListFor(item.WeaponID, MyApplication.Models.DropDownList.GetDropDownList() )%>
请看我在blogspot上的帖子,我用一个非常简单的例子来解释:
如果您有任何问题,请告诉我:我找到了解决方案 显然,当我对参数变量使用与类型名称相同的名称时,大小写不必匹配,如下所示:
[HttpPost]
public ActionResult Index(IndexViewModel model)
{
// do some magic with model.conditions and return another view here
}
[HttpPost]
public ActionResult Index(FilterConditions filterConditions)
{
// do some magic with model and return another view here
// now the filterConditions variable actually contains values!
}
如果我的filterConditions的值不再为空/null,一切都会正常工作。显然,默认modelbinder使用参数的名称作为绑定的潜在前缀
我很高兴我发现了这一点,但如果能在某个地方更清楚地记录下来,那就太好了。这一点都不明显
编辑:
请求时:这是我的视图aspx中的代码:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyProject.Models.IndexViewModel>" %>
<%-- ... more stuff here ... --%>
<% using (Html.BeginForm())
{%>
<%= Html.ValidationSummary(true)%>
<fieldset>
<div class="editor-label">
<%= Html.LabelFor(model => model.FilterConditions.Country)%>
</div>
<div class="editor-field">
<%= Html.DropDownListFor(model => model.FilterConditions.Country, Model.Countries)%>
<%= Html.ValidationMessageFor(model => model.FilterConditions.Country)%>
</div>
<div class="editor-label">
<%= Html.LabelFor(model => model.FilterConditions.Make)%>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model.FilterConditions.Make)%>
<%= Html.ValidationMessageFor(model => model.FilterConditions.Make)%>
</div>
<%-- ... more fields inserted here ... --%>
<p>
<input type="submit" value=" Search... " />
</p>
</fieldset>
<% } %>
据我所知,最佳实践是控制器应收集所有数据并将其传递给视图。在您的示例中,视图本身正在查询模型。我认为在ASP.NET MVC中,这不是正确的做法。您也可以同时传递两个模型进行查看,一个是我们的视图模型,另一个是列表模型,这很好。@Maidot:这正是我的问题。要传递这两个模型,在我的例子中,您必须将它们封装在包装类DefaultViewModel中,这样我的模型实际上是DefaultViewModel的子对象。对不起,我太笨了:,您尝试过[BindExclude=blah]吗。但我不确定这是否是您想要的,因为它可能会将所有信息传递给服务器端。@Maidot:我想要的是将DefaultViewModel作为我的操作方法的参数去掉。所以排除不是我需要的。虽然我发现我可以使用前缀,但后来我遇到了另一个问题,请看我更新的问题。听起来你想用两种方式来称呼它。。。也许您可以在每种方式中使用一个参数,并根据设置的值选择要使用的参数。您是使用AjaxForm进行ajax调用还是使用jQuery ajax?@nEEbz:我使用jQuery ajax,但这并不重要,因为我也有不使用ajax的问题。我发现这有点难以理解。对于public ActionResult IndexIndexViewModel模型,您是否尝试只发送筛选条件而不发送国家/地区?我认为模型绑定器只会智能地绑定FilterConditions条件,并将国家列表保留为空。@nEEbz:我只发送条件。这实际上是通过发布表单自动完成的,由于表单上的字段仅来自筛选条件,模型的其他字段将填充我的下拉列表,因此仅发送这些字段。我的问题是,如果我只将FilterConditions模型指定为action方法的参数,则默认的模型绑定器不会将它们解析到模型对象中。它确实起作用
当我指定FilterConditions时,FilterConditions可以看到我的答案。您更改了参数的名称,它开始工作了吗?我可能很烦人,你能给我们看一下你的表单/视图吗?它包含过滤条件元素。只是为了我们的学习目的。我一直认为模型绑定器使用name属性将元素绑定到控制器参数名称。@nEEbz:好了。更新了我的答案。
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyProject.Models.IndexViewModel>" %>
<%-- ... more stuff here ... --%>
<% using (Html.BeginForm())
{%>
<%= Html.ValidationSummary(true)%>
<fieldset>
<div class="editor-label">
<%= Html.LabelFor(model => model.FilterConditions.Country)%>
</div>
<div class="editor-field">
<%= Html.DropDownListFor(model => model.FilterConditions.Country, Model.Countries)%>
<%= Html.ValidationMessageFor(model => model.FilterConditions.Country)%>
</div>
<div class="editor-label">
<%= Html.LabelFor(model => model.FilterConditions.Make)%>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model.FilterConditions.Make)%>
<%= Html.ValidationMessageFor(model => model.FilterConditions.Make)%>
</div>
<%-- ... more fields inserted here ... --%>
<p>
<input type="submit" value=" Search... " />
</p>
</fieldset>
<% } %>