Values from Form doesn't pass to view MVC - asp.net-mvc

Can someone tell what is wrong in my code? I've been searching several days a solution for this, but can't find any. Values from Form doesn't pass to view, only values that are "hardcoded" like OrderDate, CompanyID and so on, is added to database.
I'm making my first MVC onlineshop and struggling with it quite a lot.
EDIT: Data to view is coming from db.Selection but I need to save data to model db.Cart with additional parameters. Maybe FormCollection is not right way to do this, but what is?
NVCONTROLLER:
public ActionResult Index()
{
return View(db.Selection);
}
public ActionResult AddtoCart()
{
return View("AddtoCart");
}
[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult AddtoCart(FormCollection form)
{
string Author = form["Author"];
string ISBN = form["ISBN"];
string BookName = form["BookName"];
string Publisher = form["Publisher"];
string Price = form["Price"];
var cart = new Cart();
cart.Orderdate = DateTime.Now;
cart.CompanyID = 12345;
cart.ISBN = Convert.ToInt32(ISBN);
cart.BookName = BookName;
cart.Price = Convert.ToInt32(Price);
cart.IsInCart = true;
cart.Author = Author;
cart.Publisher = Publisher;
cart.SentToJvs = false;
cart.Reference = "NV kevät 1999";
db.Cart.Add(cart);
db.SaveChanges();
return RedirectToAction("Index");
}
VIEW
#model IEnumerable<STGchannelMVC.Models.Selection>
#using STGchannelMVC.Controllers
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("AddtoCart", "NV", FormMethod.Post))
{
<p>
Lisää tuotteet ostoskoriin
</p>
#Html.AntiForgeryToken()
<div class="form-group">
<table class="table">
<tr>
<th hidden>
#Html.DisplayNameFor(model => model.BookID)
</th>
<th>
#Html.DisplayNameFor(model => model.ISBN)
</th>
<th>
#Html.DisplayNameFor(model => model.Author)
</th>
<th>
#Html.DisplayNameFor(model => model.BookName)
</th>
<th>
#Html.DisplayNameFor(model => model.Publisher)
</th>
<th>
#Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td hidden>
#Html.DisplayFor(modelItem => item.BookID)
</td>
<td>
#Html.DisplayFor(modelItem => item.ISBN)
</td>
<td>
#Html.DisplayFor(modelItem => item.Author)
</td>
<td>
#Html.DisplayFor(modelItem => item.BookName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Publisher)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<button type="submit" class="btn btn-primary">Add to Cart</button>
</td>
</tr>
}
</table>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
MODEL
public class Cart
{
public int OrderID { get; set; }
public Nullable<System.DateTime> Orderdate { get; set; }
[Display(Name = "CompanyID")]
public Nullable<long> CompanyID { get; set; }
[Display(Name = "ISBN")]
public Nullable<long> ISBN { get; set; }
[Display(Name = "BookName")]
public string BookName { get; set; }
[Display(Name = "Price")]
public Nullable<decimal> Price { get; set; }
public Nullable<bool> IsInCart { get; set; }
[Display(Name = "Author")]
public string Author { get; set; }
[Display(Name = "Publisher")]
public string Publisher { get; set; }
public Nullable<bool> SentToJvs { get; set; }
public string Reference { get; set; }
}

This question/answer might explain it better: MVC4 Razor - #Html.DisplayFor not binding to model
Basically you have two options:
In your view, you can keep using #Html.DisplayFor() but add #Html.HiddenFor() inside the foreach loop. Doesn't make much sense since there's no way for the values to be changed by the user.
#foreach (var item in Model)
{
#Html.HiddenFor(modelItem => item.BookID)
#Html.HiddenFor(modelItem => item.ISBN)
#Html.HiddenFor(modelItem => item.Author)
#Html.HiddenFor(modelItem => item.BookName)
#Html.HiddenFor(modelItem => item.Publisher)
#Html.HiddenFor(modelItem => item.Price)
<tr>
<td hidden>
#Html.DisplayFor(modelItem => item.BookID)
</td>
<td>
#Html.DisplayFor(modelItem => item.ISBN)
</td>
<td>
#Html.DisplayFor(modelItem => item.Author)
</td>
<td>
#Html.DisplayFor(modelItem => item.BookName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Publisher)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<button type="submit" class="btn btn-primary">Add to Cart</button>
</td>
</tr>
}
Or instead of using #Html.DisplayFor(), use #Html.TextboxFor because DisplayFor does not render an input element that the user can interact with while TextboxFor does.

