Retaining Form Values After Post (not part of model)

时间秒杀一切 提交于 2019-12-05 06:05:46

So here is how I typically solve this problem. My notes are purely my opinion (religous?) about naming classes in an MVC project to keep clear their purpose.

Couple of interfaces to keep it extensible:

// 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; }
}

Couple of classes

// 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; }
}

Now for your controllers, I'll set them up in a way that would also allow you to do Ajax in the future.

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

Create a couple of partial-views your Views.

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

And Finally the view:

/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>

Now enabling Ajax is pretty crazy easy (simplified and my not be exactly right):

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

if you are using html in mvc then check solution 2 from here, value="@Request["txtNumber1"]" worked fine for me,

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

hope helps someone.

What I typically do is pass the posted Model back into the view. This way the values are not cleared out.

Your code would look something like this:

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

When initially getting the form, you'll have to create a new Model, otherwise the Model will be null and throw an exception when properties are called on it.

Sample 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>

}

Here is a link on creating models for a view in MVC.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!