MVC- Count Number of Records - c#

Edit My view is using the Employer model. Employer and JobPosting have a 1:M relationship. I will share more of the view for context.
Context: In my application, I want to show the Employer the number of applicants who applied for their JobPosting. The code that I currently have written is not returning any value. It's not throwing any errors- but it's not working either. I'm pretty sure the issue is in my controller, but I'll provide the Model and View as well.
Controller:
public ActionResult AppCount()
{
foreach (var app in db.JobPostings.ToList())
{
int id = app.JobPostingID;
int count= db.Applications.Where(a => a.JobPostingID == id).Count();
app.AppCount = count;
ViewBag.AppCount = count;
}
return View();
}
View:
#model InTurn_Model.Employer
.
.
.
<h2>My Job Postings</h2>
<p>
#Html.ActionLink("Create New", "Create", "JobPostings", null, null)
</p>
<div id="employeeContainer"></div>
<table class="table table-striped">
<tr>
<th>Position</th>
<th>Job Type</th>
<th>Number of Applicatiosn</th>
<th></th>
</tr>
#foreach (var item in Model.JobPostings)
{
if (item.EmployerID == Model.EmployerID)
{
<tr>
<td>
#Html.DisplayFor(model => item.Position)
</td>
<td>
#Html.DisplayFor(model => item.JobType)
</td>
<td>#ViewBag.AppCount</td>
<td>#Html.ActionLink("Details", "Details", "JobPostings", new { id = item.JobPostingID }, null) </td>
</tr>
}
}
</table>
Model:
[MetadataType(typeof(JobPostingMetaData))]
public partial class JobPosting
{
public int AppCount { get; set; }
private sealed class JobPostingMetaData
{
[Display(Name = "Job Posting ID")]
public int JobPostingID { get; set; }
[Display(Name = "Employer ID")]
public int EmployerID { get; set; }
[Display(Name = "Description")]
public string Desc { get; set; }
[Display(Name = "Job Type")]
public JobType JobType { get; set; }
[Display(Name = "Employment Type")]
public TimeType TimeType { get; set; }
[DataType(DataType.Currency)]
public decimal Wage { get; set; }
}
}

There are two problems that I see.
First, you are not passing Model from controller to view. However, you are iterating through Model.JobPostings. It is empty.
Second, you assign ViewBag.AppCount in the loop. So, all values, except for the last one are lost. But if you fix the first problem (use Model instead of ViewBag) - the second might go away by itself.

You need to specify the model in the view with #model:
#model YourNameSpace.JobPosting
Then return that model to the view:
public ActionResult AppCount()
{
foreach (var app in db.JobPostings.ToList())
{
int id = app.JobPostingID;
int count= db.Applications.Where(a => a.JobPostingID == id).Count();
app.AppCount = count;
ViewBag.AppCount = count;
}
return View(app);
}
This will make the values in the model available to the view. There is no need to use ViewBag, as AppCount is part of the model.

I was overthinking this. I just needed to set this up from the JobPosting model, and then the rest worked, I didn't need to iterate through the Controller at all.
public int AppCount => Applications.Count;

Related

Save checkbox list value Sql database in MVC5

I want to store fields and checkboxes in a database table in a form: The connection table contains the following fields:
connection table:
public partial class Connection
{
[Key]
public int ID { get; set; }
public string CommunicationName { get; set; }
public bool IsSelected { get; set; }
}
Register table:
public class RegisterForm
{
#region Ctor
public RegisterForm()
{
}
#endregion Ctor
#region Properties
[Key]
[Required]
public int ID { get; set; }
[Required(ErrorMessage = ("Required"))]
[StringLength(50, ErrorMessage = "This field must be a maximum of 50 characters")]
[TypeConverter("NVarchar(121)")]
[DisplayName("FullName")]
public string FullName { get; set; }
public string Email { get; set; }
public List<Connection> Communications { get; set; }
}
The values of the checkbox fields in the list are displayed using the following method:
questionForm.Communications = db.Connections.ToList<Connection>();
Now how to save the information in the post and save it to the register table. ????????? What changes should be Create to the update, delete operation in the register?
controller for register:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,FullName,PhoneNumber,Email,Communication,")]RegisterForm questionForm)
{
if (ModelState.IsValid)
{
db.Registers.Add(questionForm);
var data = db.SaveChanges();
return View("FormSuccessfullySubmitted");
}
return View(questionForm);
}
You should read about MVC model binding. Normally it could bound it without any problem. But lists are slightly different. You are to provide index of item in list. That is why it is better to use for, instead of foreach.
Check this view and grab it POSTed values to examine. Pay attention, that all list items are displayed using its index in list.
<table class="table">
#using (Html.BeginForm("Bind", "Bind", FormMethod.Post))
{
for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => Model[i].CommunicationName)
</td>
<td>
#Html.CheckBoxFor(modelItem => Model[i].IsSelected)
</td>
</tr>
}
<button type="submit">Submit</button>
}
</table>