Related

Send List Type to View from Controller

Entities:
public partial class Institution
{
public int? Id { get; set; }
public string? District { get; set; }
public string? InstitutionCode { get; set; }
public string? InstitutionName { get; set; }
public string? DemolitionStatus { get; set; }
public string? ReinforcementStatus { get; set; }
}
Controller:
public class HomeController : Controller
{
_context c;
public HomeController(_context c)
{
this.c = c;
}
public IActionResult Index()
{
var GetAll=c.Institutions.ToList();
return View(GetAll);
}
}
In View
#model List<GetAll>
#foreach (var item in Model)
{
#item.InstitutionName
}
Also it doesn't work:
The type or namespace name 'GetAll' could not be found
Try with #model SolutionName.Entities or Ienumarable or adding namespace #using FBMv3.Controllers
What is the wrong or missing?
Try with #model SolutionName.Entities or Ienumarable or adding
namespace #using FBMv3.Controllers
What is the wrong or missing?
Well, first of all, GetAllcannot be a reference for your Institution list.
assuming, you are using asp.net core application, in this scenario, here #model List<GetAll> should be the location of your Institution class. For instance if your Institution class located like below folder:
So you should write the code like this #model IEnumerable<DotNet6MVC.Models.Institution> instead of #model List<GetAll>
Complete sample for you:
Controller:
public IActionResult Index()
{
var instituteList = new List<Institution>()
{
new Institution(){ Id =101,District = "Dis-A", InstitutionCode = "IC-1",InstitutionName = "IN-AAA",DemolitionStatus="YES",ReinforcementStatus = "T"},
new Institution(){ Id =102,District = "Dis-B", InstitutionCode = "IC-2",InstitutionName = "IN-BBB",DemolitionStatus="NO",ReinforcementStatus = "F"},
new Institution(){ Id =103,District = "Dis-C", InstitutionCode = "IC-3",InstitutionName = "IN-CCC",DemolitionStatus="NO",ReinforcementStatus = "T"},
new Institution(){ Id =104,District = "Dis-D", InstitutionCode = "IC-4",InstitutionName = "IN-DDD",DemolitionStatus="NO",ReinforcementStatus = "T"},
new Institution(){ Id =105,District = "Dis-E", InstitutionCode = "IC-5",InstitutionName = "IN-EEE",DemolitionStatus="YES",ReinforcementStatus = "T"},
};
return View(instituteList);
}
Note: You could write your controller code as well. Like this:
var GetAll=c.Institutions.ToList();
return View(GetAll)
View:
#model IEnumerable<DotNet6MVC.Models.Institution>
#{
ViewData["Title"] = "Index";
}
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Id)
</th>
<th>
#Html.DisplayNameFor(model => model.District)
</th>
<th>
#Html.DisplayNameFor(model => model.InstitutionCode)
</th>
<th>
#Html.DisplayNameFor(model => model.InstitutionName)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.District)
</td>
<td>
#Html.DisplayFor(modelItem => item.InstitutionCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.InstitutionName)
</td>
<td>
<a asp-action="EditMember" class="btn btn-primary" asp-route-memberId="#item.Id">Details</a> | <a asp-action="EditMember" class="btn btn-warning" asp-route-memberId="#item.Id">Edit</a>
</td>
</tr>
}
</tbody>
</table>
Note: Be double confirm in your scenario, it would be #model IEnumerable<YourProjectName.YourClassFolder.Institution>. Because, your problem is here.
Output:
Note: If you still have any concern on this I would highly recommend you to check this official document.

