model does not contain a public instance definition for 'OnlineUserModel' - asp.net-mvc

On my View:
#model IEnumerable<Project.Models.OnlineUserModel>
<div class="form-group online">
<ul>
#foreach (var user in Model)
{
<li>
#Html.DisplayFor(modelItem => user.UserName) <br />
</li>
}
</ul>
</div>
AJAX:
$(function () {
$.ajax({
type: "POST",
url: "/Home/OnlineUsers",
MODEL :
public class OnlineUserModel
{
public string UserName { get; set; }
public string UserID { get; set; }
public OnlineUserModel(DataRow rs)
{
if (!DBNull.Value.Equals(rs["UserName"])) this.UserName = (string)rs["UserName"];
if (!DBNull.Value.Equals(rs["UserID"])) this.UserID = (string)rs["UserID"];
}
public static List<OnlineUserModel> OnlineUsersList()
{
List <OnlineUserModel> user = new List<OnlineUserModel>();
DataTable resultTable = Globals.CommonData.RetrieveOnlineUsers();
if (resultTable != null)
{
foreach (DataRow rs in resultTable.Rows)
{
user.Add(new OnlineUserModel(rs));
}
}
return user;
}
}
CONTROLLER:
[HttpPost]
public JsonResult OnlineUsers()
{
return Json(Project.Models.OnlineUserModel.OnlineUsersList());
}
I did the same exact way on my other project and it is working fine but this one keeps giving me error and I need help in figuring it out. Probably an obvious one for the experienced contributor here but not for me. Thank you, Pls point me to the right direction.

Related

Dropdown list population from ViewModel

First of all, I know this question has been asked many, many times. I've read countless articles and Stack Overflow answers. I've tried to figure this problem out for four days and I think I need help if someone doesn't mind.
I have two databases. The employee database has a field called "DisplayName" -- the second database has a relationship with the first and they work together great. I'm able to call the two databases perfectly in another application.
You can see the in the picture Index Page
that I have a list of people. I want a dropdown below it that lists all display names in the database so employees can add themselves to the list. You'll see a dropdown in the image but it's not populated.
Seems simple. But geez. Part of a problem I'm having is my home controller already has a function to populate the list in the picture so I can't do another on that page. I've tried a lot of suggestions on a lot of sites. I get IEnumerable errors or display reference errors....
Here's my controller (again - it has nothing in it that helps the dropdown):
namespace SeatingChart.Controllers
{
public class HomeController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: Employee
public ActionResult Index()
{
var lists = db.BreakModels
.Include("Employee")
.Include("TimeEntered")
.Include("TimeCleared")
.Include("DisplayName")
.Select(a => new HomeIndexViewModels
{
Employee = a.Employee,
DisplayName = a.EmployeeModels.DisplayName,
TimeEntered = a.TimeEntered,
TimeCleared = a.TimeCleared.Value,
Id = a.EmployeeModels.Id,
});
return View(lists);
}
View:
#model IEnumerable<SeatingChart.Models.HomeIndexViewModels>
#{
Layout = null;
}
#Html.Partial("_Header")
<div class="container_lists">
<div class="container_break col-md-8">
<h5 style="text-align:center">Break List</h5>
<table class="table-bordered col-lg-12">
#if (Model != null)
{
foreach (var item in Model)
{
if (item.TimeCleared == null)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.DisplayName)
</td>
<td>
 BV
</td>
<td>
 #item.TimeEntered.ToString("HH:mm")
</td>
</tr>
}
}
}
</table>
#using (Html.BeginForm())
{
<div class="row site-spaced">
<div class="col-3">
#Html.DropDownList("DisplayName", new SelectList(new List<string>() { "---Dispatcher---" }), new { #class = "required " })
</div>
</div>
<div class="col-3">
<input type="submit" value="Submit" class="site-control" />
</div>
}
</div>
</div>
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace SeatingChart.Models
{
public class HomeIndexViewModels
{
//Break Model
public int BreakId { get; set; }
public int Employee { get; set; }
public DateTime TimeEntered { get; set; }
public DateTime? TimeCleared { get; set; }
//Employee Model
public int Id { get; set; }
public string DisplayName { get; set; }
public string DisplayNames { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool NotActive { get; set; }
public int Force { get; set; }
public string EmployeeList { get; set; }
}
}
I hope this is clear enough. I've tried so many different ways with so much code - the errors are different with everything I've tried.
Thanks in advance for your patience and help!
You can add to your viewmodel
public List<SelectListItem> Employees { get; set; }
Then you can populate this list with controller then in view just call it with:
#Html.DropDownListFor(m => m.Id, Model.Employees, new { #class = "form-control", required = "required" })
Update - how to populate list. Should work (but not tested code).
public List<SelectListItem> GetEmployeeForDropdown(List<HomeIndexViewModels> list)
{
List<SelectListItem> empList = new List<SelectListItem>();
try
{
if (list != null && list.Count > 0)
{
foreach (var item in list)
{
empList.Add(new SelectListItem { Text = item.DisplayName, Value = item.Id.ToString() });
}
}
else
{
empList.Add(new SelectListItem { Text = "No items", Value = string.Empty });
}
}
catch (Exception ex)
{
//handle exceptions here
}
return empList;
}
Edit: Remember to use your model in view!

How to update list withing viewmodel in view? Passing data from view to controller

I am passing viewmodel to create view where I select few properties from dropdown list and then I create new model in database. The problem is that I have to select a product from dropdown list and after button click add product to list(which is defined in model). You can see the code bellow, I am having the problem of passing id of product as it is always null
SellsViewModel:
public class SellsViewModel
{
public List<Center> center { get; set; }
public List<Leader> leader { get; set; }
public List<Member> member { get; set; }
public List<Group> group { get; set; }
public Sell sell { get; set; }
public Guid productSelection { get; set; }
public IEnumerable<Product> product { get; set; }
public IEnumerable<Product> selectedProducts { get; set; }
}
Create.cshtml
#model Medical.ViewModels.SellsViewModel
#{
var addproduct = Model.product.Select(product => new SelectListItem
{
Text = product.Name,
Value = product.Id.ToString()
});
}
...
<div class="form-group">
<div align="right" class="col-md-2">
<b>Delivery</b>
</div>
<div align="center" class="col-md-2">
#Html.DropDownListFor(m => m.productSelection, addproduct, "-- Choose product --")
</div>
<div class="col-md-2">
<a asp-action="AddProducttoSell" method="post" asp-route-id="#Model.productSelection" class="btn btn-primary">Add</a>
</div>
</div>
Controller:
[HttpGet]
public IActionResult AddProducttoSell(Guid id)
{
var sProduct = _context.Products.FirstOrDefault(p => p.Id == id);
svm.selectedProducts.ToList().Add(sProduct);
return RedirectToAction(nameof(Create));
}
Basically, I want that when I choose product in view, I add it to selectedProducts list in viewmodel, and than return it to view. Afterwards, I will submit new model to database.
I got your example to work in Core.
First, I followed this tutorial, making appropriate changes:
https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-2.2
This is the code, starting with my Model-codeFirst and my ViewModel:
namespace SOPassDataViewToController.Models
{
public class Sell
{
public int ID { get; set; }
public string Name { get; set; }
}
}
namespace SOPassDataViewToController.Models
{
public class Product
{
public int Value { get; set; }
public string Text { get; set; }
}
public class SellsViewModel
{
public List<Product> Products { get; set; }
public int productSelection { get; set; }
}
}
Here is my Controller code:
[HttpPost]
public IActionResult AddProducttoSell(SellsViewModel sellsviewmodel)
{
//put breakpoint here to interrogate sellsviewmodel-productSelection
var viewModel = PrepViewModel();
return View(viewModel);
}
// GET: Sells
// I'm using this method instead of AddProducttoSell
//public async Task<IActionResult> Index()
public IActionResult Index()
{
var viewModel = PrepViewModel();
//return View(await _context.Sells.ToListAsync());
return View(viewModel);
}
public SellsViewModel PrepViewModel()
{
//prepping view model
//sending view model to view
SellsViewModel viewModel = new SellsViewModel();
viewModel.Products = new List<Product>();
var products = _context.Sells.ToList();
foreach (Sell product in products)
{
var eachProduct = new Product();
eachProduct.Value = product.ID;
eachProduct.Text = product.Name;
viewModel.Products.Add(eachProduct);
}
return viewModel;
}
Here is my view Index.cshtml:
#model SOPassDataViewToController.Models.SellsViewModel
#*need the form tag*#
<form asp-action="AddProducttoSell">
<div class="form-group">
<div align="right" class="col-md-2">
<b>Delivery</b>
</div>
<div align="center" class="col-md-2">
#*#Html.DropDownListFor(m => m.productSelection, addproduct, "-- Choose product --")*#
#Html.DropDownListFor(m => m.productSelection, new SelectList(Model.Products, "Value", "Text"))
</div>
<div class="col-md-2">
#*took out will need to put back asp-route-id="#Model.productSelection"*#
#*<a asp-action="AddProducttoSell" method="post" asp-route-id="#Model.productSelection" class="btn btn-primary">Add</a>*#
<div class="form-group">
<input type="submit" value="AddProducttoSell" class="btn btn-primary" />
</div>
</div>
</div>
</form>
#section scripts
{
#*//the natural progression for what you are doing is to change the href not the asp-route-id, because
//href is what gets rendered. So you can do the following--and tighten it up--
//you can also use FormCollection, or even possibly window.location, but the best way from Microsoft's
//tutorial is to use a model like my previous post*#
<script>
$(document).ready(function () {
$("#DropDownElement").change(function () {
$("#PostingElement").attr("href", "/Sells/Edit/" + $("#DropDownElement").val());
})
});
</script>
}
My Action looks like the following. I use Edit instead of AddProducttoSell
// GET: Sells/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var sell = await _context.Sells.FindAsync(id);
if (sell == null)
{
return NotFound();
}
return View(sell);
}

How do I change a partial view with a radio button click in .Net MVC and have some of the model state passed along to the partial view?

I'm trying to display a partial view in a div block named 'productButtonForm' based on a radio button click. The partial view appears to be called, but the passed model has null member variables. Can someone help me figure out where I've gone wrong? Below is what I've got:
Model
public class RetrieveAllModel
{
public Guid ConversationId { get; set; }
public List<RetrieveProductsModel> Products { get; set; }
public RetrieveOffersModel Offers { get; set; }
public int ProductType { get; set; }
}
View
#{
ViewBag.Title = "Easy Order";
int productCount = 0;
}
<legend>Offers/Products</legend>
#using (Html.BeginForm("ShowProductItems", "BrowseShopping"))
{
foreach (var type in Model.Products)
{
if (productCount > 0 && productCount % 5 == 0)
{
<br/>//break after every 5 products
}
#type.Name
#Html.RadioButtonFor(model => model.ProductType, type.ID, Model);
<label> </label>
productCount = productCount + 1;
}
<div class="col-lg-5 col-md-6 col-sm-12" id="productButtonForm">
</div>
}
Controller
public PartialViewResult ShowProductItems()
{
return PartialView("RetrieveProducts", new RetrieveAllModel() {Products = new List<RetrieveProductsModel>()});
}
[HttpPost]
public PartialViewResult ShowProductItems(RetrieveAllModel model)
{
//The passed model only has the ProductType set, every other
//member variable is null
return PartialView("RetrieveProducts", model);
}
Script file
$(function() {
$("[name=ProductType]").on('change',
function() {
var $radio = $(this);
var myurl = "ShowProductItems?ProductType=" + $radio.val();
console.log("We hit the script");
$.ajax({
url: myurl,
type: 'POST',
success: function(data) {
$("#productButtonForm").append(data);
}
});
});
});
I had a few issues going. Aside from what Stephen mentioned above, I had two data models that needed to be represented in the same button group. To address that, I had to use Html.RadioButton instead of RadionButtonFor. Also, I needed to access the controller's established conversation with the client to access the model state of the current view. Once I got those in place, the partial view changes as desired. Below are the changes I made to fix my triggering problem.
Model
public class RetrieveAllModel
{
public Guid ConversationId { get; set; }
public List<RetrieveProductsModel> Products { get; set; }
public RetrieveOffersModel Offers { get; set; }
public string ProductType { get; set; }
}
public class RetrieveCatalogModel
{
public List<BrowseDataItemModel> AvailableBrowseItems { get; set; }
}
public class RetrieveOffersModel : RetrieveCatalogModel
{
public List<int> SelectedServiceIds { get; set; }
}
public class RetrieveProductsModel : RetrieveCatalogModel
{
public int ID { get; set; }
public string Name { get; set; }
public int Count { get; set; }
}
View
#model OrderServiceClient.Models.RetrieveAllModel
#{
ViewBag.Title = "Easy Order";
int productCount = 1;
string offers = "Offers";
}
#using (Html.BeginForm("ShowCatalog", "BrowseShopping"))
{
//since offers are not part of the dynamic product list, they need to be specifically identified
#offers<label> </label>
#Html.RadioButton("catalogName", "Offers", true, new { catalogName = "Offers", conversationid = Model.ConversationId })
<label> </label>
foreach (var type in Model.Products)
{
if (productCount > 0 && productCount % 5 == 0)
{
<br/>//break after every 5 products
}
#type.Name<label> </label>
#Html.RadioButton("catalogName", type.Name, new { catalogName = type.Name, conversationid = Model.ConversationId })
<label> </label>
productCount = productCount + 1;
}
}
...
<div class="row">
#{Html.RenderPartial("RetrieveCatalogs", Model.Offers.AvailableBrowseItems);}
</div>
Partial View
#model List<OrderServiceClient.Models.BrowseDataItemModel>
#if (Model != null)
{
<div class="col-lg-7 col-md-6 col-sm-12 offers-container" id="shoppingcatalog">
<table class="table table-striped">
<tr>
<th>Data Type</th>
<th>Name</th>
<th>Price</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr class="offerList">
<td>#item.DataType</td>
<td>#item.Name</td>
<td>#string.Format($"{item.Amount,0:C2}")</td>
<td><a class="addService" dataType="#item.DataType" serviceId="#item.ServiceId" serviceName="#item.Name" amount="#item.Amount">Add</a></td>
</tr>
}
</table>
</div>
}
Controller
public PartialViewResult ShowCatalog()
{
RetrieveCatalogModel rcm = new RetrieveCatalogModel();
rcm.AvailableBrowseItems = new List<BrowseDataItemModel>();
return PartialView("RetrieveCatalogs", rcm.AvailableBrowseItems);
}
[HttpPost]
public PartialViewResult ShowCatalog(string catalogName, Guid conversationid)
{
if (catalogName.Equals("Offers"))
{
RetrieveOffersModel offers = new RetrieveOffersModel();
var response = BrowseShoppingHelper.RetrieveOffers(conversationid, _client);
offers.AvailableBrowseItems = BuildOffersBrowseDataItemsModel(response).ToList();
return PartialView("RetrieveCatalogs", offers.AvailableBrowseItems);
}
else
{
var prodctFolderResponse = BrowseShoppingHelper.RetrieveProductFolders(conversationid, _client);
var output = (RetrieveProductFoldersCommandOutput) prodctFolderResponse.Body.Output;
RetrieveProductsModel rpm = new RetrieveProductsModel{Name = catalogName, AvailableBrowseItems = new List<BrowseDataItemModel>()};
foreach (var folder in output.Folders)
{
if (!catalogName.Equals(folder.Name)) continue;
var items = BuildProductBrowseItemsModel(
(RetrieveProductsInGroupCommandOutput) BrowseShoppingHelper
.RetrieveProductItems(conversationid, _client, folder).Body.Output);
rpm.AvailableBrowseItems.AddRange(items);
break;
}
return PartialView("RetrieveCatalogs", rpm.AvailableBrowseItems);
}
}
Script file
$(function() {
$("[name=catalogName]").on('change',
function () {
var $radio = $(this);
var myurl = "ShowCatalog?catalogName=" + $radio.val() + "&conversationid=" + $(this).attr('conversationid');
console.log("Catalog item is: " + $radio.val() + " and id is: " + $(this).attr('conversationid'));
$.ajax({
url: myurl,
type: 'POST',
success: function (data) {
$("#shoppingcatalog").html(data);
}
});
});
});

