使用ASP.NET MVC中的SelectList提交模型

时间:2016-10-07 14:29:20

标签: c# asp.net asp.net-mvc razor

我所拥有的是一个包含多个输入的表单,我想用它来查询数据库以获得一些结果。表单有一些默认值,它都可以工作,但我有问题提交给自己。

返回的错误是“没有为此对象定义的无参数构造函数”,它是由SelectList对象引起的。

我尝试了this solution并使用getter和setter将psUserType设为私有,并将其初始化为空列表,但是我的dropDown菜单在启动时没有值。不确定为什么GetUserTypes没有填充它们。

我在这里做错了什么?如何同时具有预选值并使用用户选择的值发送相同模型,同时还在同一页面上显示结果?

对所有3个动作使用相同的模型是否有意义:1。使用默认值显示表单和输入2.在提交期间发布选定的值3.返回结果和选择的值?我还阅读了this solution,但不知道如何在这里使用2个或3个单独的模型。

感谢任何帮助。提前谢谢。

模型

public class SearchDownloadsModel
{
    public SelectList psUserType { get; private set; } //causes problem on submit
    public string psText { get; set; }
    public MultiSelectList psColumns { get; private set; }
    public IEnumerable<ResultsRowModel> psResults { get; set; }

    public SearchDownloadsModel()
    {            
        this.psUserType = GetUserTypes();          
        this.psColumns = GetColumns();
        this.psResults = new List<ResultsRowModel>(); //empty by default
    }

    public SelectList GetUserTypes()
    {
        List<SelectListItem> items = new List<SelectListItem>()
        {
            new SelectListItem { Value="user", Text="Single User" },
            new SelectListItem { Value="group", Text="User group" },
            ...               
        };
        return new SelectList(items, "Value", "Text");
    }

    public MultiSelectList GetColumns()
    {
        List<SelectListItem> items = new List<SelectListItem>()
        {
            new SelectListItem { Value = "user", Text="Username" },
            new SelectListItem { Value = "file", Text="Filename" },
            new SelectListItem { Value = "titl", Text="Title" },
            new SelectListItem { Value = "auth", Text="Author" },
            ...
        };
        return new MultiSelectList(items, "Value", "Text");
    }
}

public class ResultsRowModel
{
    public int ID { get; set; }
    public string EventTime { get; set; }
    public string FileName { get; set; }
    public string FilePath { get; set; }
    public string UserName { get; set; }
    ...
}

查看

@model Proj.Models.SearchDownloadsModel

@using (Html.BeginForm("Downloads", "Home", FormMethod.Post))
{
   @Html.DropDownListFor(x => x.psUserType, Model.psUserType)
   @Html.TextBoxFor(x => x.psText)
   @Html.ListBoxFor(x => x.psColumnsSelected, Model.psColumns, new { multiple = "multiple" })

   <button type="submit" class="btn btn-primary">Search</button>
}

@if (Model.psResults != null && Model.psResults.Any())
{
    <table>
        <tr>
            <th>User</th>
            <th>File</th>
        </tr>
        @foreach (var row in Model.psResults)
        {
            <tr>
                <td>@row.UserName</td>
                <td>@row.FileName</td>
            </tr>
        }
    </table>
}

控制器

[HttpGet]
public ActionResult Downloads()
{
    SearchDownloadsModel model = new SearchDownloadsModel();
    model.psColumnsSelected = new List<string>() { "user", "file" }; //preselected values
    return View(model);
}

[HttpPost]
public ActionResult Downloads(SearchDownloadsModel model)
{       
    model.psResults = queryDatabase(model);
    return View(model);
}

private List<ResultsRowModel> queryDatabase(SearchDownloadsModel model)
{
    //...
}

编辑:在SearchDownloadsModel

下添加了ResultsRowModel

3 个答案:

答案 0 :(得分:2)

在ASP.NET MVC中,您应该只在ViewModel类中放置包含已发布或已选择值的变量。选择列表项被视为额外信息,通常使用ViewBag项从操作方法传递到视图(.cshtml)。

许多渲染扩展方法甚至专门为这种方法编写,导致代码如下:

<强>控制器

ViewBag.PersonID = persons.ToSelectList(); // generate SelectList here

查看

@Html.DropDownListFor(model => model.PersonID)
@* The above will look for ViewBag.PersonID, based on the name of the model item *@

答案 1 :(得分:0)

DropDownListFor生成一个<select>元素,其中包含绑定它的属性的名称。提交表单时,该名称将作为其中一个表单字段包含在内,其值将是您选择的选项值。

您将DropDownList绑定到SelectList类型的属性(psUserType),当您的操作被调用时,SelectList的新实例必须是创建是为了将表单字段绑定到它。首先,SelectList类没有无参数构造函数,因此也没有错误。其次,即使SelectList可以作为模型绑定的一部分创建,<select>元素也会提交一个字符串值,无论如何都不能转换为SelectList

您需要做的是向string添加SearchDownloadsModel属性,例如:

public string SelectedUserType { get; set; }

然后将下拉列表绑定到此属性:

@Html.DropDownListFor(x => x.SelectedUserType, Model.psUserType)

提交表单时,此新属性将具有您在下拉列表中选择的值。

答案 2 :(得分:0)

彼得的回答和斯蒂芬的评论帮助我解决了这个问题 有些人会发现它很有用。

欢迎任何进一步的建议。

<强>模型

public class PobraniaSzukajModel
{
    public IEnumerable<SelectListItem> UserTypes { get; set; }
    public string psSelectedUserType { get; set; }
    public IEnumerable<SelectListItem> Columns { get; set; }
    public IEnumerable<string> psSelectedColumns { get; set; }
    public string psText { get; set; }
    public ResultsModel psResults { get; set; }
}

查看

@Html.ListBoxFor(x => x.psSelectedUserType, Model.Columns)
@Html.TextBoxFor(x => x.psText)
@Html.ListBoxFor(x => x.psSelectedColumns, Model.Columns)

<强>控制器

[HttpGet]
public ActionResult Downloads()
{    
    SearchDownloadsModelmodel = new SearchDownloadsModel();  
    model.UserTypes = GetUserTypes();
    model.Columns = GetColumns();     
    model.psColumnsSelected = new List<string>() { "user", "file" }; //preselected values
    return View(model);
}

[HttpPost]
public ActionResult Downloads(SearchDownloadsModel model)
{
    model.UserTypes = GetUserTypes();
    model.Columns = GetColumns();     
    model.psResults = GetResults(model);
    return View(model);
}
public SelectList GetUserTypes()
{
    //...
}
public MultiSelectList GetColumns()
{
    //...
}
public ResultsModel GetResults()
{
    //...
}