如何让post action方法将原始视图模型的子对象作为参数

本文关键字:模型 对象 参数 视图 原始 post action 方法 | 更新日期: 2023-09-27 17:52:56

这是我的模型:

public class IndexViewModel
{
    public FilterConditions conditions { get; set }
    public IEnumerable<SelectListItem> Countries { get; set }
}
public class FilterConditions
{
    public string condition11 { get; set }
    // ...
}

我有一个Index动作方法,像这样:

public ActionResult Index()
{
    var model = new IndexViewModel();
    // fill the model here with default values
    return View(model);
}

视图以过滤器条件作为输入类型呈现表单。

现在我想让这个表单返回的post由这个action方法处理:

[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
}

这一切都像它应该的那样工作,但这不是"正确的"(IMHO),因为我不需要返回的"国家"列表,我只需要选定的国家(这是其中一个条件)。

什么是一个很好的(最佳实践)的方式,使这项工作,而不必采取整个原始视图模型作为输入参数?

顺便说一句,我正在使用ASP。. NET MVC 2(我不认为这真的很重要,因为我认为这是同样的问题在MVC 3,但我不完全确定)。

(我一直在互联网上寻找关于asp.net mvc中的下拉列表和视图模型的"最佳实践",但我发现的不同建议并没有真正相互一致,而且很多已经过时了。)我没有找到一个"官方"的最佳实践。我希望我在正确的方向(有列表作为我的视图模型的一部分),请随时纠正我在这个问题上,如果我不是。如果你知道任何关于这方面的"认可的最佳实践",请随时向我指出。

:

我发现我可以使用[Bind]属性加上前缀"filterconditions"。这确实适用于这个观点。但我最初的问题(我承认,它没有包括在我的问题中)没有得到解决。

碰巧这个特定的操作方法也从另一个视图调用(它是一个ajax调用),它没有那个前缀,在这种情况下,它不再工作了。有什么建议吗?

如何让post action方法将原始视图模型的子对象作为参数

我找到解决办法了。

显然,当我为参数变量使用与类型名称相同的名称时(大小写不必匹配),就像这样:

[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了)。显然,默认的模型绑定器使用参数的名称作为绑定的潜在前缀。

我很高兴我发现了,但如果在某个地方更清楚地记录了这一点,那就更好了。这一点也不明显。

编辑:根据请求:这是我视图(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>
<% } %>

嗨,fretje:现在我可以用你的方式来解决你的问题,首先我有两个模型"IndexViewModel" &"Index"和下拉列表(这无关紧要,只提供下拉列表项):

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;
   }
}

和两个控制器是Test()和Test(Models.Index),我通过IndexViewModel和postback IndexModel:

public ActionResult Test()
{
    var result =
        new Models.IndexViewModel
        {
            value = 1,
            items = new Models.DropDownList().GetDropDownList()
        };
    return View(result);
}
[HttpPost]
public ActionResult Test(Models.Index posatback)
{
    return View();
}

Test()的视图是:

<% 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>
<% } %>

的工作!谢谢fretje,我又学到了一项技术:)


也许你可以试试

[HttpPost]
public ActionResult Index([Bind(Exclude="Countries")]IndexViewModel model)
{
    // do some magic with model.conditions and return another view here
}

嗨~你不需要将整个SelectListItem组合到ViewModel,实际上你的ViewModel只有一个字段来存储用户的选择,整数或字符串,然后使用DropDownListFor,如:

<%: Html.DropDownListFor(item.WeaponID, MyApplication.Models.DropDownList.GetDropDownList() )%>

请参阅我的博文,我用一个非常简单的例子来解释:http://maidot.blogspot.com/2011/04/aspnet-mvc-viewdropdownlistfor.html

如果你有任何问题请告诉我