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

时间:2012-08-07 15:55:20

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

我有一个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和SearchviewModel类中From和Days属性之间可用的CarTypes列表 - 它还用于在视图中生成下拉列表:

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将发送到View with null对TypesAvail
  2. 当Post发生时,控制器使用以下方法将From,Days和DealerID直接填充到模型中:

    [HttpPost]
    public ActionResult Avail(SearchViewModel model)

  3. 在控制器中,它还会填充TypesAvail IQueryable

  4. 现在,ViewModel具有搜索日期,天数和TypesAvailable列表,其中包括选择列表。

    这在以下视图中重新填充:

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

    返回服务器的第二个POST显示:

    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分配给每个下拉列表:

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

    我的问题来自POST模型 - 显示了TypesAvail的NULL - 有没有办法在下拉列表中直接表示所选项目,直接回传到ViewModel?

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

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

    ...然后我可以用来将记录添加到我的数据库中(基本上是经销商想要在两个日期之间雇用的汽车列表)。

    或者我是尝试从一个表单中获取搜索日期,然后使用多个下拉列表填充相同的表单,做太多 - 并且有更好的方法:

    1. 从日期框和夜晚搜索
    2. 然后显示符合搜索条件的选项列表
    3. 然后发布到服务器,并保存搜索数据(从日期,天数,经销商ID),以及选定的下拉列表,以及每个选择的内容?
    4. 谢谢Mark,

      更新

      在Shyu的帮助下,我取得了一些进展 - 我添加了一个editortemplate:

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

      ...并在视图中使用以下内容进行渲染:

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

      然而,当我然后将表单发回控制器(添加editorTemplate之后)后,我收到以下消息:

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

      我认为这意味着它不再能识别模型 - 这是因为EditorTemplate吗?

      我的回发方法,然后向ViewModel添加最好的方法,或者你建议用jQuery / Ajax做所有客户端 - 并且最后只发布回服务器,当我有我模型的完整JSON对象?

      我很感激任何指导。

      谢谢,Mark

2 个答案:

答案 0 :(得分:1)

使用 EditorTemplate

创建一个名为“EditorTemplates”的文件夹,并创建一个名为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" />
}

答案 1 :(得分:1)

尝试

        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控件。