MVC Dropdown list persting for each requests - asp.net-mvc-3

I am working on a web app using MVC, where all pages have header section consiting of three dropdowns one text box and an image button. So no matter on which page user is, he/she has ability to select a combination out of three dropdowns, enter some text in text box and hit image button to search in database.
So i am using a strongly typed(BaseViewModel) master _Layoutthought, and then add two partial views on it, one to display user info and another one to display all dropdowns, text box and imaage button. Now, Models i have 3 models for each dropdown option/item and then a BaseViewModel which will have 3 properties as a list of each model and 3 int properties to hold selected item ID. And plan is to use this baseViewModel as parent class for all viewmodels so that i can fullfil my strongly tyed _Layout for each request and responce. OK i am not sure that if i have explained my requirement clearly :(.
so here is the code
all models:
namespace XYZNameSpace.Models
{
public class ManageCompany
{
public long ManageCompanyID { get; set; }
public string ManageCompanyName { get; set; }
}
}
namespace XYZNameSpace.Models
{
public class SuperCompany
{
public long SuperCompanyID { get; set; }
public string SuperCompanyName { get; set; }
}
}
public class User
{
public long UserID { get; set; }
public string UserName { get; set; }
public string UserLoginName { get; set; }
public string UserLevel { get; set; }
public int UserLevelId { get; set; }
}
namespace XYZNameSpace.Models
{
public class SearchResult
{
public string CompanyName { get; set; }
public string SubCompanyName { get; set; }
public string UserName { get; set; }
}
}
ViewModel
namespace XYZNameSpace.ViewModels
{
public class BaseViewModel : User
{
public long SelectedManageCompanyID { get; set; }
public List<SelectListItem> ManageCompanyList { get; set; }
public string SelectedManageCompanyName { get; set; }
public long SelectedSuperCompanyID { get; set; }
public List<SelectListItem> SuperCompanyList { get; set; }
public string SelectedSuperCompnayName { get; set; }
public int SelectedSearchOptionID { get; set; }
public List<SelectListItem> SearchOptionsList { get; set; }
public string SelectedSearchOptionName { get; set; }
public string SearchWord { get; set; }
}
public class SearchOption
{
public int SearchOptionID { get; set; }
public string SearchOptionName { get; set; }
}
}
namespace XYZNameSpace.ViewModels
{
public class SearchResultsViewModel : BaseViewModel
{
public List<SearchResult> ResultsList { get; set; }
}
}
Controller
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Home()
{
BaseViewModel bVM = new BaseViewModel()
{
ManageCompanyList = (new List<ManageCompany>() {
new ManageCompany()
{
ManageCompanyID = 1,
ManageCompanyName = "MC 1"
},
new ManageCompany()
{
ManageCompanyID = 2,
ManageCompanyName = "MC 2"
},
new ManageCompany()
{
ManageCompanyID = 3,
ManageCompanyName = "MC 3"
},
new ManageCompany()
{
ManageCompanyID = 4,
ManageCompanyName = "MC 4"
},
new ManageCompany()
{
ManageCompanyID = 5,
ManageCompanyName = "MC 5"
}
}).Select(x => new SelectListItem { Value = x.ManageCompanyID.ToString(), Text = x.ManageCompanyName }).ToList(),
SuperCompanyList = (new List<SuperCompany>(){
new SuperCompany(){
SuperCompanyID=6,
SuperCompanyName="SC 6"
},
new SuperCompany(){
SuperCompanyID=7,
SuperCompanyName="SC 7"
},
new SuperCompany(){
SuperCompanyID=8,
SuperCompanyName="SC 8"
},
new SuperCompany(){
SuperCompanyID=9,
SuperCompanyName="SC 9"
},
new SuperCompany(){
SuperCompanyID=10,
SuperCompanyName="SC 10"
}
}).Select(y => new SelectListItem { Value = y.SuperCompanyID.ToString(), Text = y.SuperCompanyName }).ToList(),
SearchOptionsList = (new List<SearchOption>(){
new SearchOption(){
SearchOptionID=11,
SearchOptionName="SO 11"
},
new SearchOption(){
SearchOptionID=12,
SearchOptionName="SO 12"
},
new SearchOption(){
SearchOptionID=13,
SearchOptionName="SO 13"
},
new SearchOption(){
SearchOptionID=14,
SearchOptionName="SO 14"
},
new SearchOption(){
SearchOptionID=15,
SearchOptionName="SO 15"
}
}).Select(y => new SelectListItem { Value = y.SearchOptionID.ToString(), Text = y.SearchOptionName }).ToList()
};
return View(bVM);
}
[HttpPost]
public ActionResult Search(BaseViewModel bVM)
{
SearchResultsViewModel sRVM = new SearchResultsViewModel();
sRVM.ResultsList = new List<SearchResult>(){
new SearchResult()
{
CompanyName = bVM.SelectedSuperCompanyID.ToString(),
SubCompanyName = bVM.SelectedManageCompanyID.ToString(),
UserName = "Duh"
}
};
return View("SearchResults", sRVM);
}
}
Views /Home/Home.cshtml
#{
ViewBag.Title = "Home";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div style="float: left; vertical-align: top;">
</div>
<br />
/Home/SearchResults.cshtml
#model XYZNameSpace.ViewModels.SearchResultsViewModel
<table width="100%">
<thead>
<tr>
<td>
COMPANY
</td>
<td>
SUB COMPANY
</td>
<td>
USER NAME
</td>
</tr>
</thead>
<tbody>
#foreach (XYZNameSpace.Models.SearchResult sr in Model.ResultsList)
{
<tr>
<td>
#sr.CompanyName
</td>
<td>
#sr.SubCompanyName
</td>
<td>
#sr.UserName
</td>
</tr>
}
</tbody>
</table>
/Shared/SearchDDLPartialView.cshtml
#model XYZNameSpace.ViewModels.BaseViewModel
<div>
<div style="float: left">
<span class="Label">Search: </span>
#using (Html.BeginForm("Search", "Home", FormMethod.Post))
{
#Html.DropDownListFor(x => x.SelectedSuperCompanyID, Model.SuperCompanyList)
#Html.DropDownListFor(x => x.SelectedManageCompanyID, Model.ManageCompanyList)
#Html.DropDownListFor(x => x.SelectedSearchOptionID, Model.SearchOptionsList)
<input type="image" src="../../Content/images/search.gif" />
}
</div>
</div>
/Shared/_Layout.cshtml
#model XYZNameSpace.ViewModels.BaseViewModel
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/BEClientProfile.css")" rel="Stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
</head>
<body>
<table>
<tr>
<td>
<img src="../../Content/images/logo124.gif" alt="Logo" />
</td>
<td valign="top">
<div style="float: left; vertical-align: top; text-align: left">
<img src="../../Content/images/user-info.gif" alt="User Infor" />
<span class="Label">Welcome </span><span class="HeaderLabelText">#Model.UserLevel</span>
</div>
<div>
<div style="float: left; width: 100%;">
<u><span class="Label">Currently Editing:</span> </u>
</div>
<div style="float: left; width: 100%;">
<span class="Label">Company:</span> <span class="HeaderLabelText">#Model.SelectedManageCompanyID</span>
</div>
<div style="float: left; width: 100%;">
<span class="Label">User:</span> <span class="HeaderLabelText">#Model.UserLoginName</span>
</div>
</div>
</td>
<td>
</td>
<td>
#{Html.RenderPartial("SearchDDLPartialViews", Model);}
</td>
</tr>
<tr>
<td colspan="4">
#RenderBody()
</td>
</tr>
</table>
</body>
</html>
/Shared/UserPartialView.cshtml
#model XYZNameSpace.Models.User
<div style="float: left; margin-left: .5em;">
<img src="../../Content/images/user-info.gif" alt="User Infor" />
<span style="font-weight: bold; float: left;">Welcome </span>
</div>
OK, i was able to select one item from each dropdown but when i click on image button at search Action in home control, the BaseViewModel has nothing other than selectedIDs, so when action is trying to display SearchResults view back, them _Layout.cshtml throughs error saying there nothing in lists that are used by dropdowns.
so how do we persist this information for every request...?

