#html.TextBox() is not passing in the controller in actionlink - razor

I`m trying to pass value in a controller from a text box. i google this problem. but not get any suitable solution which works for me.
below is my controller.
WebProductController
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DatabaseService_WebAPI.Models;
namespace DatabaseService_WebAPI.Controllers
{
public class WebProductController : Controller
{
private ProductContext db = new ProductContext();
private LocalDBContext ldb = new LocalDBContext();
private ProductTypeContext pdb = new ProductTypeContext();
//
// GET: /WebProduct/
public ActionResult Index()
{
var temp = from tpro in db.Products
where tpro.User==User.Identity.Name
select tpro;
return View(temp.ToList());
}
public ActionResult TypeT()
{
var temp = from ttpro in pdb.ProductTypes
where ttpro.Type == "Tablet"
select ttpro;
return View(temp.ToList());
}
public ActionResult TypeC()
{
var temp = from ctpro in pdb.ProductTypes
where ctpro.Type == "Capsule"
select ctpro;
return View(temp.ToList());
}
public ActionResult TypeS()
{
var temp = from stpro in pdb.ProductTypes
where stpro.Type == "Syrup"
select stpro;
return View(temp.ToList());
}
//
// GET: /WebProduct/Details/5
public ActionResult Details(int id = 0)
{
Product product = db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
return View(product);
}
//
// GET: /WebProduct/Create
public ActionResult Create()
{
return View();
}
//
// POST: /WebProduct/Create
[HttpPost]
public ActionResult Create(Product product)
{
if (ModelState.IsValid)
{
LocalDB tobj = ldb.LocalDBs.Single(s => s.User == User.Identity.Name);
product.city = tobj.City;
product.OrderDate = DateTime.Now.Date.ToShortDateString();
product.ShopName = tobj.ShopName;
product.User = tobj.User;
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("Index", "WebProduct");
}
return View(product);
}
[HttpPost]
public ActionResult Add(ProductType type, string quantity)
{
Product product = new Product();
if (type.Type=="Tablet")
{
//string order = type.Name + " " + type.Quantity;
LocalDB tobj = ldb.LocalDBs.Single(s => s.User == User.Identity.Name);
product.city = tobj.City;
product.OrderDate = DateTime.Now.Date.ToShortDateString();
product.ShopName = tobj.ShopName;
product.User = tobj.User;
//product.OrderDetail = order;
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("TypeT", "WebProduct");
}
else if (type.Type == "Syrup")
{
//string order = type.Name + " " + type.Quantity;
LocalDB tobj = ldb.LocalDBs.Single(s => s.User == User.Identity.Name);
product.city = tobj.City;
product.OrderDate = DateTime.Now.Date.ToShortDateString();
product.ShopName = tobj.ShopName;
product.User = tobj.User;
// product.OrderDetail = order;
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("TypeS", "WebProduct");
}
else
{
// string order = type.Name + " " + type.Quantity;
LocalDB tobj = ldb.LocalDBs.Single(s => s.User == User.Identity.Name);
product.city = tobj.City;
product.OrderDate = DateTime.Now.Date.ToShortDateString();
product.ShopName = tobj.ShopName;
product.User = tobj.User;
// product.OrderDetail = order;
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("TypeC", "WebProduct");
}
return View();
}
//
// GET: /WebProduct/Edit/5
public ActionResult Edit(int id = 0)
{
Product product = db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
return View(product);
}
//
// POST: /WebProduct/Edit/5
[HttpPost]
public ActionResult Edit(Product product)
{
if (ModelState.IsValid)
{
db.Entry(product).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index", "WebProduct");
}
return View(product);
}
//
// GET: /WebProduct/Delete/5
public ActionResult Delete(int id = 0)
{
Product product = db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
return View(product);
}
//
// POST: /WebProduct/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Product product = db.Products.Find(id);
db.Products.Remove(product);
db.SaveChanges();
return RedirectToAction("Index", "WebProduct");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
TypeT.cshtml
#model IEnumerable<DatabaseService_WebAPI.Models.ProductType>
#{
ViewBag.Title = "Tablets";
<script type="text/javascript">
$(function () {
$('#edit').click(function() {
var name = $('#quantity').val();
this.href = this.href + '/' + encodeURIComponent(name);
});
});
</script>
}
<h2>Tablets</h2>
#*#using (Html.BeginForm("Add", "WebProductController",FormMethod.Post)) {
#Html.ValidationSummary(true)
*#
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Price)
</th>
<th>
#Html.DisplayNameFor(model => model.Batch)
</th>
<th>
#Html.DisplayNameFor(model => model.Expiry)
</th>
<th>
#Html.DisplayNameFor(model => model.Quantity)
</th>
#* <th>
#Html.DisplayNameFor(model => model.Type)
</th>*#
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.DisplayFor(modelItem => item.Batch)
</td>
<td>
#Html.DisplayFor(modelItem => item.Expiry)
</td>
<td>
#Html.TextBox("quantity")
</td>
#Html.Hidden("idText", item.Id)
<td>
#Html.ActionLink("Add", "Add", new { id = item.Id, name=item.Name, type=item.Type }, null)
#*#Html.ActionLink("Add", "Add", null, new { id = "edit" })*#
#*<input type="submit" value="Add" />*#
</td>
</tr>
}
</table>
#*}*#
<div>
#Html.ActionLink("Back to List", "Create")
</div>
In my controller i`m calling Add() method. in action result it is passing values in the controller but not passing the textbox value. when i try to use
#using (Html.BeginForm("Add", "WebProductController",FormMethod.Post))
Then the form doesnt recognize my method when i use button to sending data in my form.
im stuck in this problem. but no solution:(

Your Controller should look like:
public ActionResult Add(IList<ShoppingItemModel> items){
foreach(ShopingItemModel item in items){
if (item.Id != null){
ShopingItem shopingItem = service.GetById(item.Id);
... Add Item to whatever
}
}
}
Your ShoppingItemModel:
public class ShoppingItemModel{
[Required]
public Id{get;set;}
[Required]
public Amount{get;set;}
...
}
Your View (I Skipped Java Script):
#model IList<ShoppingItemModel>
<h2>Tablets</h2>
#using (Html.BeginForm("Add", "WebProductController",FormMethod.Post)) {
#Html.ValidationSummary(true)
<table>
<tr>
<th>
Name
</th>
<th>
Price
</th>
...
<th>Amount</th>
</tr>
#for(int index; index < Model.Count; index++) {
<tr>
<td>
#Html.HiddenFor(model => model[index].Id)
#Html.DisplayFor(model => model[index].Name)
</td>
<td>
#Html.DisplayFor(model => model[index].Price)
</td>
<td>
#Html.DisplayFor(model => model[index].Batch)
</td>
...
<td>
#Html.TextBoxFor(model => model[index].Quantity)
</td>
</tr>
}
</table>
<input type="submit" value="Add" />
}
That is not the complete solution. Just a hint.
Tobi

