Error when joining two tables using linq in mvc4 - linq

This is my controller, in select new what should I use? If I use any class name the it is showing error like name don't find in this model?
Here the controller code:
public class HomeController : Controller
{
Database1Entities db = new Database1Entities();
public ActionResult Index()
{
return View();
}
public ActionResult details()
{
var myParts = (from p in db.emps
join d in db.depts on p.Eid equals d.Eid
select new
{
name =p.name,
address = p.address,
number=d.number,
sub=d.sub
}).ToList();
return View(myParts);
}
}
}
My index page what should I give in model if I give the class name or table name if I give class name then I have two class the which class i give in above model
here this Index page code:
#model IEnumerable<two2.Models.mass>
#{
ViewBag.Title = " Deaprtment name ";
}
<h2>Index</h2>
#{
ViewBag.Title = "Department";
}
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.name)
</th>
<th>
#Html.DisplayNameFor (model => model.address)
</th>
<th>
#Html.DisplayNameFor (model => model.sub)
</th>
<th>
#Html.DisplayNameFor (model => model.mark)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.address)
</td>
<td>
#Html.DisplayFor(modelItem => item.sub)
</td>
<td>
#Html.DisplayFor(modelItem => item.mark)
</td>
</tr>
}
</table>
and my view page
in index page it is showing object not found
and in foreach statement it is showing error
#model two2.Models.mass
#{
ViewBag.Title = "deatils";
}
#using (#Html.BeginForm())
{
#Html.LabelFor(model => model.name)
#Html.TextBoxFor(model => model.name)
<br /><br />
#Html.LabelFor(model => model.address)
#Html.PasswordFor(model => model.address)
<br /><br />
<br /><br />
#Html.LabelFor(model => model.sub)
#Html.PasswordFor(model => model.sub)
<br /><br />
<br /><br />
#Html.LabelFor(model => model.mark)
#Html.PasswordFor(model => model.mark)
<br /><br />
<button>Login</button>
}
I don't know what should I use such that my be class name or table name and how to display on view

You should use same class name in Action also which is used in View like:
public ActionResult details()
{
var myParts = (from p in db.emps
join d in db.depts on p.Eid equals d.Eid
select two2.Models.mass
{
Eid = p.Eid,
name = p.name,
address = p.address,
number = d.number,
mark = d.mark, // <- you need to pass mark as it is used in View
sub = d.sub
}).ToList();
return View(myParts);
}
If you are using in View:
#model IEnumerable<two2.Models.mass>
Class two2.Models.mass is one type of ViewModel and it should contain only those fields which are needed in View:
namespace two2.Models
{
public class mass
{
public int Eid { get; set; }
public string name { get; set; }
public string address { get; set; }
public int number { get; set; }
public string sub { get; set; }
public int mark { get; set; }
}
}

Related

ASP.NET Core 6 MVC : HTML table to view model collection

Starting up with ASP.NET Core 6 MVC and in my case I have one view which lists few properties of one object and then some other for their children in a editable table (user can edit the values)
View model has the properties and an IEnumerable of the children:
public class MyObjectViewModel
{
public String Id { get; set; }
public String Descr { get; set; }
public IEnumerable<ChildrenObject> Children { get; set; }
public MyObjectViewModel()
{
Children = Enumerable.Empty<ChildrenObject>();
}
public class ChildrenObject
{
public String? Id { get; set; }
public String? Name { get; set; }
}
}
All under the same form:
#using (Html.BeginForm("Save", "Controller", FormMethod.Post))
{
<input type="submit" value="SAVE"/>
<br />
#Html.LabelFor(model => model.Id)
#Html.TextBoxFor(model => model.Id, new { #readonly = "readonly" })
<br />
#Html.LabelFor(model => model.Descr)
#Html.EditorFor(model => model.Descr)
<br />
<table>
<tbody>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
#foreach (var child in Model.Children)
{
<tr>
<td>#child.Id</td>
<td><input class="ef-select" type="text" value="#child.Name"></td>
</tr>
}
</tbody>
</table>
}
So when the button is pressed the data is dumped back to the model to perform the SAVE action in the controller.
All ok for the simple fields (I can get the data in the controller as the view model), but not sure how to accomplish it with the table / children property...
Any simple way without needing to use JS to serialise or pick up the data from the table?
Thanks
If you want to pass id and name of ChildrenObject in table,you can try to add hidden inputs for the Id,and set name attribute for name inputs:
#{var count = 0; }
#foreach (var child in Model.Children)
{
<tr>
<td>
#child.Id
<input value="#child.Id" name="Children[#count].Id" />
</td>
<td><input class="ef-select" type="text" value="#child.Name" name="Children[#count].Name"></td>
</tr>
count++;
}

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.