Quick solution is store the List < SelectListItem > or the viewmodel itself in session and reintroduce them to the view every time you return the viewmodel. However for cloud based solutions, same concept, but you'll need to use other caching storage such as appfabric, memcache or other addons allowed by your PaaS.

Related

.Net MVC ModelState.IsValid always returns true

ModelState.IsValid is always returning true.
Code:
user.cs
public class User
{
public int UserID { get; set; }
public string Username { get; set; }
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
}
HomeController.cs
public ActionResult SaveUser(User user)
{
if (ModelState.IsValid)
{
//create DBContext object
using (var dbCtx = new UsersDbEntities())
{
dbCtx.Entry(user).State = EntityState.Modified;
dbCtx.SaveChanges();
}
return View("ShowUser", user);
}
return View("EditUser", user);
}
Register.cshtml
#model TrainingWebsite.Models.User
<div id="myForm">
#using (Html.BeginForm("RegisterUser", "Home", FormMethod.Post))
{
if (#ViewBag.Message != null)
{
<div style="border: 1px solid red">
#ViewBag.Message
</div>
}
<table>
<tr>
<td>#Html.LabelFor(a => a.Username)</td>
<td>#Html.TextBoxFor(a => a.Username, new { id = "id_username" })</td>
<td>#Html.ValidationMessageFor(a => a.Username)</td>
</tr>
<tr>
<td>#Html.LabelFor(a => a.FirstName)</td>
<td>#Html.TextBoxFor(a => a.FirstName, new { id = "id_firstName" })</td>
<td>#Html.ValidationMessageFor(a => a.FirstName)</td>
</tr>
<tr>
<td>#Html.LabelFor(a => a.LastName)</td>
<td>#Html.TextBoxFor(a => a.LastName, new { id = "id_lastName" })</td>
<td>#Html.ValidationMessageFor(a => a.LastName)</td>
</tr>
</table>
ModelState.IsValid is true even though Last Name field is empty yet is a required field
Any help would be appreciated. Thanks in advance
David

Postback occurs when client side validation is enabled MVC3

I have client side validation enabled and indeed it is working in that I see error message for required fields when I submit the form. But a postback is also occuring despite the fact that client side validation has fired. It is my understanding that client side validation is supposed to suppress the postback. Can someone confirm for me that is the expected behaviour and see if there is anything amiss with this view. Many thanks.
This is the view in question
#model Intranet.ViewModels.Student.CreateStudentViewModel
#{
ViewBag.Title = "Create Student";
}
<h2>
Create Student</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<table class="detailViewTable">
<tr>
<td>#Html.LabelFor(c=>c.Contact.Title)</td>
<td>#Html.EditorFor(c=>c.Contact.Title)</td>
<td>#Html.ValidationMessageFor(c=>c.Contact.Title)</td>
</tr>
<tr>
<td>#Html.LabelFor(c=>c.Contact.FirstName)</td>
<td>#Html.EditorFor(c=>c.Contact.FirstName)</td>
<td>#Html.ValidationMessageFor(c=>c.Contact.FirstName)</td>
</tr>
<tr>
<td>#Html.LabelFor(c=>c.Contact.LastName)</td>
<td>#Html.EditorFor(c=>c.Contact.LastName)</td>
<td>#Html.ValidationMessageFor(c=>c.Contact.LastName)</td>
</tr>
<tr>
<td>#Html.LabelFor(c=>c.Contact.Phone)</td>
<td>#Html.EditorFor(c=>c.Contact.Phone)</td>
<td>#Html.ValidationMessageFor(c=>c.Contact.Phone)</td>
</tr>
<tr>
<td>#Html.LabelFor(c=>c.Contact.AltPhone)</td>
<td>#Html.EditorFor(c=>c.Contact.AltPhone)</td>
<td>#Html.ValidationMessageFor(c=>c.Contact.AltPhone)</td>
</tr>
<tr>
<td>#Html.LabelFor(c=>c.Contact.Email)</td>
<td>#Html.EditorFor(c=>c.Contact.Email)</td>
<td>#Html.ValidationMessageFor(c=>c.Contact.Email)</td>
</tr>
<tr>
<td>Guardian 1</td>
<td>#Html.DropDownListFor(c=>c.Guardian1ID, new SelectList(Model.Contacts, "ID", "FullName"))</td>
</tr>
<tr>
<td>Guardian 2</td>
<td>#Html.DropDownListFor(c=>c.Guardian2ID, new SelectList(Model.Contacts, "ID", "FullName"))</td>
</tr>
</table>
<p>
<input type="submit" value="Create" />
</p>
}
<div>
#Html.ActionLink("Back to List", "List")
</div>
And here is the CreateStudentViewModel
public class CreateStudentViewModel
{
public int ID { get; set; }
public ContactViewModel Contact { get; set; }
public int Guardian1ID { get; set; }
public int Guardian2ID { get; set; }
public List<ContactViewModel> Contacts { get; set; }
}
And the ContactViewModel that contains the validation properties.
public class ContactViewModel
{
public int ID { get; set; }
[Required(ErrorMessage = "Title is required")]
public string Title { get; set; }
[Required(ErrorMessage = "First Name is required")]
[DisplayName("First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name is required")]
[DisplayName("Last Name")]
public string LastName { get; set; }
public string Phone { get; set; }
[DisplayName("Alternate Phone")]
public string AltPhone { get; set; }
public string Email { get; set; }
public string FullName
{
get { return string.Format("{0} {1} {2}", Title, FirstName, LastName); }
}

Posted ViewModel return null properties

I am having issues with a view model that constantly return null properties after a post. Below is my code (it could be a syntax issue or two calling a class or property the same name as i saw in other posts but i could not see any such issue in code):
VIEW MODEL:
public class ProductItem
{
public int ProductID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string LongDescription { get; set; }
public int SupplierID { get; set; }
public string Dimensions { get; set; }
public double Price { get; set; }
public bool On_Sale { get; set; }
public double DiscountedPrice { get; set; }
public string Thumbnail { get; set; }
public string LargeImage { get; set; }
public string LargeImage2 { get; set; }
public string LargeImage3 { get; set; }
public string CrossRef { get; set; }
public byte Available { get; set; }
public double Weight { get; set; }
public byte Important { get; set; }
public virtual ICollection<ProductCategory> ProductCategories { get; set; }
// this is required on the page to allow products to be marked for deletion
public bool IsForDelete { get; set; }
}
public class ProductListViewModel
{
public IEnumerable<ProductItem> ProductItems { get; set; }
public IEnumerable<Category> CategoryItems { get; set; }
}
CONTROLLER:
public ActionResult ProductList()
{
var productList = new ProductListViewModel();
productList.ProductItems = productRepository.GetProductsWithDeleteOption().ToList();
productList.CategoryItems = categoryRepository.GetCategories().ToList();
return View(productList);
}
[HttpPost]
public ActionResult ProductList(ProductListViewModel productViewModel, FormCollection formCollection, string submit)
{
if (ModelState.IsValid)
{
// Check for submit action
if (submit == "Change Sort")
{
if (formCollection["Sortby"] == "ProductID")
{
OrderBy(productViewModel, formCollection, "m.ProductID");
}
else if (formCollection["Sortby"] == "Code")
{
OrderBy(productViewModel, formCollection, "m.Code");
}
else if (formCollection["Sortby"] == "Name")
{
OrderBy(productViewModel, formCollection, "m.Name");
}
else if (formCollection["Sortby"] == "Price")
{
OrderBy(productViewModel, formCollection, "m.Price");
}
}
else if (submit == "Delete all selected")
{
}
else if (submit == "Update All")
{
}
else if (submit == "Restrict Display")
{
}
}
return View(productViewModel);
}
VIEW:
#model Admin.Models.ViewModels.ProductListViewModel
#{
ViewBag.Title = "View Products";
}
#using (Html.BeginForm())
{
<h2>Product List as at #DateTime.Now.ToString("dd/MM/yyyy")</h2>
<table>
<tr>
<td>Sort by:</td>
<td>
<select name="Sortby">
<option value="ProductID">ProductID</option>
<option value="Code">Code</option>
<option value="Name">Name</option>
<option value="Price">Price</option>
</select>
</td>
<td>
<input type="radio" name="sortDirection" checked="checked" value="Asc" /> Ascending
<input type="radio" name="sortDirection" value="Desc" /> Descending
</td>
<td>
<input type="submit" name="submit" value="Change Sort" />
</td>
</tr>
<tr>
<td>Display only : (category)</td>
<td>#Html.DropDownList("CategoryID", new SelectList(Model.CategoryItems, "CategoryID", "Name"), "All Categories")</td>
<td colspan="2"><input type="submit" name="submit" value="Restrict Display" /></td>
</tr>
<tr>
<td colspan="4"><br />Total Number of products: #Model.ProductItems.Count()</td>
</tr>
</table>
<table>
<tr>
<th>
Edit
</th>
<th>
Code
</th>
<th>
Name
</th>
<th>
Price
</th>
<th>
On_Sale
</th>
<th>
DiscountedPrice
</th>
<th>
Weight
</th>
<th>
Delete
</th>
<th></th>
</tr>
#for (var i = 0; i < Model.ProductItems.ToList().Count; i++)
{
<tr>
<td>
#Html.HiddenFor(m => m.ProductItems.ToList()[i].ProductID)
#Html.ActionLink(Model.ProductItems.ToList()[i].ProductID.ToString(), "ProductEdit", new { id = Model.ProductItems.ToList()[i].ProductID })
</td>
<td>
#Html.DisplayFor(m => m.ProductItems.ToList()[i].Code)
</td>
<td>
#Html.DisplayFor(m => m.ProductItems.ToList()[i].Name)
</td>
<td>
#Html.EditorFor(m => m.ProductItems.ToList()[i].Price)
</td>
<td>
#Html.CheckBoxFor(m => m.ProductItems.ToList()[i].On_Sale, new { id = "On_Sale_" + Model.ProductItems.ToList()[i].ProductID })
</td>
<td>
#Html.EditorFor(m => m.ProductItems.ToList()[i].DiscountedPrice)
</td>
<td>
#Html.EditorFor(m => m.ProductItems.ToList()[i].Weight)
</td>
<td>
#Html.CheckBoxFor(m => m.ProductItems.ToList()[i].IsForDelete, new { id = Model.ProductItems.ToList()[i].ProductID })
</td>
<td>
#Html.ActionLink("Edit", "ProductEdit", new { id = Model.ProductItems.ToList()[i].ProductID }) |
#Html.ActionLink("Details", "Details", new { id = Model.ProductItems.ToList()[i].ProductID }) |
#Html.ActionLink("Delete", "Delete", new { id = Model.ProductItems.ToList()[i].ProductID })
</td>
</tr>
}
</table>
<p>
<input name="submit" type="submit" value="Delete all selected" />
</p>
<p>
<input name="submit" type="submit" value="Update All" />
</p>
<p>
#Html.ActionLink("Add a new product", "ProductAdd")
</p>
}
In the post action, the productViewModel argument has the ProductItems and CategoryItems properties as null.
Ok, so there are two problems.
I don't understand why you want to post list of the CategoryItems You should only expect the selected category and not the list
The problem with ProductItems is the name generated for <input> tags. Currently, the name being generated is name="[0].Price" whereas it should have been name="ProductItems[0].Price"
I changed the following code
#Html.EditorFor(m => m.ProductItems.ToList()[i].Price)
to
#Html.EditorFor(m => m.ProductItems[i].Price)
and it worked.
Note: I changed IEnumerable<ProductItem> ProductItems to List<ProductItem> ProductItems in ProductListViewModel
Yes it will be null on post back. I have a similar table in one of my projects and this is what I would have done given my situation.
You could change your view model to look like this then you don't have to do so many converting to lists in your view:
public class ProductListViewModel
{
public List<ProductItem> ProductItems { get; set; }
public List<Category> CategoryItems { get; set; }
}
Now in you view it could look something like this (this is just part of it, then rest you can just go and add):
#for (int i = 0; i < Model.ProductItems.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(m => m.ProductItems[i].Name)
#Html.HiddenFor(m => m.ProductItems[i].Name)
</td>
</tr>
<tr>
<td>
#Html.CheckBoxFor(m => m.ProductItems[i].IsForDelete)
</td>
</tr>
}
Add the code and do some debugging to see how the values are returned on submit
I hope this helps.