Issue when trying to use partial view inside view

still learning MVC (slowly) which I am enjoying but having some trouble with partial views. If anyone could point me in the right direction that would be great!
This is the error I am getting:
InvalidOperationException: The model item passed into the dictionary
is of type
'System.Collections.Generic.List1[mvc_project.Models.Contact]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[mvc_project.ViewModels.ViewContactsVM]'.
I created the partial view using the List template.
Chose my model ViewContactsVM
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace mvc_project.ViewModels
{
public class ViewContactsVM
{
[Key]
public int ContactID { get; set; }
public int ClientID { get; set; }
[DisplayName("Contact Name")]
public string ContactName { get; set; }
[DisplayName("Contact Phone Number")]
public string ContactPhoneNumber { get; set; }
[DisplayName("Contact Email Address")]
public string ContactEmailAddress { get; set; }
[DisplayName("Job Title")]
public string JobTitle { get; set; }
public string AddedBy { get; set; }
}
}
Controller code:
public ActionResult _ContactList(int id)
{
using (var context = new mvc_projectEntities())
{
var data = context.Contacts.Where(x => x.ClientID == id).ToList();
return View(data);
}
}
_ContactsList Partial View Page:
#model IEnumerable<mvc_project.ViewModels.ViewContactsVM>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.ClientID)
</th>
<th>
#Html.DisplayNameFor(model => model.ContactName)
</th>
<th>
#Html.DisplayNameFor(model => model.ContactPhoneNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.ContactEmailAddress)
</th>
<th>
#Html.DisplayNameFor(model => model.JobTitle)
</th>
<th>
#Html.DisplayNameFor(model => model.AddedBy)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ClientID)
</td>
<td>
#Html.DisplayFor(modelItem => item.ContactName)
</td>
<td>
#Html.DisplayFor(modelItem => item.ContactPhoneNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.ContactEmailAddress)
</td>
<td>
#Html.DisplayFor(modelItem => item.JobTitle)
</td>
<td>
#Html.DisplayFor(modelItem => item.AddedBy)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ContactID }) |
#Html.ActionLink("Details", "Details", new { id=item.ContactID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ContactID })
</td>
</tr>
}
</table>
Details View Page:
#{
ViewBag.Title = "Details";
}
<h2>Details</h2>
#Html.Action("_ContactList")
It is necessary to pass the ViewContactsVM type to the view, as it defined in the view data model. Therefore try:
public ActionResult _ContactList(int id)
{
using (var context = new mvc_projectEntities())
{
var data = context.Contacts
.Where(x => x.ClientID == id)
.Select(c => new mvc_project.ViewModels.ViewContactsVM() {
ContactID = c.ContactID,
ClientID = c.ClientID,
ContactName = c.ContactName
...
})
.ToList();
return View(data);
}
}

How to implement image dynamically in multiple views?

I am looking for a way to display the Image dynamically based on Placement_Position and Region into different View.
Placement view, where I display all the content from table.
There is no link between these Views.
I am confused, how to implement this scenario. Anyone please help me here.
In Employee view, I want to display the image Atop_1if the region is 1 and Atop_2 if the region is 2
public class ClsPlacement
{
public int Id { get; set; }
public string Placement_Position { get; set; }
public string Path { get; set; }
public int Region { get; set; }
}
Controller
public ActionResult Placement()
{
var model = context.Placement.ToList();
return View(model);
}
Placement View
<table>
<tr>
<th>
#Html.DisplayNameFor(m => m.Id)
</th>
<th>
#Html.DisplayNameFor(m => m.Placement_Position)
</th>
<th>
#Html.DisplayNameFor(m => m.Region)
</th>
<th>
#Html.DisplayNameFor(m => m.Path)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
#Html.DisplayFor(modelItem => item.Id)
<td>
#Html.DisplayFor(modelItem => item.Placement_Position)
</td>
<td>
#Html.DisplayFor(modelItem => item.Region)
</td>
<td>
#Html.Image(item.Path, "Image")
</td>
</tr>
}
</table>
you can use LINQ to write query for each controller and return IList :
so in Employee view :
public ActionResult Employee()
{
IList<ClsPlacement> plcList = new List<ClsPlacement>();
var query= from m in context.Placement
select m;
var plc= query.ToList();
foreach(var plcData in plc)
{
if(plcData.Placement_Position=="A_Top")
{
plcList.Add(new ClsPlacement()
{
Id= plcData.Id,
Placement_Position= plcData.Placement_Position,
Path = plcData.Path ,
Region= plcData.Region
});
}
}
return View(plcList);
}
then in your view you can write this:
#foreach (var item in Model)
{
<div class="col-md-5">
<img src="#Url.Content(String.Format("~/Content/Place/{0}{1}{2}", "Atop_",item.Region,".jpg"))" />
</div>
}
and same this for Customer view.