View Not Returning Multiple Lists in Asp.net MVC [duplicate]

This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Closed 5 years ago.
i am new to web from desktop.
i have two models.
first
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public double Price { get; set; }
public double Stock { get; set; }
public Category Category { get; set; }
public string ImagePath { get; set; }
}
and second is
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public bool isSelected { get; set; }
}
and a ViewModel for passing it to my view
public class ProductsVM
{
public IList<Item> items { get; set; }
public IList<Category> categories { get; set; }
}
and my controller action method looks like this
[HttpGet]
public ActionResult Products()
{
ViewBag.Message = "...Products...";
ProductsVM productsVm = new ProductsVM();
productsVm.items = db.Items.ToList();
productsVm.categories = db.Categories.ToList();
return View(productsVm);
}
[HttpPost]
public ActionResult Products(ProductsVM model)
{
ViewBag.Message = "...Categories...";
return View(model);
}
i have used it in my view like this
#using (Html.BeginForm())
{
<div class="row">
<div class="col-md-2">
#foreach (var it in Model.categories.ToList())
{
<div class="input-group">
#Html.CheckBoxFor(i => it.isSelected, new { Name = "ChkCategory", id = "ChkCategory"+it.Id, #class = "Categories" }) #it.Name
#Html.HiddenFor(i => it.Name)
</div>
}
</div>
#*Loading Items...*#
<div class="col-md-10">
#for (int i = 0; i < Model.items.Count() / 3; i++)
{
<div class="row">
#foreach (var item in Model.items.Skip(i * 3).Take(3))
{
<div class="col-md-4 col-sm-6 col-xs-12">
<img src="#Url.Content(item.ImagePath)" alt="#item.Description" class="thumbnail" />
</div>
}
</div>
}
</div>
</div>
<input type="submit" value="submit" />
}
#section scripts
{
<script src="~/Scripts/Products.js"></script>
}
i have tried all the ways to get my model back when i post the from to controller
i am posting the from on checkbox click event using ajax from my products.js file.
but in my controller action method it always show the ViewModel as null.
what should i do? am i doing something wrong.
Products.js
$(function () {
console.log('Inside js......');
$('.Categories').click(function (e) {
console.log(this.id, $("#" + this.id).is(":checked"));
$.ajax({
type: "POST",
url: "/Home/Products",
success: function () {
console.log("ajax successfull....");
},
error: function () {
console.log("ajax error....");
}
});
});
});
This is your ProductsVM:
public class ProductsVM
{
public IList<Item> items { get; set; }
public IList<Category> categories { get; set; }
}
This is your action method to which you are posting:
[HttpPost]
public ActionResult Products(ProductsVM model)
When you submit your form, it will take the values from your form's controls and using the names of the controls, it will post them to the Products action. In your view (form), you have a checkbox with the name chkCategory and a hidden input with the name Name. When you post your form, it will send chkCategory and its value, and the hidden item with the name Name. When it arrives on the server side, the MVC will look for an action method named Products in your controller. Then the default binder will try to look for chkCategory and Name properties to see if the action accepts them. It will not find it. Then it will try to see if it can create a ProductsVM and it cannot because ProductsVM has 2 properties: items and categories and they do not match what you are posting so it will just choose that action and pass it null.
You have many issues in your code and it is not playing nicely with the whole MVC framework. I suggest you read Understanding MVC Model Binding and try some simple examples to get a hang of it and then try what you are doing.