no accessible extension method

The view is not able to get my GridData, not sure why.
The code pass the GridData in the view, but the view page is not able to access GridData object.
UserMaster Models:
namespace Project.Models
{
public class UserMaster
{
[Key]
public int UserId { get; set; }
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
}
public class UserMasterList
{
public List<UserMaster> GridData { get; set; }
}
}
Control:
UserMasterList userMasterList = new UserMasterList();
List<UserMaster> gl = new List<UserMaster>();
var userMasterListResult = _context.UserMaster.FromSql("EXECUTE [dbo].[UserMaster_Get] {0}", 0).ToList();
foreach (var data in userMasterListResult)
{
gl.Add(data);
}
userMasterList.GridData = gl;
return View(userMasterList);
View:
#model Project.Models.UserMaster
#foreach (var data in #Model.GridData) {
<tr>
<td>
#Html.DisplayFor(modelItem => data.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => data.LastName)
</td>
</tr>
}
Error:
The code pass the GridData in the view, but the view page is not able to access GridData object.
in view, you should have
#model Project.Models.UserMasterList
In your controller you are passing an object with type of UserMasterList, but in your view, model is type of UserMaster so that you should update used model in view as like as below:
#model Project.Models.UserMasterList

LINQ Repository & method return

I am new to C#, MVC, LINQ, Entity Framework, and everything else I'm doing. I have picked the stackoverflow brain-trust and other sites on this issue and do not see how to resolve it.
I am trying to implement the Repository pattern for a new application we are building and having problems returning the query results. The first and most pressing issue is that I am getting the error below, and the second is more a matter of figuring out how to handle empty results from the query.
For this issue, I am trying to get a list of requests from the database to be presented in the dashboard view. We have a working prototype that uses SQL queries, and I'm trying to replace it with repositories, which may be overkill, but it is something we feel we want to do.
Here is the view:
#using RAM.DAL.Models
#model RequestViewModel
#{
ViewBag.Title = "Dashboard";
}
<h1>Dashboard</h1>
<div class="col-md-4">
<h2>Resource Requests</h2>
<div class="panel">
<table class="table table-hover">
<thead>
<tr class="bg-primary">
<th>Number</th>
<th>Mission Title</th>
<th>Resource Requested</th>
<th>Person</th>
</tr>
</thead>
<tbody>
#if (Model.isEmpty)
{
<tr>
<td colspan="4">No requests pending</td>
</tr>
}
else
{
<tr onclick="location.href= '#Url.Action("Assignment", "Mission", new { id = Model.ID })'">
<td>#Model.ID</td>
<td>#Model.title</td>
<td>#Model.resourceTitle</td>
<td>#Model.userName</td>
</tr>
}
</tbody>
</table>
</div>
<!--<p><a class="btn btn-default" href="#">Content 1 Btn ยป</a></p>-->
</div>
Here is the ViewModel:
using System;
namespace RAM.DAL.Models
{
public class RequestViewModel
{
public int? ID { get; set; }
public string title { get; set; }
public string requestText { get; set; }
public string user_ID { get; set; } //The userID of the user being requested.
public string userName { get; set; } //Full name of the user being requested
public int? fromResourceID { get; set; } //The resource where the request was generated from
public int? toResourceID { get; set; } //The resource where the reassigned worker is requested to go to
public string resourceTitle { get; set; } //Title of the resource where the reassigned worker is requested to go to
public DateTime? requestDate { get; set; }//The date the request was made
public bool? isEmpty { get; set; }
}
}
And here is the repository up to the GetRequests method I'm having problems with (the rest is not implemented yet):
using RAM.DAL.Models;
using System;
using System.Linq;
using System.Data;
using System.Collections.Generic;
namespace RAM.DAL
{
public class RequestRepository : IRequestRepository<RequestViewModel>
{
private RAMcontext context;
public RequestRepository(RAMcontext context)
{
this.context = context;
}
public IEnumerable<RequestViewModel> GetRequests()
{
var requests = from r in context.RAM_Requests
join u in context.Users on r.user_ID equals u.User_ID
join res in context.RAM_Resources on r.toResourceID equals res.ID
where r.resolved == false
select new RequestViewModel()
{
title = r.title,
ID = r.ID,
fromResourceID = r.fromResourceID,
toResourceID = r.toResourceID,
user_ID = r.user_ID,
userName = u.First_Name + " " + u.Last_Name,
resourceTitle = res.title,
requestText = r.requestText,
requestDate = r.requestDate
};
/* }
catch
{
RequestViewModel empty = new RequestViewModel
{
isEmpty = true
};
return empty;
}*/
return requests.ToList().AsEnumerable();
}
The error I'm getting is:
The model item passed into the dictionary is of type
'System.Collections.Generic.List`1[RAM.DAL.Models.RequestViewModel]',
but this dictionary requires a model item of type
'RAM.DAL.Models.RequestViewModel'.
From the error message, I guess your action method is sending a collection of RequestViewModel to the view. But your view is strongly typed to a single instance of RequestViewModel , not a collection. That is the reason you are getting this error.
Since you want to show a collection of requests, you should change the view to be strongly typed to a collection. You can use the LINQ Any() method to determine whether you have more than one item in the collection passed to the view and show/hide a message/ table to display the data.
#model IEnumerable<RequestViewModel>
<h1>Dashboard</h1>
#if(!Model.Any())
{
<p>No records found </p>
}
else
{
<table>
<tr>
<th>Title</th>
<th>User name </th>
</tr>
#foreach(var req in Model)
{
<tr>
<td>#req.title</td>
<td>#req.userName</td>
</tr>
}
</table>
}

Two queries, one view

The goal
Iterating between two queries within a single view.
The problem
In my application there is a comparison list of a specific product. At the top of the page, there is details of this product as its name, min/max price, photo and some other details.
What I need is something like this:
#modelComparisonList List<MyApp.Models.Products>
#modelProduct MyApp.Models.Products
#{
ViewBag.Title = "Comparing " + modelProduct.name;
}
<h1>There is #modelProduct.quantity products to compare</h1>
<table>
#foreach (var item in modelComparisonList)
{
<tr>
<p>#item.productName</p>
</tr>
<tr>
<p>#item.productPrice</p>
</tr>
<tr>
<p>#item.marketName</p>
</tr>
}
</table>
Can you understand my case?
I don't know how to perform a solution to resolve this. Can someone give me an idea?
Just make a wrapper class that contains both, ie simply:
public class TheViewModel
{
public List<MyApp.Models.Products> Item1 { get; set; }
public MyApp.Models.Products Item2 { get; set; }
}
Yes you can do it by using a view model. View models are there to represent your data on the view. Your view model can be a "concatenation" from multiple models.
Below is a couple of tips as well regarding your classes and properties.
Your product domain model will look like this:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string MarketName { get; set; }
public decimal Price { get; set; }
// Other properties not mentioned above
}
Your view model could look something like this:
public class ProductViewModel
{
public IEnumerable<Product> Products { get; set; }
public Product Product { get; set; }
}
Your action method could look something like this:
public ActionResult Compare(int id)
{
ProductViewModel viewModel = new ProductViewModel
{
Product = productRepository.GetBuId(id),
Products = productRepository.GetAll()
};
return View(viewModel);
}
And your view could look something like this:
#model YourProject.ViewModels.Products.ProductViewModel
#{
ViewBag.Title = "Comparing " + #Model.Product.Name;
}
<h1>There is #Model.Product.Quantity products to compare</h1>
<table>
#foreach (var product in Model.Products)
{
<tr>
<td>#product.Name</td>
</tr>
<tr>
<td>#product.Price</td>
</tr>
<tr>
<td>#product.MarketName</td>
</tr>
}
</table>
I hope this helps.