Related

PaginatedList onpostasync - ArgumentNullException: Value cannot be null. (Parameter 'model') when submitting on paginnatelist

HI Perhaps someone can point me in the right direction.
I created a paginated list page use the example on the ms site.
https://learn.microsoft.com/en-us/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-5.0
and modified it slightly. I replaced one item with a input box as would like to edit the list and do a bulk save instead on opening every item on a new page to edit it.
but when it click the submit button i get the error.
ArgumentNullException: Value cannot be null. (Parameter 'model')
Microsoft.AspNetCore.Mvc.RazorPages.PageModel.TryValidateModel(object model, string name)
if I bind the property
[BindProperty(SupportsGet = true)]
public PaginatedList<CompanyDataListing> CustomersDisplayList { get; set; }
i get the follow error
ArgumentException: Type 'BizFinder.PaginatedList`1[BizFinder.Data.CompanyDataListing]' does not have a default constructor (Parameter 'type')
and even the paginated list does not render.
My code for the sumbit is as follows.
public PaginatedList<CompanyDataListing> CustomersDisplayList { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!TryValidateModel(CustomersDisplayList, nameof(CustomersDisplayList)))
{
return Page();
}
foreach (var item in CustomersDisplayList)
{
if (item.GoogleCategory != "")
{
string cat = item.GoogleCategory;
}
}
return Page();
}
and my html is as follow.
#using (Html.BeginForm(FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<table class="table">
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="#Model.NameSort"
asp-route-currentFilter="#Model.CurrentFilter">
#Html.DisplayNameFor(model => model.CustomersDisplayList[0].CompanyName)
</a>
</th>
<th>
#Html.DisplayNameFor(model => model.CustomersDisplayList[0].Keywords)
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="#Model.DateSort"
asp-route-currentFilter="#Model.CurrentFilter">
#Html.DisplayNameFor(model => model.CustomersDisplayList[0].GoogleCategory)
</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.CustomersDisplayList)
{
<tr>
<td>
<input type="hidden" asp-for="CustomersDisplayList[0].Id" />
#Html.DisplayFor(modelItem => item.CompanyName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Keywords)
</td>
<td>
#*#Html.DisplayFor(modelItem => item.GoogleCategory)*#
<input asp-for="CustomersDisplayList[0].GoogleCategory" name="Category1" placeholder="Input your keyword" class="form-control GoogleCategory" autofocus="autofocus" />
<span asp-validation-for="CustomersDisplayList[0].GoogleCategory" class="text-danger"></span>
</td>
<td>
<a asp-page="./Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="#item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
<div asp-validation-summary="All">
<span>Please correct the following errors</span>
</div>
#* #Html.ValidationSummary(true, "", new { #class = "text-danger" })*#
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</div>
}
and the full code base is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BizFinder.Data;
using BizFinder.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
//https://learn.microsoft.com/en-us/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-5.0
namespace BizFinder.Pages.Admin
{
public class ManCatergoryModel : PageModel
{
private readonly ApplicationDbContext _context;
private readonly IConfiguration Configuration;
private readonly IAuthorizationService _authorizationService;
public int PageSize { get; set; } = 10;
// private readonly SchoolContext _context;
public ManCatergoryModel(ApplicationDbContext context, IConfiguration configuration)
{
_context = context;
Configuration = configuration;
}
public string NameSort { get; set; }
public string DateSort { get; set; }
public string CurrentFilter { get; set; }
public string CurrentSort { get; set; }
// public IList<CompanyDataListing> CustomersDisplayList { get; set; }
// [BindProperty(SupportsGet = true)]
public PaginatedList<CompanyDataListing> CustomersDisplayList { get; set; }
public async Task OnGetAsync(string sortOrder,
string currentFilter, string searchString, int? pageIndex)
{
CurrentSort = sortOrder;
NameSort = String.IsNullOrEmpty(sortOrder) ? "CompanyName" : "";
DateSort = sortOrder == "Keywords" ? "date_desc" : "Date";
if (searchString != null)
{
pageIndex = 1;
}
else
{
searchString = currentFilter;
}
CurrentFilter = searchString;
// using System;
IQueryable<CompanyDataListing> CompData = from s in _context.CompanyDataList
where s.GoogleCategory == null
select s;
switch (sortOrder)
{
case "name_desc":
CompData = CompData.OrderByDescending(s => s.CompanyName);
break;
case "Date":
CompData = CompData.OrderBy(s => s.Keywords);
break;
case "GoogleCategory":
CompData = CompData.OrderByDescending(s => s.GoogleCategory);
break;
default:
CompData = CompData.OrderBy(s => s.CompanyName);
break;
}
// var pageSize = Configuration.GetValue("PageSize", 4);
CustomersDisplayList = await PaginatedList<CompanyDataListing>.CreateAsync(
CompData.AsNoTracking(), pageIndex ?? 1, PageSize);
}
public async Task<IActionResult> OnPostAsync(PaginatedList<CompanyDataListing> Datalist)
{
// List < CompanyDataListing > mm = CustomersDisplayList.ToList();
foreach (var item in Datalist)
{
string str = item.GoogleCategory;
}
return Page();
}
}
}
The first thing you need to know is that the pagination in the tutorial is the back-end pagination. When you click the next page, the data is re-requested every time, so if you want to submit in batches, you can only submit current page data.
If you want the data of the current page to be submitted in batches, then you can modify your code as follows.
PageModel:
public class IndexModel : PageModel
{
private readonly PageListRazorContext _context;
private readonly IConfiguration Configuration;
public IndexModel(PageListRazorContext context, IConfiguration configuration)
{
_context = context;
Configuration = configuration;
}
public string NameSort { get; set; }
public string KeywordsSort { get; set; }
public string CurrentSort { get; set; }
public PaginatedList<CompanyDataListing> CompanyDataListing { get;set; }
public async Task OnGetAsync(string sortOrder,int? pageIndex)
{
NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
KeywordsSort = sortOrder == "Keywords" ? "keywords_desc" : "Keywords";
IQueryable<CompanyDataListing> company = from s in _context.CompanyDataListing
select s;
switch (sortOrder)
{
case "name_desc":
company = company.OrderByDescending(s => s.CompanyName);
break;
case "Keywords":
company = company.OrderBy(s => s.Keywords);
break;
case "keywords_desc":
company = company.OrderByDescending(s => s.Keywords);
break;
default:
company = company.OrderBy(s => s.CompanyName);
break;
}
var pageSize = Configuration.GetValue("PageSize", 4);
CompanyDataListing = await PaginatedList<CompanyDataListing>.CreateAsync(
company.AsNoTracking(), pageIndex ?? 1, pageSize);
}
public IActionResult OnPost(List<CompanyDataListing> Datalist)
{
//....
return RedirectToPage("./Index");
}
}
Page:
<form method="post">
<table class="table">
<thead>
<tr>
<th>
<a asp-page="./Index" asp-route-sortOrder="#Model.NameSort">
#Html.DisplayNameFor(model => model.CompanyDataListing[0].CompanyName)
</a>
</th>
<th>
<a asp-page="./Index" asp-route-sortOrder="#Model.KeywordsSort">
#Html.DisplayNameFor(model => model.CompanyDataListing[0].Keywords)
</a>
</th>
<th>
#Html.DisplayNameFor(model => model.CompanyDataListing[0].GoogleCategory)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.CompanyDataListing)
{
<tr>
<td>
<input type="hidden" asp-for="#item.CompanyName" name="Datalist[#i].CompanyName" />
#Html.DisplayFor(modelItem => item.CompanyName)
</td>
<td>
<input type="hidden" asp-for="#item.Keywords" name="Datalist[#i].Keywords" />
#Html.DisplayFor(modelItem => item.Keywords)
</td>
<td>
<input asp-for="#item.GoogleCategory" name="Datalist[#i].GoogleCategory" placeholder="Input your keyword" class="form-control GoogleCategory" autofocus="autofocus" />
<span asp-validation-for="#item.GoogleCategory" class="text-danger"></span>
</td>
<td>
<a asp-page="./Edit" asp-route-id="#item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="#item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="#item.ID">Delete</a>
</td>
#{i++;}
</tr>
}
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</div>
#{
var prevDisabled = !Model.CompanyDataListing.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.CompanyDataListing.HasNextPage ? "disabled" : "";
}
<a asp-page="./Index"
asp-route-sortOrder="#Model.CurrentSort"
asp-route-pageIndex="#(Model.CompanyDataListing.PageIndex - 1)"
class="btn btn-primary #prevDisabled">
Previous
</a>
<a asp-page="./Index"
asp-route-sortOrder="#Model.CurrentSort"
asp-route-pageIndex="#(Model.CompanyDataListing.PageIndex + 1)"
class="btn btn-primary #nextDisabled">
Next
</a>
</form>
Test result:
You are referencing CustomerDisplayList in the OnPost handler but it has not been initialised, hence the exception. You initialised it in the OnGet handler, but that only executes for GET requests. If you want to use a POST request, you also need to initialise the CustomerDisplayList in that too.
For what it's worth, the example you linked to uses GET requests for the whole cycle. This usually makes more sense for things like paginating and filtering results. That way, the criteria are passed in the URL as query string values or route data, which means that you can bookmark filtered/paged results. You won't need to render the anti forgery token for GET requests.