SignalR and Knockout viewmodel binding

I'am trying to display product list from database using signalr and knockout.js. But without any result. Could anyone tell me what I'am doing wrong or where I have mistake? I will be very grateful for helping me.
This is the view:
<div class="products">
<div class="row" data-bind="template: { name: 'productTemplate', foreach: products }">
</div>
<span class="messageClass" style="color: red;"></span>
</div>
<script type="text/html" id="productTemplate">
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<div class="caption">
<h3 data-bind="text: name"></h3>
</div>
</div>
</div>
</script>
This is the script:
<script>
$(function () {
function productViewModel(id, name) {
this.productId = id;
this.name = ko.observable(name);
var self = this;
}
function productListViewModel() {
this.hub = $.connection.voteHub;
this.products = ko.observableArray([]);
var products = this.products;
this.init = function () {
this.hub.server.getAllProducts();
}
this.hub.client.getAllProducts = function (allProducts) {
var mappedProducts = $.map(allProducts, function (item) {
return new productViewModel(item.productId, item.name)
});
products(mappedProducts);
}
}
var vm = new productListViewModel();
ko.applyBindings(vm);
$.connection.hub.start(function () {
vm.init();
});
});
</script>
Here is the hub method to get all products:
public void GetAllProducts()
{
VoteViewModel viewModel = new VoteViewModel();
viewModel.Products = ProductService.GetProducts(new GetProductsRequest()).Products.ToList();
if (viewModel.Products != null)
{
// TODO: pomyslec nad wysylaniem listy a nie tablicy!
Clients.All.getAllProducts(viewModel.Products.ToArray());
}
}
If I put on my hub code like this, it will work well (taken from demo app):
VoteViewModel vm = new VoteViewModel();
vm.Products = new List<Product>() { new Product() { Name = "Sample", Id = 1 } };
Clients.All.getAllProducts(vm.Products.ToArray());
My code which look like this don't work though. (i don't know why, maybe because my Product object from db, has more variables?):
VoteViewModel viewModel = new VoteViewModel();
viewModel.Products = ProductService.GetProducts(new GetProductsRequest()).Products.ToList();
Clients.All.getAllProducts(viewModel.Products.ToArray());
Here is code from my Product class: (dbcontext class)
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
[Required]
public string ImagePath { get; set; }
public virtual ICollection<Vote> Votes { get; set; }
I made new ProductViewModel class which looks like this:
public class ProductViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string ImagePath { get; set; }
public int VotesAmount { get; set; }
}
And then bind all data from db to that model, and then return List and IT WORKS NOW!, but I really don't understand why I can't just take list of products from database and send it to signalr client side (like I tried to do it before).
List<ProductViewModel> prods = new List<ProductViewModel>();
List<Product> products = ProductService.GetProducts(new GetProductsRequest()).Products.ToList();
foreach (var item in products)
{
ProductViewModel prod = new ProductViewModel()
{
Id = item.Id,
Name = item.Name,
Description = item.Description,
ImagePath = item.ImagePath,
VotesAmount = item.Votes.Count()
};
prods.Add(prod);
}
Clients.All.getAllProducts(prods.ToArray());
Your code is absolutely working fine. Please check if you have the referrence to the following files.
<script src="~/scripts/jquery.signalr-2.0.2.js" type="text/javascript"></script>
<script src="~/signalr/hubs"></script>
Signalr.hubs is the main reference which gives the javascripts proxy files. If you are facing any errors please let me know.
Next thing is the property name referred in the model object creation.
this.hub.client.getAllProducts = function (allProducts) {
var mappedProducts = $.map(allProducts, function (item) {
return new productViewModel(item.productId, item.name)
});
products(mappedProducts);
}
I have updated the property names to pascal case and worked for me.
return new productViewModel(item.ProductId, item.Name)

Resources