Using Ajax gives stale results

EDIT
My Ajax form gets correct Id to update a content and a replace option.
Submitting is by clicking <input type="submit" value="submit!" />.
Problem: When I clicked on submit I didn't see any update. Second trial gave the expected result. When I refreshed the page the lost record (first hit was successful) was on spot.
Model
[Serializable]
public abstract class AbstractEntity {
public Guid Id { get; set; }
public DateTime LastModified { get; set; }
}
[Serializable]
public class Product : AbstractEntity {
public Product() {
this.Attachments = new HashSet<Attachment>();
}
public String Title { get; set; }
public String Commentary { get; set; }
public DateTime PlacedOn { get; set; }
public String User { get; set; }
public ICollection<Attachment> Attachments { get; set; }
}
[Serializable]
public class Attachment {
public String MimeType { get; set; }
public String Description { get; set; }
public String Filename { get; set; }
}
Controller
[HandleError]
public class ProductController : Controller {
private readonly IDocumentSession documentSession;
public ProductController(IDocumentSession documentSession) {
this.documentSession = documentSession;
}
public ActionResult ListRecent() {
return View(ListAll());
}
[Audit, HttpPost]
public ActionResult Delete(Guid id) {
documentSession.Delete<Product>(documentSession.Load<Product>(id));
documentSession.SaveChanges();
return PartialView("ProductsList", ListAll());
}
[Audit, HttpPost]
public ActionResult Create(Product product) {
if(ModelState.IsValid) {
documentSession.Store(product);
documentSession.SaveChanges();
}
return PartialView("ProductsList", ListAll());
}
private IEnumerable<Product> ListAll() {
return documentSession.Query<Product>().ToArray();
}
}
Views ('scriptless')
Layout
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/stylesheets/normalize.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/stylesheets/site.core.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.7.2.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
</head>
<body>
<div id="main-wrapper">
<div id="header">[#Html.ActionLink("List", "ListRecent", "Product")]</div>
<div id="content">#RenderBody()</div>
</div>
</body>
ListRecent.cshtml
#model IEnumerable<lamp.DomainLayer.Entities.Product>
#{
ViewBag.Title = "ListRecent";
var options = new AjaxOptions {
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "productsList"
};
}
<h2>List</h2>
#Html.Partial("ProductsList", Model)
#using(Ajax.BeginForm("Create", "Product", options)) {
<fieldset>
<p>
<label class="autoWidth">Title</label>
#Html.Editor("Title")
#Html.ValidationMessage("Title")
</p>
<p>
<label class="autoWidth">Commentary</label>
#Html.TextArea("Commentary")
#Html.ValidationMessage("Commentary")
</p>
#* Some fields I have omitted.. *#
<input type="submit" value="submit" />
<input type="reset" value="clear" />
</fieldset>
}
ProductsList.cshtml
#model IEnumerable<lamp.DomainLayer.Entities.Product>
#{
var options = new AjaxOptions {
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "productsList"
};
}
<div id="productsList">
#foreach(var p in Model) {
<div class="productCard">
<p class="title"><strong>Title</strong>: #p.Title</p>
<p class="author"><strong>User</strong>: #p.User</p>
<p class="date"><strong>Placed on</strong>: #idea.PlacedOn.ToShortDateString()</p>
<p class="link">#Html.ActionLink("details", "Details", "Product")</p>
<p class="link">
#using(Ajax.BeginForm("Delete", "Product", new { id = p.Id }, options)) {
<input type="submit" value="you!" />
}
</p>
</div>
}
</div>
I guess it is IE's fault (precisely the way,how IE cache AJAX requests). Look here-it could be solution:
http://viralpatel.net/blogs/ajax-cache-problem-in-ie/
Ok. Darin was right! I found out that changing my controller code to this one:
private IEnumerable<Product> ListAll() {
return documentSession
.Query<Product>()
.Customize((x => x.WaitForNonStaleResults()))
.ToArray();
}
fixes everything.
.Customize((x => x.WaitForNonStaleResults()))
is the solution!
Thanks everyone!

