2016-10-07 38 views
0

我所擁有的是一個包含多個輸入的表單,我想用它來查詢數據庫中的某些結果。表單有一些默認值,它都可以工作,但我有問題提交給自己。在ASP.NET MVC中使用SelectList提交模型

返回的錯誤是「No paramaterless constructor defined for this object」,它是由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

+1

你能不能也請添加類的定義「ResultsRow模型「 –

+0

我同意@KD - 你的一個類有一個構造函數,它接受參數(例如, '公共MyClass(字符串1,字符串2)'),但沒有構造函數沒有(例如'公共MyClass()')並導致此錯誤。看看你的類,你應該能夠弄清楚這一個自己:)信息在這裏:http://stackoverflow.com/questions/1355464/asp-net-mvc-no-parameterless-constructor-defined-for -this-object –

+0

@KD ResultsRowModel幾乎就是一個類,它具有存儲像'public string NameColumn {get; set;}'這樣的列的屬性,沒有別的。 – yosh

回答

0

下ResultsRowModel的DropDownListFor產生與你綁定它的屬性的名稱<select>元素。當您提交表單時,該名稱將被包含爲表單域中的一個,其值將是您選擇的選項值。

你綁定DropDownListSelectList類型(psUserType),當你的行動被調用時,必須創建的SelectList一個新實例的屬性以表單域綁定到它。首先,SelectList類不具有無參數的構造函數,因此,您的錯誤。其次,即使SelectList可以創建爲模型綁定的一部分,但<select>元素正在提交字符串值,無論如何,該字符串值都不能轉換爲SelectList

你需要做的是一個string屬性添加到您的SearchDownloadsModel,例如:

public string SelectedUserType { get; set; } 

然後下拉列表綁定到這個屬性:

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

當您提交表單,這個新的屬性將具有您在下拉菜單中選擇的值。

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 *@ 
+0

好的答案,@Peter!我會更頻繁地使用'.ToSelectList()'擴展方法,現在:) –

+0

建議OP使用'ViewBag'而不是視圖模型屬性是可怕的建議。 –

+0

ViewBag包含列表,並且Model包含所選的項目ID。我沒有提出這種方法,微軟也這麼做,並且他們的許多例子都使用它。 –

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() 
{ 
    //... 
} 
+1

你已經有了一個視圖模型,所以要使用它,而不是使用無類型的'ViewBag'(typeof'dynamic')。模型應該包含一個屬性'public IEnumerable Columns {get;組; }'在視圖中它只是'@ Html.ListBoxFor(x => x.psSelectedColumns,Model.Columns)'(不需要強制轉換) –

+0

@StephenMuecke如果我這樣做,會導致錯誤:「ViewData項目鍵'psSelectedColumns'的類型是'System.String []',但必須是'IEnumerable '的類型。「這是否意味着我必須改變我聲明預選值的方式? – yosh

+1

不,你只需要重新填充SelectList(s),如果你需要返回視圖(就像你在GET方法中做的一樣,而你現在正在使用ViewBag而不是視圖模型) - 另請參閱[The具有鍵'XXX'的ViewData項目的類型爲'System.Int32',但必須是'IEnumerable '類型的(http://stackoverflow.com/questions/34366305/the-viewdata-item-that-有-key-xxx-is-of-type-system-int32-but-must-o -o) –