how to get selected checkbox in asp.net using entity framework

i'm new to asp.net mvc.I have a list of checkboxes and i want when the checkboxes are selected a new list of selected checkboxs are shown.
my code Product.cs code:
public class Product
{
public int ProductID { get; set; }
public string ProductName { get; set; }
public int Price { get; set; }
public bool Checked { get; set; }
public virtual ICollection<Purchase> Purchases { get; set; }
}
My view:
<h2>Product Lists</h2>
#using (Html.BeginForm())
{
<table class="table">
<tr>
<th>
Product ID
</th>
<th>
Product Name
</th>
<th>
Price
</th>
<th></th>
</tr>
#for (var i = 0; i < Model.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(x => x[i].ProductID)
</td>
<td>
#Html.DisplayFor(x => x[i].ProductName)
</td>
<td>
#Html.DisplayFor(x => x[i].Price)
</td>
<td>
#Html.CheckBoxFor(x => x[i].Checked, new { Style = "vertical-align:3px}" })
</td>
</tr>
}
</table>
<input type="submit" value="Purchase" class="btn btn-default" />
}
This is my Controller code.I want when the check boxes are selected in a new page the selected check boxes are shown.
my ActionResult:
public ActionResult Index()
{
return View(db.Products.ToList());
}
[HttpPost]
public ActionResult Index(List<Product> list)
{
return View(list);
}
#using (Html.BeginForm())
{
<table class="table">
<tr>
<th>
Product ID
</th>
<th>
Product Name
</th>
<th>
Price
</th>
<th></th>
</tr>
#for (var i = 0; i < Model.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(x => x[i].ProductID)
</td>
<td>
#Html.DisplayFor(x => x[i].ProductName)
</td>
<td>
#Html.DisplayFor(x => x[i].Price)
</td>
<td>
#Html.CheckBoxFor(x => x[i].Checked, new { Style = "vertical-align:3px}" })
</td>
</tr>
}
</table>
If you already have a List with all checked/unchecked properties and just want to show the checked records in a new view, you can store your list in a TempData and redirect to an action which will use your list:
public ActionResult Index()
{
return View(db.Products.ToList());
}
[HttpPost]
public ActionResult Index(List<Product> list)
{
TempData["CheckedRecords"] = list.Where(x=>x.Checked).ToList(); //Don't forget to add 'using System.Linq;'!
return RedirectToAction("MyOtherView");
}
public ActionResult MyOtherView()
{
var checkedRecords = (List<Product>)TempData["CheckedRecords"];
return View(checkedRecords);
}

Modifying the text color and background color of a table

