【问题标题】:Retaining Form Values After Post (not part of model)发布后保留表单值(不是模型的一部分)
【发布时间】:2016-06-22 12:58:06
【问题描述】:

我有一个 MVC4 页面,该页面有一个表单,其中包含用作搜索字段的复选框、单选按钮和文本框的集合。发布后,解析选择并使用新结果更新较低的结果网格。现在所有的表单值在返回时都会被清除,新的结果会显示在网格中——只有网格是模型的一部分。

我希望所有表单选择在发布后保留其值,以便用户可以查看(并更改)下一次发布/搜索的选择。表单中填充了 viewbags。

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "searchform" }))
{
    @Html.ValidationSummary("Please correct the following errors")

<div style="float:left;">

    <div style="float:left;">
    <label>Name:</label>
    @Html.TextBox("name")
    </div>

    <div style="float:left; margin-left:15px">
    <label>Company:</label>
    @Html.TextBox("company")
    </div>

    <div style="float:left; margin-left:65px">
    <label>Date Range:</label>
    @Html.TextBox("dateStart", "", new { @class = "datefield", type = "date" })
    &nbsp;to&nbsp;
    @Html.TextBox("dateEnd", "", new { @class = "datefield", type = "date" })
    </div>

</div>

<div style="clear: both;">
    Match Any Categories? <input type="radio" name="categoryMatchAll" value="false" checked="checked" />&nbsp;&nbsp;&nbsp;
    Match All Categories?  <input type="radio" name="categoryMatchAll" value="true" /> 
</div>

<div style="float:left;">

    <div id="searchform-categories" style="float:left;">
        <div class="scroll_checkboxes">
            <label>Categories</label>
            <ul>
            @foreach (var x in ViewBag.Categories)
            {
                    <li>
                        <input type="checkbox" name="categories" value="@x.Id"/>

                        @x.Name

                    </li>
            }
            </ul>
        </div>
    </div>

    <div id="searchform-diversity" style="float:left; margin-left:30px">    
        <div class="search-selection" style="float:left;">
            <label>Minority Owned</label>
            <ul>
                @foreach (var x in ViewBag.Minorities)
                {
                    <li>
                        @Html.RadioButton("minorities", (String)x.Id.ToString())
                        @x.Name
                    </li>
                }
            </ul>
        </div>
        <div class="search-selection" style="float:left;">
            <label>Diversity Class</label>
            <ul>
            @foreach (var x in ViewBag.Classifications)
            {
                <li>
                    @Html.RadioButton("classifications", (String)x.Id.ToString())
                    @x.Name
                </li>
            }
        </ul>
        </div>    
    </div>  

</div>    

<div style="clear: both;">
    <input type="submit" value="Search Profiles" />
    <input type="submit" value="Reset" />
    </div>       
}

数据网格绑定到模型

@model IEnumerable<VendorProfileIntranet.Models.VendorProfile>

<table id="VendorTable" width="100%" class="gradeA">
<thead>
    <tr>
    <th>
        @Html.DisplayNameFor(model => model.Name)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.CompanyName)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.City)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.State)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.DateCreated)
    </th>
    <th>Actions</th>
    </tr>
</thead>
<tbody>

@foreach (var item in Model)
{
<tr>
    <td class="list-field">
        @Html.DisplayFor(modelItem => item.Name)
    </td>
    <td class="list-field">
        @Html.DisplayFor(modelItem => item.CompanyName)
    </td>
    <td class="list-field">
        @Html.DisplayFor(modelItem => item.City)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.State)
    </td>
    <td class="list-field">
        @Html.DisplayFor(modelItem => item.DateCreated)
    </td>
    <td class="list-field">
        @Html.ActionLink("Edit", "Edit", new { id = item.ProfileID }) |
        @Html.ActionLink("View", "View", new { id = item.ProfileID }) |
        @Html.ActionLink("Delete", "Delete", new { id = item.ProfileID }, new { onclick = " return DeleteConfirm()" })
    </td>
