从 MVC 中发布的表单值填充模型 asp.net

本文关键字:填充 模型 asp net 表单 MVC | 更新日期: 2024-11-06 12:39:19

我有一个SearchViewModel:

public class SearchViewModel
{
    [Required]
    public DateTime From { get; set; }
    [Required]
    public int Days { get; set; }
    public long DealerID { get; set; }
    public IQueryable<TypesAvail> TypesAvails { get; set; }
}

IQueryable TypesAvails 是另一个类,它包含 DealerID 中可用的 CarType 列表,以及 SearchviewModel 类中的"发件人"和"天数"属性之间 - 它还用于在视图中生成下拉列表:

public class TypesAvail
{
    public String TypeNme { get; set; }
    public long TypeID { get; set; }
    public int NumSelected { get; set; }
    public int TypeCount { get; set; }
    public IEnumerable<SelectListItem> CarsAvail 
    {
        get
        {
            return new SelectList(
                    Enumerable.Range(0, TypeCount+1)
                    .OrderBy(typecount => typecount)
                    .Select(typecount => new SelectListItem
                    {
                        Value = typecount.ToString(),
                        Text = typecount.ToString()
                    }), "Value", "Text");
        }
    } 
}

我的控制器是:(编辑:添加了控制器以显示访问数据的代码)

  public ActionResult Avail(SearchViewModel model, string id)
    {
        if (ModelState.IsValid)
        {
            var dteFrom = model.From;
            var dteTo = model.From.AddDays(model.Days);
            var prebookedCars = db.Cars
                .Where(car=> car.Rentals.Any(rental =>
                    (model.DealerID == rental.Dealerid) && (
                    (dteFrom >= rental.dateout && dteFrom < rental.datein )
                    ||
                    (dteTo > rental.dateout && dteTo <= rental.datein )
                    ||
                    (dteFrom <= rental.dateout && dteTo >= rental.datein )
                )));

            model.TypesAvails = db.Cars
                .Where(r => r.Dealerid == model.DealerID)
                .Except(prebookedCars)
                .GroupBy(p => p.CarType)
                .Select(g => new TypesAvail
                {
                    TypeNme = g.Key.type_name,
                    TypeID = g.Key.type_id,
                    TypeCount = g.Count(),
                    NumSelected = 0
                }
                );
            return View(model);
        }
        else
        {
            return View(model);
        }
    }

逻辑(我愿意纠正)如下:

  1. SearchViewModel 被发送到视图,针对 TypesAvail 的空
  2. 当开机自检发生时,控制器使用以下命令将"开始"、"天数"和"经销商 ID"直接填充回模型中:


    [HttpPost] public ActionResult Avail(SearchViewModel model)

  3. 在控制器中,它还会填充 类型可用 IQueryable

因此,现在 ViewModel 具有"搜索日期"、"天数"和"可用类型"列表,其中包括"选择列表"。

这将在视图中重新填充,如下所示:

@model ebm2.ViewModels.SearchViewModel
@using (Html.BeginForm()) 
{
    @Html.ValidationSummary()
    <ul data-role="listview" data-inset="true">
        <li data-role="list-divider">Check Availability</li>
        <li data-role="fieldcontain">
            @Html.LabelFor(m => m.From)
            @Html.TextBoxFor(m => m.From, new { @type = "date", data_role = "datebox", data_options = "{'"mode'":'"slidebox'", '"overrideDateFormat'":'"%A %d %b %Y'"}" })    
            @Html.ValidationMessageFor(m => m.From)    
        </li>           
        <li data-role="fieldcontain">
            @Html.LabelFor(m => m.Days)
            @Html.TextBoxFor(m => m.Days, new { @type = "range", min = 1, max = 30 })            
            @Html.ValidationMessageFor(m => m.Days)    
        </li>
        <li data-role="fieldcontain">
            <input type="submit" value="Search" />
        </li>
    </ul>
    @Html.HiddenFor(m => m.DealerID)
    if (Model.TypesAvails != null)
    {
        <ul data-role="listview" data-inset="true">
            <li data-role="list-divider">Book</li>
            @foreach (var item in Model.TypesAvails)
            {
                <li data-role="fieldcontain">      
                    @Html.HiddenFor(modelItem => item.TypeID) ->
                    @Html.DisplayFor(modelItem => item.NumSelected) ->
                    @Html.DropDownListFor(modelItem => item.NumSelected, item.CarsAvail)
                </li>
            }
        </ul>
    }
}

第二次开机自检到服务器显示:

From=07%2F08%2F2012+00%3A00%3A00& Nights=1 & DealerID=1 & 
item.TypeID=3059 & item.NumSelected=3 & 
item.TypeID=3103 & item.NumSelected=2 & 
item.TypeID=3170 & item.NumSelected=7 & 
item.TypeID=3212 & item.NumSelected=4

显示这些的 Razor 不会将 TypeID 连接到每个 Type 的下拉列表:

@Html.HiddenFor(modelItem => item.TypeID)
@Html.DropDownListFor(modelItem => item.NumSelected, item.CarsAvail)

我的问题是来自 POST 模型 - 显示 NULL for TypesAvail - 有没有办法在回发时直接表示下拉列表中的选定项目?

如果没有,我如何遍历 FORM 字段以创建另一个模型 - 它将具有:

From
Days
DealerID
{
    TypeID = 3059, NumSelected = 3,
    TypeID = 3103, NumSelected = 2,
    TypeID = 3170, NumSelected = 7,
    TypeID = 3212, NumSelected = 4
}

。然后,我可以使用它向我的数据库添加记录(基本上是经销商想要租用的汽车列表,在两个日期之间)。

或者我是否试图从一个表单中获取搜索日期,然后用多个下拉列表填充同一表单,做太多事情 - 有没有更好的方法:

  1. 从日期框和晚数搜索
  2. 然后显示满足搜索条件的选项列表
  3. 然后发布到服务器,并保存搜索数据(从日期、天数、经销商 ID)以及选定的下拉列表,以及每个下拉列表中选择了什么?

谢谢你,马克

更新

在 Syuu 的帮助下,我取得了一些进展 - 我添加了一个编辑器模板:

@model ebm2.Models.TypesAvail
@Html.DropDownListFor(modelItem => modelItem.NumSelected, Model.CarsAvail)

。并在视图中呈现如下:

   @Html.EditorFor(model=>model.TypesAvails)

但是,当我将表单发布回控制器(添加编辑器模板后)时,我收到以下消息:

[MissingMethodException: Cannot create an instance of an interface.]

我假设这意味着它不再识别模型 - 这是因为编辑器模板吗?

我的回发方法,然后添加到ViewModel是最好的方法,还是你建议使用jQuery/Ajax在客户端全部执行 - 并且只有当我有一个完整的JSON对象时,才最终回发到服务器我的模型?

我将不胜感激对此的任何指导。

谢谢,马克

从 MVC 中发布的表单值填充模型 asp.net

使用 EditorTemplate

创建

一个名为"编辑器模板"的文件夹,并创建名为 TypesAvail.cshtml 的视图(编辑器模板

现在将以下代码添加到此新视图中。

@model TypesAvail
<p>
   @Html.DropDownListFor(modelItem => item.NumSelected, item.CarsAvail)
</p>

现在,在主视图中,使用 Html.EditorFor HTML 帮助程序方法调用此编辑器模板

@model ebm2.ViewModels.SearchViewModel
<h2>CarList</h2>
@using (Html.BeginForm())
{
    <p>Put other elements also </p>
    @Html.EditorFor(x=>x.TypesAvails)
    <input type="submit" value="Save" />
}

尝试

        Dim strcon As String = "Data Source=.'SQLEXPRESS;AttachDbFilename=D:'webarticles'App_Data'mydatabase.mdf;Integrated Security=True;User Instance=True"
        Dim con As New SqlConnection(strcon)
        con.Open()

        Dim da As SqlDataAdapter
        Dim ds As New DataSet
        Dim sqlstring As String = "SELECT * FROM tblstudent "
        da = New SqlDataAdapter(sqlstring, con)
        da.Fill(ds)
        FormView1.DataSource = ds.Tables(0)
        FormView1.DataBind()
        Label1.Text = "Formview is filled"


    Catch ex As Exception
        Label1.Text = "There is Some Error"
    End Try

FormView 是用于处理记录的另一个 asp.net 控件,它使您能够使用数据源中的单个记录,类似于 DetailsView 控件。