I no longer have a question as I figured out how to do it
Index.cshtml
#model IEnumerable<ContactManager.Models.Contacts>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2></h2>
#using (Html.BeginForm()) {
<p>#Html.TextBox("SearchString")
<input type="submit" value="Search" /></p>
}
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstName)
</th>
<th>
#Html.DisplayNameFor(model => model.LastName)
</th>
<th>
#Html.DisplayNameFor(model => model.Address)
</th>
<th>
#Html.DisplayNameFor(model => model.City)
</th>
<th>
#Html.DisplayNameFor(model => model.State)
</th>
<th>
#Html.DisplayNameFor(model => model.Zip)
</th>
<th>
#Html.DisplayNameFor(model => model.Phone)
</th>
<th>
Modify
</th>
</tr>
#foreach (var item in Model) {
var lncolor = "white" ;
var zipcolor = "black";
switch (item.LastName) {
case "Whited":
lncolor = "yellow";
break;
default:
lncolor = "white";
break;
}
if (item.ID % 2 == 0) {
zipcolor = "red";
} else {
zipcolor = "black";
}
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td bgcolor="#lncolor">
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Address)
</td>
<td>
#Html.DisplayFor(modelItem => item.City)
</td>
<td>
#Html.DisplayFor(modelItem => item.State)
</td>
<td>
<font color="#txtcolor">
#Html.DisplayFor(modelItem => item.Zip)
</font>
</td>
<td>
#Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
Relative part of my Controller
private ContactsDBContext db = new ContactsDBContext();
// GET: Contacts
public ActionResult Index(string searchString)
{
var contacts = from c in db.Contact
select c;
if (!String.IsNullOrEmpty(searchString)) {
contacts = contacts.Where(s => s.FirstName.Contains(searchString) || s.LastName.Contains(searchString) || s.Address.Contains(searchString)
|| s.City.Contains(searchString) || s.State.Contains(searchString) || s.Zip.Contains(searchString) || s.Phone.Contains(searchString));
}
//return View(db.Contact.ToList());
return View(contacts);
}
I managed to figured out a way to accomplish what I wanted to do with this. I have updated the code as well to refelct on what I have done. I am not sure it is the most elegant way to accomplish this so if anyone has any better suggestions I am all ears.
Writing any kind of logic in view page is highly depreciated in MVC pattern. You can do it by using viewmodel. Here is the steps.
First create an appropriate view model for model contact.
public class ContactViewModel
{
public string FirstName{ get; set; }
public string LastName{ get; set; }
public string Address{ get; set; }
public string City{ get; set; }
public string State{ get; set; }
public string Zip{ get; set; }
public string Phone{ get; set; }
public string LastNameBgcolor{ get; set; }
public string FontColor{ get; set; }
}
In controller:
private ContactsDBContext db = new ContactsDBContext();
// GET: Contacts
public ActionResult Index(string searchString)
{
var contacts = from c in db.Contact
select c;
if (!String.IsNullOrEmpty(searchString)) {
contacts = contacts.Where(s => s.FirstName.Contains(searchString) || s.LastName.Contains(searchString) || s.Address.Contains(searchString)
|| s.City.Contains(searchString) || s.State.Contains(searchString) || s.Zip.Contains(searchString) || s.Phone.Contains(searchString));
}
//return View(db.Contact.ToList());
List<ContactViewModel> ContactViewModels= new List<ContactViewModel>();
foreach(var contact in contacts){
ContactViewModel cvm= new ContactViewModel();
cvm.FirstName=contact.FirstName;
cvm.LastName=contact.LastName;
if(contact.LastName=="Whited"){
cvm.LastNameBgcolor="yellow";
}
else{
cvm.LastNameBgcolor="white";
}
cvm.Address=contact.Address;
cvm.City=contact.City;
cvm.State=contact.State;
cvm.Zip=contact.Zip;
cvm.Phone=contact.Phone;
if (contact.ID % 2 == 0) {
cvm.FontColor = "red";
} else {
cvm.FontColor = "black";
}
ContactViewModels.Add(cvm);
}
return View(ContactViewModels);
}
In view page:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td bgcolor="#model.LastNameBgcolor">
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Address)
</td>
<td>
#Html.DisplayFor(modelItem => item.City)
</td>
<td>
#Html.DisplayFor(modelItem => item.State)
</td>
<td>
<font color="#model.FontColor">
#Html.DisplayFor(modelItem => item.Zip)
</font>
</td>
<td>
#Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
Hope this will help.

Resources