Error on page: The model item passed into the dictionary is of type 'System.Data.Entity.DynamicProxies

I get this error on my Details view page:
The model item passed into the dictionary is of type 'System.Data.Entity.DynamicProxies.cpd_certificates_65AF30842281867E2F4F6A1026590271109C12A85C8175394F14EF6DE429CBC7', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[cpd.Models.cpd_certificates]'.
This is my controller :
public class Default8Controller : Controller
{
//
// GET: /Default8/
private cpdDbContext db = new cpdDbContext();
public ActionResult Index()
{
return View(db.CPD.ToList());
}
//
// GET: /Default8/Details/5
public ActionResult Details(int id)
{
cpd_certificates cpd_ = db.Cert.Find(id);
return View(cpd_);
}
Below is my Details view:
#model IEnumerable<cpd.Models.cpd_certificates>
#{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<table>
<tr>
<th>
certificateNo
</th>
<th>
Mark
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CertificateNo)
</td>
<td>
#Html.DisplayFor(modelItem => item.Mark)
</td>
</tr>
}
</table>
Below is the cpd_certificates model:
public class cpd_certificates
{
[Key]
public int CertificateNo { get; set; }
public int QuizNo { get; set; }
public DateTime? DateReceived { get; set; }
public DateTime? DatePaid { get; set; }
public string Mark { get; set; }
public int? AccreditationNo { get; set; }
public int? ID { get; set; }
public virtual cpd_recipients Recipients { get; set; }
}
I have two models and I can view the list on my Index. I intended that when I click the details link it takes me to details of certificates earned and exams which are in another model/table. So in short two models which have a PK ID for CPD and FK ID on Cert. Index page show just personal information and this page is fine.
When Details is clicked it then shows the other model/table data that is the many certificates of that person.
You should pass the model into the view as the List of IEnumerable entries instead of passing it as a single entry.
In your Controller you want to show one entry details, but in the view, want to show details of all entries.First you should decide what to show.
For showing one entry details, use this:
controller:
public ActionResult Details(int id)
{
cpd_certificates cpd_ = db.Cert.Find(id);
return View(cpd_);
}
view:
#model cpd.Models.cpd_certificates
#{
ViewBag.Title = "Details";}
<h2>Details</h2>
<table>
<tr>
<th>
certificateNo
</th>
<th>
Mark
</th>
<th></th>
</tr>
<tr>
<td>
#Html.DisplayFor(model => model.CertificateNo)
</td>
<td>
#Html.DisplayFor(model => model.Mark)
</td>
</tr>
}
</table>
And when you want to list all of entries, use this:
controller:
public ActionResult List()
{
cpd_certificates cpd_ = db.Cert.ToList();
return View(cpd_);
}
view:
#model IEnumerable<cpd.Models.cpd_certificates>
#{
ViewBag.Title = "List";
}
<h2>List</h2>
<table>
<tr>
<th>
certificateNo
</th>
<th>
Mark
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CertificateNo)
</td>
<td>
#Html.DisplayFor(modelItem => item.Mark)
</td>
</tr>
}
</table>

How to pass IEnumerable object or data from view to controller?