Date validation on search input/textbox for a razor view MVC

I would like to add a textbox (date) and button to my report, which filters the data.
The below mvc is working, but the input must still be validated (must be a DATE) on client side (and server side if possible)
My Model looks like this :
public class DailyReport
{
public int DailyReportID { get; set; }
public DateTime? ReportDate { get; set; }
}
View :
#model IEnumerable<project_name.Models.DailyReport>
#* text box and button: *#
#using (Html.BeginForm("Index", "DailyReport", FormMethod.Get))
{ <p>
Title: #Html.TextBox("SearchDateString")
<input type="submit" value="Filter" />
</p>
}
#* display dates*#
#foreach (var item in Model)
{ #Html.DisplayFor(modelItem => item.ReportDate)
}
my controller:
public ViewResult Index(String SearchDateString)
{
var dailyreport = db.DailyReport.Include(d => d.Site);
if (!String.IsNullOrEmpty(SearchDateString))
{
DateTime search_date = Convert.ToDateTime(SearchDateString);
dailyreport = dailyreport.Where(r => r.ReportDate == search_date);
}
return View(dailyreport.ToList());
}
Can someone help me please?
How do I make sure a valid date is entered in the textbox?
Should I create a another model with a date field for this input?
Utilize the DataTypeAttribute from the DataAnnotations namespace in your Model, like so:
public class DailyReport
{
public int DailyReportID { get; set; }
public DateTime? ReportDate { get; set; }
}
public class DrViewModel
{
[DataType(DataType.Date)]
public string DateTimeSearch { get; set; }
List<DailyReport> DailyReports { get; set; }
}
In your View, have something like:
#model project_name.Models.DrViewModel
#using (Html.BeginForm("Index", "DailyReport", FormMethod.Get))
{
<p>
Title: #Html.TextBoxFor(m => m.DateTimeSearch)
<input type="submit" value="Filter" />
</p>
}
#foreach (var item in Model.DailyReports)
{
#Html.DisplayFor(m => item.ReportDate)
}
#Shark Shark pointed me in the right direction to use a viewmodel, this is the end result that is now working. JS validation added as well.
(DBSet was not necessary because DrViewModel is a viewmodel.)
controllers :
public ActionResult Index(DrViewModel dvm)
{
var dailyreport = db.DailyReport.Include(d => d.Site);
if (dvm.DateTimeSearch != null)
{
dailyreport = dailyreport.Where(r => r.ReportDate == dvm.DateTimeSearch);
}
dvm.DailyReport = dailyreport.ToList();
return View(dvm);
}
models :
public class DrViewModel
{
public DateTime? DateTimeSearch { get; set; }
public List<DailyReport> DailyReport { get; set; }
}
public class DailyReport
{
public int DailyReportID { get; set; }
public DateTime? ReportDate { get; set; }
}
view :
#model myproject.Models.DrViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm("Index","DailyReport", FormMethod.Get ))
{
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.LabelFor(model => model.DateTimeSearch)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DateTimeSearch)
#Html.ValidationMessageFor(model => model.DateTimeSearch)
<input type="submit" value="Filter" />
</div>
}
#foreach (var item in Model.DailyReport)
{
#Html.DisplayFor(modelItem => item.ReportDate)
}

Resources