Get value from selected option and pass it to the function

Hi im making a reservation page in razor pages asp.net. On my page I have two drop downlist. One for the location other for the rooms of that specific location. I want to pass the value of that selected location to the function which shows the rooms (function is named showRoom()), so that the rooms will be shown depending on which location you selected. How do i do that with html? I tried something but didnt really work. Here is the html code
<td>Select location</td>
<div class="form-group">
<select id="locations" name="Location">
#foreach(var reservations in #Model.PopulateReservations())
{
<option>#Html.DisplayFor(m => reservations.LocationName)</option>
}
</select>
</div>
<td>Select Room</td>
<div class="form-group">
<select id="rooms" name="Room">
#foreach(var reservations in #Model.ShowRoom(string LocationName))
{
<option>#Html.DisplayFor(m => reservations.RoomName)</option>
}
</select>
</div>
Here is the function showRoom
public List<WorkspaceModel> ShowRoom(string loc)
{
var cs = Database.Database.Connector();
List<WorkspaceModel> res = new List<WorkspaceModel>();
using var con = new NpgsqlConnection(cs);
{
string query = "Select room FROM workspaces WHERE location = '"+ loc +"'";
using NpgsqlCommand cmd = new NpgsqlCommand(query, con);
{
cmd.Connection = con;
con.Open();
using (NpgsqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
res.Add(new WorkspaceModel { RoomName = dr["room"].ToString() });
}
}
con.Close();
}
}
Here is a demo(I use fake data to test):
class:
public class PopulateReservation
{
public string LocationName { get; set; }
}
public class WorkspaceModel
{
public string RoomName { get; set; }
}
TestDropDown.cshtml:
<td>Select location</td>
<div class="form-group">
<select id="locations" name="Location">
#foreach (var reservations in #Model.PopulateReservations)
{
<option>#Html.DisplayFor(m => reservations.LocationName)</option>
}
</select>
</div>
<td>Select Room</td>
<div class="form-group">
<select id="rooms" name="Room">
#foreach (var reservations in #Model.Rooms)
{
<option>#Html.DisplayFor(m => reservations.RoomName)</option>
}
</select>
</div>
<form>
#Html.AntiForgeryToken()
</form>
#section scripts{
<script>
$('#locations').on('change', function () {
var arr = [];
$.ajax({
type: "POST",
url: '?handler=ShowRoom',
headers: {
RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val()
},
data: { "loc": $("#locations").val() },
dataType:"json"
}).done(function (data) {
$("#rooms").empty();
$.each(data, function (i, item) {
$("#rooms").append('<option> ' + item["roomName"] + ' </option>');
});
});
});
</script>
}
TestDropDown.cshtml.cs:
public class TestDropDownModel : PageModel
{
[BindProperty]
public List<PopulateReservation> PopulateReservations { get; set; }
[BindProperty]
public List<WorkspaceModel> Rooms { get; set; }
public IActionResult OnGet()
{
PopulateReservations = new List<PopulateReservation> {
new PopulateReservation { LocationName = "location1" },
new PopulateReservation { LocationName = "location2" },
new PopulateReservation { LocationName = "location3" }
};
Rooms = new List<WorkspaceModel> {
new WorkspaceModel { RoomName = "Room1" },
new WorkspaceModel { RoomName = "Room2" },
new WorkspaceModel { RoomName = "Room3" },
};
return Page();
}
public IActionResult OnPost()
{
return Page();
}
public IActionResult OnPostShowRoom(string loc)
{
List<WorkspaceModel> l= new List<WorkspaceModel> {
new WorkspaceModel { RoomName = loc + "Room1" },
new WorkspaceModel { RoomName = loc + "Room2" },
new WorkspaceModel { RoomName = loc + "Room3" },
};
return new JsonResult(l);
}
}
result:

Changing HTML with Java(Spring)

I am a newbie at Spring and I am writing a rental system for movies. I have a Controller where I can get a list of all movies which are still rented (marked by digit "1" as a status in my Database) and which are already have been returned(marked as "0").
Now currently, when I call the page I see all the rented movies with the current status "1" or "0" as well as already returned movies which can still be returned and have a checkbox (which shouldn't be possible.
My question is, how can I change the HTML in the following way:
The status "1" or "0" changes to "rented" and "returned"
I want to remove the checkbox on all movies which already have been returned.
My code:
#Controller
public class MovieController {
#Autowired
private MovieService movieService;
#GetMapping("/home")
public String home(Model model) {
return "index";
}
#GetMapping("/movieList")
public String listAllMovies(Model model) {
model.addAttribute("listMovies", movieService.findNotRented());
return "movies";
}
#GetMapping("/search")
public String findByOption(Model model, #RequestParam(value = "search") String search,
#RequestParam("options") String options) {
if (options.equals("movie")) {
model.addAttribute("listMovies", movieService.findByName(search));
} else if (options.equals("actor")) {
model.addAttribute("listMovies", movieService.findMovieByActor(search));
} else if (options.equals("genre")) {
model.addAttribute("listMovies", movieService.findMovieByGenre(search));
}
return "movies";
}
#GetMapping("/rentedList")
public String findRentedMovies(Model model) {
model.addAttribute("listMovies", movieService.findRentedMovies());
return "rented";
}
#GetMapping("/rentMovie")
public String rentMovie(Model model, #RequestParam int id) {
model.addAttribute("listMovies", movieService.rentMovie(id));
return "index";
}
#GetMapping("/deleteRentedMovie")
public String deleterentedMovie(Model model, #RequestParam int id) {
model.addAttribute("listMovies", movieService.deleteRentedMovie(id));
return "index";
}
#GetMapping("/rentMovie2")
public String rentMovie2(Model model, #RequestParam("idChecked") List<Integer> id) {
if (id != null) {
for (Integer idInt : id) {
model.addAttribute("listMovies", movieService.rentMovie(idInt));
}
}
return "index";
}
#GetMapping("/deleteRentedMovie2")
public String deleterentedMovie(Model model, #RequestParam("idChecked") List<Integer> id) {
if (id != null) {
for (Integer idInt : id) {
model.addAttribute("listMovies", movieService.deleteRentedMovie(idInt));
}
}
return "index";
}
}
Thymeleaf
<h1>Movie List</h1>
<form action="/deleteRentedMovie2">
<table>
<tr>
<th>Title</th>
<th>Time rented</th>
<th>Status</th>
<th>Select</th>
</tr>
<tr th:each="movie : ${listMovies}">
<td th:text="${movie.title}"></td>
<td th:text="${movie.date}"></td>
<td th:text="${movie.status}"></td>
<td><input type="checkbox" th:name="idChecked" th:value="${movie.id}"></td>
</tr>
</table>
<input type="submit" value="Return Movie">
</form>
Thank you in advance and sorry for my bad English
For the status I would something like:
<td>
<span th:if="${movie.status == 1}">rented</span>
<span th:if="${movie.status == 0}">returned</span>
</td>
You could also use the Elvis operator but it is maybe less readable.
For the checkbox:
<td><input th:unless="${movie.status == 0}" type="checkbox" th:name="idChecked" th:value="${movie.id}"></td>

Textbox rejecting ##,00 format

I have a MVC project where I am displaying currency amounts in different formats based on the currency of the object.
My project handles the ##.00 format just find, but I have some objects that are using Euros for example that need to be in the ##,00 format instead of ##.00.
Then the page loads in read only mode both formats display correctly, but then the form is edited, it initially shows the currencies correctly, but if I click out of a Euro formatted amount, it drops the "," out of the amount (for example 1000,00 changes to 100000).
In the model, the fields are of DataType = Currency and are decimals. Also, if 1000,00 is tried to save, it is returned as invalid.
How to I get the textbox to handle the both currency formats?
This is my code
#model Projections.Web.ViewModels.Projections.ProjectionFormView
#Html.HiddenFor(model => model.Number)
#Html.HiddenFor(model => model.Department)
#* -- Quarters -- *#
<div class="edit-fields">
<div class="control-group">
#Html.LabelFor(model => model.Q12017, new {#class = "control-label"})
<div class="controls">
#Html.EditorFor(model => model.Q12017)
</div>
</div>
<div class="control-group">
#Html.LabelFor(model => model.Q22017, new {#class = "control-label"})
<div class="controls">
#Html.EditorFor(model => model.Q22017)
</div>
</div>
<div class="control-group">
#Html.LabelFor(model => model.Q32017, new {#class = "control-label"})
<div class="controls">
#Html.EditorFor(model => model.Q32017)
</div>
</div>
<div class="control-group">
#Html.LabelFor(model => model.Q42017, new { #class = "control-label" })
<div class="controls">
#Html.EditorFor(model => model.Q42017)
</div>
</div>
<div class="control-group">
#Html.LabelFor(model => model.Q12018, new { #class = "control-label" })
<div class="controls">
#Html.EditorFor(model => model.Q12018)
</div>
</div>
</div>
Controller:
public ActionResult Edit(string number, string department)
{
// Get the project we're trying to edit a projection for.
var projects = _db.Projects.FindBy(
x => x.Number == number &&
x.PMUsername == SessionWrapper.CurrentManager,
null,
"Projection").ToList();
if (!projects.Any())
{
return Error(
Notices.ProjectNotFoundTitle,
string.Format(Notices.ProjectNotFound, number)
);
}
var project = projects.SingleOrDefault(x => x.Department == department);
var baseProject = projects.SingleOrDefault(x => x.Department == string.Empty);
// Project doesn't exist, error time!
if (project == null || baseProject == null)
{
return Error(
Notices.DepartmentNotFoundTitle,
string.Format(Notices.DepartmentNotFound, department, number)
);
}
project.Projection = project.Projection ?? new Projection { Number = number, Department = department, Project = project };
SetProjectCulture(project.ProjectCurrencyCode);
var projection = Mapper.Map<ProjectionFormView>(project.Projection);
projection.BaseProjectName = baseProject.Name;
return View(projection);
}
private void SetProjectCulture(string currencyCode)
{
var uiHelper = DependencyResolver.Current.GetService<IThreadUIHelper>();
if (!uiHelper.SetUICulture(currencyCode)) return;
var notice = new Notification(string.Format(Notices.ProjectCurrencyNotice, currencyCode));
NotificationHandler.AddNotification(notice);
}
Model
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace Projections.Web.ViewModels.Projections
{
public class Forecast : INotifyPropertyChanged
{
private decimal _q12017;
private decimal _q22017;
private decimal _q32017;
private decimal _q42017;
private decimal _q12018;
[DataType(DataType.Currency)]
public decimal Q12017
{
get { return _q12017; }
set { _q12017 = value; ForecastChanged("Q12017"); }
}
[DataType(DataType.Currency)]
public decimal Q22017
{
get { return _q22017; }
set { _q22017 = value; ForecastChanged("Q22017"); }
}
[DataType(DataType.Currency)]
public decimal Q32017
{
get { return _q32017; }
set { _q32017 = value; ForecastChanged("Q32017"); }
}
[DataType(DataType.Currency)]
public decimal Q42017
{
get { return _q42017; }
set { _q42017 = value; ForecastChanged("Q42017"); }
}
[DataType(DataType.Currency)]
public decimal Q12018
{
get { return _q12018; }
set { _q12018 = value; ForecastChanged("Q12018"); }
}
public decimal Total
{
get
{
var quarters = GetType().GetProperties().Where(x => x.Name.StartsWith("Q")).ToList();
return quarters.Sum(q => (decimal?)q.GetValue(this, null) ?? default(decimal));
}
}
public DateTime? Modified { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void ForecastChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public decimal? this[string name]
{
get
{
var property = GetType().GetProperty(name);
if (property == null) throw new InvalidOperationException("Invalid property specified.");
if (property.PropertyType == typeof(decimal))
{
return property.GetValue(this, null) as decimal?;
}
throw new InvalidOperationException("Invalid property specified.");
}
}
}
}
The default model binder will only handle decimals with a U.S.-style decimal point (.). If you need to accept a comma, you need a custom model binder. I use the following, which I found original here.
public class DecimalModelBinder : IModelBinder {
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
ValueProviderResult valueResult = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName);
ModelState modelState = new ModelState { Value = valueResult };
object actualValue = null;
try {
actualValue = Convert.ToDecimal(valueResult.AttemptedValue,
CultureInfo.CurrentCulture);
}
catch (FormatException e) {
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}
Then, register it in Application_Start in Global.asax:
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
You may need to alter the model binder to your specific usage scenario. This version simply converts based on the current culture, but you may need to do some different type of processing here if you're going to be handling both periods and commas as "decimal points".

Razor webgrid get selected row data

In my Razor view, I have this webgrid:
#{
var grid = new WebGrid(Model, canPage: false, selectionFieldName: "VendorClassID", canSort:false);
}
#grid.GetHtml(
headerStyle: "header",
htmlAttributes: new{id = "tableGrid"},
tableStyle: "webgrid",
selectedRowStyle: "webgrid-selected-row",
columns: grid.Columns(
grid.Column(header: "Select", format: #<text>#item.GetSelectLink("Select")</text>),
grid.Column("ClassID", "ID"),
grid.Column("ClassNum", "Class Num"),
grid.Column("Description")
)
)
#if (grid.HasSelection)
{
var x = #grid.SelectedRow;
}
It's my understanding that when I click the generated "select" link, the page posts back and the URL gets a parameter "VendorClassID = selectrowindex" added on. However, the value of the parameter seems to be the index of the selected row, which isn't particularly useful to me. Is there anyway to have the parameter value be set to a value from the selected row (ClassID, etc)? The #grid.SelectedRow doesn't seem to know anything about the row's data either, but I am new to MVC so perhaps there is a way to get the row data from there?
I found the solution, I got the data I wanted (VendorClassID), by using
#if (grid.HasSelection)
{
var x = grid.SelectedRow.Value.VendorClassID;
//logic
}
VendorClassID is an attribute of my VendorClass. The page has a list of VendorClasses for its Model
Model:
public class SchemeDetailsModel
{
[Display(Name = "File Name")]
public string FileName { get; set; }
public Int64 FileId { get; set; }
[DataType(DataType.Date)]
public DateTime Date { get; set; }
[Display(Name = "Scheme Id")]
public int SchemeId { get; set; }
public string Status { get; set; }
[Display(Name="Validation Error Report")]
public string ValidationErrorReport { get; set; }
}
Controller:
[HttpGet]
public ActionResult History()
{
if (ModelState.IsValid)
{
List<SchemeDetailsModel> objSchemeDetails = new List<SchemeDetailsModel>();
string employerId = Session["EmployerId"].ToString();
objSchemeDetails = _repository.getSchemeDetails(employerId);
return View(objSchemeDetails);
}
return View();
}
Repository:
public List<SchemeDetailsModel> getSchemeDetails(string employerId)
{
List<SchemeDetailsModel> objDetails = new List<SchemeDetailsModel>();
var query = (from efd in _context.EmployerFileDatas
//where efd.EmployerId == employerId
orderby efd.FileName
select new
{
efd.FileName,
efd.Timestamp,
//efhd.SchemeId,
efd.ValidationStatus
}).ToList();
//join efhd in _dataContext.EmployerFileHeaderDetails on efd.EmployerId equals efhd.EmployerId
if(query!=null)
{
foreach (var item in query)
{
objDetails.Add(new SchemeDetailsModel { FileName = item.FileName, Date = item.Timestamp, Status = item.ValidationStatus, ValidationErrorReport = "View" });
}
return objDetails;
}
View:
#model IEnumerable<EFITestHarness.Models.SchemeDetailsModel>
#using System.Web.Helpers;
#{
ViewBag.Title = "SchemeDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
var grid = new WebGrid(Model, canPage: true, rowsPerPage: 4, selectionFieldName: "selectedRow"); grid.Pager(WebGridPagerModes.NextPrevious);
}
<table>
<tr>
<td>#Html.ActionLink("Back", "FileUpload", "Home", null, new { #class = "form-control" })
</td>
</tr>
</table>
<div id="gridContent" class="webGridWrapper">
#grid.GetHtml(tableStyle: "webGrid",
footerStyle: "foot",
headerStyle: "webGridHeader",
alternatingRowStyle: "webGridAlt",
selectedRowStyle: "select",
columns: grid.Columns(
grid.Column("FileName"), //the model fields to display
grid.Column("Date"),
grid.Column("SchemeId"),
grid.Column("Status"),
grid.Column("ValidationErrorReport", format: (item => Html.ActionLink((string)(#item.ValidationErrorReport).ToString(), "ValidationResults", new { fileName = #item.FileName })))
))
</div>
Controller:
[HttpGet]
public ActionResult ValidationResults(string fileName)
{
Session["FileName"] = fileName;
if (ModelState.IsValid)
{
List<ValidationResultsModel> objValidationResults = new List<ValidationResultsModel>();
string employerId = Session["EmployerId"].ToString();
objValidationResults = _repository.getValidationResultsDetails(101);
if (objValidationResults.Count() > 0)
{
//var dataGrid = new GridView();
Session["results"] = objValidationResults;
//dataGrid.DataSource = objValidationResults;
//dataGrid.DataBind();
return View(objValidationResults);
}
else
return PartialView("~/Views/Results.cshtml");
}
return View();
}
Model:
public class ValidationResultsModel
{
public string NINO { get; set; }
public DateTime? DOB { get;set;}
public string Transaction { get;set; }
public string Element { get;set; }
public string ErrorMessage { get; set; }
}
View:
#model IEnumerable<EFITestHarness.Models.ValidationResultsModel>
#using System.Web.Helpers;
#{
ViewBag.Title = "ValidationResults";
Layout = "~/Views/Shared/_Layout.cshtml";
var grid = new WebGrid(Model, canPage: true, rowsPerPage:2, selectionFieldName: "selectedRow"); grid.Pager(WebGridPagerModes.NextPrevious);
}
#using (Html.BeginForm("ValidationResults", "Home", new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<table>
<tr>
<td>#Html.ActionLink("Back", "History", "Home", null, new { #class = "form-control" })
</td>
</tr>
</table>
<div class="container-fluid" style="font-size:medium;color:blue;">
Validation Results: </div>
<div style="font-size:medium;color:black;">1.Error Message<br />
</div>
<div id="gridContent" class="webGridWrapper">
#grid.GetHtml(tableStyle: "webGrid",
footerStyle: "foot",
headerStyle: "webGridHeader",
alternatingRowStyle: "webGridAlt",
selectedRowStyle: "select",
columns: grid.Columns(
grid.Column("NINO"), //the model fields to display
grid.Column("DOB"),
grid.Column("Transaction"),
grid.Column("Element"),
grid.Column("ErrorMessage", style: "description")
))
</div>
}
<div style="font-size:medium;color:black;">
Select the Button below to Download the Validation error Report
</div>
<div>
<input type="button" class="btn btn-primary btn-md" value="Download" onclick="#("window.location.href='" + #Url.Action("Download", "Home") + "'");" />
</div>
Controller:
[HttpGet]
public ActionResult Download()
{
var dataGrid = new GridView();
dataGrid.DataSource = Session["results"];
dataGrid.DataBind();
/*Code to eport the detail in excel sheet format*/
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename='" + Session["FileName"] + "'.xls");
Response.ContentType = "application/ms-excel";
Response.Charset = "";
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
dataGrid.RenderControl(htw);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
return View();
}
partial view:
#{
ViewBag.Title = "ValidationResults";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<table>
<tr>
<td>
#Html.ActionLink("Back", "History", "Home", null, new { #class = "form-control" })
</td>
</tr>
</table>
<div class="container-fluid" style="font-size:medium;color:blue;">
Validation Results:
</div>
<div style="font-size:medium;color:black;">
1.Successful Message<br />
</div>
}