I have created a strongly type view. I want to pass IEnumerable Object or data from View to Controller. Following are my Model, Controller ,view
My Model:
public class UserDetailsClass
{
public static FeedbackDatabaseDataContext context = new FeedbackDatabaseDataContext();
public class Tablefields
{
[Key]
public int ID { get; set; }
[Required(ErrorMessage = "Email is required")]
public string EmailID { get; set; }
[Required(ErrorMessage="Password is required")]
public string Password { get; set; }
[Required(ErrorMessage = "First Name is required")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name is required")]
public string LastName { get; set; }
}
public static List<UserDetails> getalluser()
{
var lst = (from r in context.UserDetails select r);
return lst.ToList();
}
}
My Controller
public ActionResult Test()
{
IList<UserDetailsClass.Tablefields> viewmodel = new List<UserDetailsClass.Tablefields>();
var q = UserDetailsClass.getalluser().ToList();
foreach (SQLOperation.Models.UserDetails item in q)
{
UserDetailsClass.Tablefields viewItem = new UserDetailsClass.Tablefields();
viewItem.EmailID = item.Email;
viewItem.FirstName = item.FirstName;
viewItem.LastName = item.LastName;
viewItem.Password = item.Password;
viewmodel.Add(viewItem);
}
return View(viewmodel);
}
[HttpPost]
public ActionResult Test(IEnumerable<UserDetailsClass.Tablefields> items)
{
return View();
}
My View:
#model IEnumerable<SQLOperation.Models.UserDetailsClass.Tablefields>
#{
ViewBag.Title = "Test";
}
<h2>Test</h2>
#using (Html.BeginForm())
{
<table>
<tr>
<th>
EmailID
</th>
<th>
Password
</th>
<th>
FirstName
</th>
<th>
LastName
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.EmailID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Password)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
</tr>
}
</table>
<input type="submit" value="submit" />
}
I didn't get any value in items.When I set breakpoint on it it show NULL in items
I am totally Confused about how to pass values to controller.
Thank you,
Amol
Instead of #Html.DisplayFor use #Html.EditorFor, that way databinding will happen in your form.
Also since you are using collection you need to iterate your fields (simplified example):
#for (int row = 0; row < Model.Count; row++)
{
#Html.EditorFor(x => x[row].FirstName )
}
#for (int i = 0; i < Model.length; i ++)
{
<tr>
<td>
#Html.DisplayFor(model => Model[i].EmailID)
</td>
<td>
#Html.DisplayFor(model => Model[i].Password)
</td>
<td>
#Html.DisplayFor(model => Model[i].FirstName)
</td>
<td>
#Html.DisplayFor(model => Model[i].LastName)
</td>
</tr>
}
</table>
<input type="submit" value="submit" />
}

MVC3 textbox submits null value?

I am creating a dynamic list of text boxes. when the user submits the value in the fields come back null. I think I'm missing something.
This is my product model:
public class EnqProduct
{
public string Id { get; set; }
public string Product { get; set; }
public string Quantity { get; set; }
}
This is the page model which includes a list of the above.
public IList<EnqProduct> EnqProduct { get; set; }
This is how I am setting the model:
IList<EnqProduct> items2 = Session["enquiry"] as IList<EnqProduct>;
var EnquiryModel = new Enquiry {
EnqProduct = items2
};
return View(EnquiryModel);
and this is how I display the fields:
foreach (var item in Model.EnqProduct)
{
<tr>
<td>
<span class="editor-field">
#Html.TextBox(item.Id, item.Product)
#Html.ValidationMessageFor(m => m.A1_Enquiry)
</span>
<br><br>
</td>
<td>
<span id = "field" class="editor-field">
#Html.TextBox(item.Id, item.Quantity)
</span>
<br><br>
</td>
</tr>
}
When the user submits the fields go back to the controller null?
I would recommend you using editor templates and replace your foreach loop with the following:
#model Enquiry
<table>
<thead>
<tr>
<th>product name</th>
<th>quantity</th>
</tr>
</thead>
<tbody>
#Html.EditorFor(x => x.EnqProduct)
</tbody>
</table>
and then define an editor template which will automatically be rendered for each element of the EnqProduct collection (~/Views/Shared/EditorTemplates/EnqProduct.cshtml):
#model EnqProduct
<tr>
<td>
#* We include the id of the current item as hidden field *#
#Html.HiddenFor(x => x.Id)
<span class="editor-field">
#Html.EditorFor(x => x.Product)
#Html.ValidationMessageFor(x => x.Product)
</span>
</td>
<td>
<span id="field" class="editor-field">
#Html.EditorFor(x => x.Quantity)
</span>
</td>
</tr>
Now when you submit the form you will get correct values:
public class HomeController: Controller
{
public ActionResult Index()
{
var model = new Enquiry();
model.EnqProduct = ...
return View(model);
}
[HttpPost]
public ActionResult Index(Enquiry model)
{
// the model.EnqProduct will be correctly populated here
...
}
}
As far as the correct wire format that the default model binder expects for your input fields I would recommend you taking a look at the following article. It will allow you to more easily debug problems in the feature when some model is not properly populated. It suffice to look with FireBug and the name of the values being POSTed and you will immediately know whether they are OK or KO.

Resources