</tr>

}

</tbody>
<tfoot>
    <tr>
        <td>&nbsp;</td>
    </tr>
</tfoot>

【问题讨论】:

    标签: asp.net-mvc-4 entity-framework-5


    【解决方案1】:

    如果您在 mvc 中使用 html,请检查 here 的解决方案 2,value="@Request["txtNumber1"]" 对我来说效果很好,

    <input type="text" id="txtNumber1" name="txtNumber1" value="@Request["txtNumber1"]"/>
    

    希望能帮助别人。

    【讨论】:

    • 为什么要投反对票?请解释以在将来添加更好的答案。
    【解决方案2】:

    这就是我通常如何解决这个问题。我的笔记纯粹是我关于在 MVC 项目中命名类以明确其目的的观点(宗教?)。

    几个接口来保持它的可扩展性:

    // be specific about what type of results, both in the name of the 
    // interface and the property needed, you don't want to have overlapping
    // properies on your classes, I like suffixing interfaces that are specific
    // to a View or Partial View with View
    public interface IPersonSearchResultsView
    {
       IEnumerable<EFPerson> PersonSearchResults { get; }
    }
    
    public interface IPersonSearchCriteriaView
    {
      PersonSearchCriteriaModel PersonSearchModel { get; }
    }
    

    几个类

    // I like suffixing classes that I only use for MVC with Model
    public PersonSearchCriteriaModel
    {
      public string Name {get; set;}  
      public string Company {get; set;}
      public string DateStart {get; set;}
      public string DateEnd {get; set;}
    }
    
    // I like suffixing classes that I used passed to a View/Partial View
    // with ViewModel    
    public class PersonSearchViewModel : IPersonSearchResultsView, 
                                         IPersonSearchCriteriaView
    {
      public IEnumerable<EFPerson> PersonSearchResults { get; set; }
      public PersonSearchCriteriaModel PersonSearchModel { get; set; }
    }
    

    现在对于您的控制器,我将设置它们以使您将来也可以使用 Ajax。

    public PersonController : Controller
    {
      public ActionResult Search()
      {
        var model = new PersonSearchViewModel();
        // make sure we don't get a null reference exceptions
        model.PersonSearchModel = new PersonSearchCriteriaModel ();
        model.PersonSearchResults = new List<EFPerson>();
        return this.View(model);
      }
    
      [HttpPost]
      public ActionResult Search(PersonSearchViewModel model)
      {
        model.PersonSearchResults = this.GetPersonResults(model.PersonSearchModel);
    
        return this.View(model)
      }
    
      // You could use this for Ajax
      public ActionResult Results(PersonSearchViewModel model)
      {
        model.PersonSearchResults = this.GetPersonResults(model.PersonSearchModel);
    
        return this.Partial("Partial-SearchResults", model)
      }
    
      private GetPersonResults(PersonSearchCriteriaModel criteria)
      {
        return DbContext.GetPersonResults(criteria)
      }
    }
    

    在您的视图中创建几个局部视图。

    /Views/Person/Partial-SearchCriteria.cshtml

    @model IPersonSearchCriteriaView
    
    // the new part is for htmlAttributes, used by Ajax later
    @using (Html.BeginForm(..., new { id="searchCriteria" }))
    {
      // Here is were the magic is, if you use the @Html.*For(m=>)
      // Methods, they will create names that match the model
      // and you can back back to the same model on Get/Post
    
      <label>Name:</label>
      @Html.TextBoxFor(m => Model.PersonSearchModel.Name)
    
      // or let mvc create a working label automagically
    
      @Html.EditorFor(m => Model.PersonSearchModel.Name)
    
      // or let mvc create the entire form..
    
      @Html.EditorFor(m => Model.PersonSearchModel)
    }
    

    /Views/Person/Partial-SearchResults.cshtml

    @model IPersonSearchResultsView
    
    @foreach (var person in Model.PersonSearchResults )
    {
      <tr>
        <td class="list-field">
          @Html.DisplayFor(modelItem => person.Name)
       </td>
    
       // etc
      </tr>
     }
    

    最后是视图:

    /Views/Person/Search.cshtml

    @model PersonSearchViewModel 
    
    @Html.Partial("Partial-SearchCriteria", Model)
    
    // easily change the order of these
    
    <div id="searchResults">
    @Html.Partial("Partial-SearchResults", Model);
    </div>
    

    现在启用 Ajax 非常简单(很简单,但我并不完全正确):

    $.Ajax({
      url: '/Person/Results',
      data: $('#searchCriteria').serialize(),
      success: function(jsonResult)
      {
        $('#searchResults').innerHtml(jsonResult);
      });
    

    【讨论】:

      【解决方案3】:

      我通常做的是将发布的模型传回视图。这样,值不会被清除。

      您的代码将如下所示:

      <div style="float:left;">
      
          <div style="float:left;">
          <label>Name:</label>
          @Html.TextBox("name", Model.Name)
          </div>
      
      <div style="float:left; margin-left:15px">
      <label>Company:</label>
      @Html.TextBox("company", Model.Company)
      </div>
      
      <div style="float:left; margin-left:65px">
      <label>Date Range:</label>
      @Html.TextBox("dateStart", Model.DateStart, new { @class = "datefield", type = "date" })
      &nbsp;to&nbsp;
      @Html.TextBox("dateEnd", Model.DateEnd, new { @class = "datefield", type = "date" })
      </div>
      

      最初获取表单时,您必须创建一个新的Model,否则Model 将为空并在对其调用属性时引发异常。

      样本模型

      public class SearchModel
      {
      
          public SearchModel()
          {
              Results = new List<Result>();
          }
      
          public string Name {get; set;}  
      
          public string Company {get; set;}
      
          public string DateStart {get; set;}
      
          public string DateEnd {get; set;}
      
          public List<Result> Results {get; set;}
      }
      
      
      @foreach (var item in Model.Results)
      {
      <tr>
          <td class="list-field">
              @Html.DisplayFor(modelItem => item.Name)
          </td>
          <td class="list-field">
              @Html.DisplayFor(modelItem => item.CompanyName)
          </td>
          <td class="list-field">
              @Html.DisplayFor(modelItem => item.City)
          </td>
          <td>
              @Html.DisplayFor(modelItem => item.State)
          </td>
          <td class="list-field">
              @Html.DisplayFor(modelItem => item.DateCreated)
          </td>
          <td class="list-field">
              @Html.ActionLink("Edit", "Edit", new { id = item.ProfileID }) |
              @Html.ActionLink("View", "View", new { id = item.ProfileID }) |
              @Html.ActionLink("Delete", "Delete", new { id = item.ProfileID }, new { onclick = " return DeleteConfirm()" })
          </td>
      </tr>
      
      }
      

      这是一个link,关于在 MVC 中为视图创建模型。

      【讨论】:

      • 我的理解是你只能有一个模型并且已经被数据网格采用,所以我不确定如何整合你的建议。 (见上文更新)
      • @Vic 是的,没错,但模型只是一个类。你可以在课堂上拥有任何东西。
      • @Vic 在 GET 上,结果将为空——不显示任何行。搜索完成后,将显示结果和搜索条件。
      • 谢谢查克。我正在使用 EF5,因此数据模型类是从数据库自动生成的。我不确定如何扩展它以在我的表单中包含搜索字段。你能提供更多关于你建议的细节吗?我也看到一些人建议使用 TempData,但仍然不确定如何在视图中实现它。
      • @Vic 专门为视图创建一个新模型。这与 EF5 数据模型是分开的。通常这些模型存储在 MVC 项目根目录下的 Models 文件夹中。
      猜你喜欢
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-29
      • 2021-04-10
      • 1970-01-01
      • 2020-10-17
      相关资源
      最近更新 更多