Saving form values โ€‹โ€‹after publication (not part of the model)

I have an MVC4 page that has a form with a set of flags, radio buttons and text fields used as search fields. After publication, the results are analyzed, and the grid with lower results is updated with new results. Currently, all form values โ€‹โ€‹are destroyed upon return, and new results are displayed in the grid - only the grid is part of the model.

I want all form options to retain their values โ€‹โ€‹after publication, so the user can see (and change) the choice for the next message / search. The form is filled with 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> } 

the data grid is attached to the model as

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

+6
source share
3 answers

So, this is how I usually solve this problem. My notes are purely my opinion (religious?) On the class names in the MVC project in order to maintain its purpose.

A 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 will configure them so that you can also 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 some partial views of 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 the inclusion of Ajax is pretty crazy (simplified and not entirely accurate):

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

What I usually do is pass the published model back to the view. Thus, the values โ€‹โ€‹are not cleared.

Your code will 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 you first get the form, you will need to create a new Model , otherwise the Model will be empty and will throw an exception when the properties are called.

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 to create models for presentation in MVC.

+1
source

if you use html in mvc then check solution 2 of here , value="@Request["txtNumber1"]" did a great job with me,

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

Hope helps someone.

+1
source

All Articles