asp.net mvc binding between the model and the view

I am new to asp.net mvc . This is how my model looks like:
[Bind(Exclude = "JournalId")]
public class Journal
{
[ScaffoldColumn(false)]
public int JournalId { get; set; }
[DisplayName("Customer")]
public int CustomerId { get; set; }
[DisplayName("Till")]
public int TillId { get; set; }
[Required(ErrorMessage = "A Journal name is required")]
[StringLength(160)]
public string Name { get; set; }
[DisplayName("Journal creation date")]
public DateTime Date { get; set; }
[DisplayName("Journal creation time")]
public DateTime Time { get; set; }
public virtual Customer Customer { get; set; }
public virtual Till Till { get; set; }
}
[Bind(Exclude = "CustomerId")]
public class Customer
{
[ScaffoldColumn(false)]
public int CustomerId { get; set; }
[Required(ErrorMessage = "A customer name is required")]
[StringLength(160)]
public string Name { get; set; }
[StringLength(250)]
public string Address { get; set; }
}
[Bind(Exclude = "TillId")]
public class Till
{
[ScaffoldColumn(false)]
public int TillId { get; set; }
[Required(ErrorMessage = "A till no is required")]
[StringLength(160)]
public string TillNo { get; set; }
[StringLength(100)]
public string TillOperator { get; set; }
}
This is how my one of my controller's action is defined:
public ViewResult Index()
{
var journals = db.Journals.AsEnumerable<Journal>();
ViewData["journals"] = journals;
return View();
}
and the view :
#model IEnumerable<ErikDemo.Models.Journal>
#foreach (var item in (IEnumerable<ErikDemo.Models.Journal>)ViewData["journals"]) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Customer.Name)
</td>
<td>
#Truncate(item.Till.TillNo, 25)
</td>
<td>
#Truncate(item.Name, 25)
</td>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.Time)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.JournalId }) |
#Html.ActionLink("Details", "Details", new { id=item.JournalId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.JournalId })
</td>
</tr>
Although when I am debugging I can see in the controller that the list passed to the View is not empty, and also I see that the ViewData["journals"].Local in a watch is not empty, nothing gets displayed. I have also used the View.Model and return View(journals.ToList()) to send data to the View, but nothing seems to work. What is the issue here? Been on that half a day.
This is wrong: (Well it can be done like this, but I think you want to pass a model)
public ViewResult Index()
{
var journals = db.Journals.AsEnumerable<Journal>();
ViewData["journals"] = journals;
return View();
}
Try this:
public ViewResult Index()
{
var journals = db.Journals.AsEnumerable<Journal>();
return View(journals); //You just passed journals as a model
}
Also if you are using mvc 3 you can use ViewBag instead of ViewData
Example:
ViewData["Journal"] = "my string";
is the same as
ViewBag.Journal = "my string";
The ViewBag is dynamic, so you can use dot notation.
Additionally
This code:
#model IEnumerable<ErikDemo.Models.Journal>
#foreach (var item in (IEnumerable<ErikDemo.Models.Journal>)ViewData["journals"])
Should be like this:
#model IEnumerable<ErikDemo.Models.Journal>
#foreach (var item in Model)
Update:
I'm not sure what you're doing with this db.Journals.AsEnumerable<Journal>();
You should have a method somewhere that gets data from a table or table(s) and returns Journals. So lets say this all comes from one table in a database:
public class JournalViewModel
{
public IEnumerable<Journals> GetJournals()
{
using(var db = new ErikDataContext())
{
return db.Journals.ToList();
}
}
}
Then in the action:
public ViewResult Index()
{
var journals = new JournalsViewModel.GetJournals();
return View(journals); //You just passed journals as a model
}
Did you forget the <table> tag? If you haven't viewed the source of your page as it is rendered, I would recommend that you do this as a next step.

Categories