ASP.NET MVC 5 Table passing objects from View to Controller - c#

I'm still working on my asp.net app. I have a page where orders table is displayed and i would like to include "details"column, so someone can choose order and then look up it's details.
Here is my View code:
<table id="example" class="table table-striped table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
<th>ID</th>
<th>Seat</th>
<th>Movie</th>
<th>Date</th>
<th>Details</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.OrderList.results)
{
<tr>
<td>#item.objectId</td>
<td>#item.Seat</td>
<td>LOTR</td>
<td>#item.createdAt</td>
<td>Details</td>
</tr>
}
</tbody>
</table>
Ofcourse Url.Action is just for testing. Here is my controller method:
public ActionResult Details(OrderModel model)
{
return View(model);
}
Results is a List of OrderModel objects. I'd like to pass one OrderModel object that corresponds with chosen table row. The whole point is to display OrderModel object contents on Details page. Can someone explain me how to do that?
EDIT: My model:
OrderModel
public class OrderModel
{
/*class representing Order data*/
public string Seat { get; set; }
public string objectId { get; set; }
public DateTime? createdAt { get; set; }
public DateTime? updatedAt { get; set; }
}
My root for ordermodel(needed for json deserialization to list of objects)
public class OrderRootModel
{
public List<OrderModel> results { get; set; }
}
My baseviewmodel orderlist line(viewmodel is shared along all sites - i'm using shared layout):
public OrderRootModel OrderList { get; set; }
EDIT2:
Alright so after looking at my code i modified it, so Details page recieves BaseViewModel instead of ordermodel(i'm using shared layout).
BaseViewModel:
public class BaseViewModel
{
public OrderModel Order { get; set; }
public OrderRootModel OrderList { get; set; }
}
OrdersController:
public ActionResult Details(OrderModel order)
{
BaseViewModel model = new BaseViewModel();
model.Order = order;
return View(model);
}

Alright guys. I think i didn't get enough sleep so my thought process was a little bit off. As #user1672994 suggested i can just pass order id to details view(if i remember right passing whole object between view and controller is not recommended).
So if anyone is interested here is a solution:
View:
#foreach (var item in Model.OrderList.results)
{
<tr>
<td>#item.objectId</td>
<td>#item.Seat</td>
<td>LOTR</td>
<td>#item.createdAt</td>
<td>Details</td>
</tr>
}
Controller:
public ActionResult Details(string id)
{
ApiModel data = new ApiModel();
BaseViewModel model = new BaseViewModel();
model.Order = data.GetOrderData(id);
return View(model);
}
Model:
public OrderModel GetOrderData(string id)
{
OrderModel model = new OrderModel();
string url = "https://api.parse.com/1/classes/Orders" + "/" + id;
model = JsonConvert.DeserializeObject<OrderModel>(getParseIdData(url));
return model;
}
It works perfect. Thank you guys.

Related

MVC- Count Number of Records

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;

Simple sorting a table with help of C# (asp-net)

I have a question. I created a system where admin can add, edit or delete items (members of society in this case). I just need a sorting by year (top-bottom: from old to new) automatically without choices or buttons. I tried to run sorting with help of JavaScript, but it didn't work, unfortunately. It is sucessfully worked with data which was written with HTML, but, probably it doesn't work with data loaded from database which is my case. I read Microsoft tutorial, but didn't understand, honestly. Can you help me with automatic sorting by year? Thank You. All code is which downloads data from the database and shows it to the user is laid out below.
TeamController:
namespace Blog.Controllers {
public class TeamController : Controller {
private IRepository _repo;
public TeamController(IRepository repo)
{ _repo = repo; }
public IActionResult Index() {
var team = _repo.GetAllPlayers();
return View(team);
}
}
}
Player.cs in Model
namespace Blog.Models
{
public class Player {
public int Id { get; set; }
public string NickName { get; set; } = "";
public string Position { get; set; } = "";
public string MemberSince { get; set; } = "";
public string Category { get; set; } = "";
}
}
index.cshtml (Team)
#model IEnumerable<Player>
<div>
<table id="table">
<thead>
<tr>
<th scope="col">NickName</th>
<th scope="col">Position</th>
<th scope="col">Member since</th>
</tr>
</thead>
<tbody>
#foreach (var player in Model) {
#if (#player.Category == "Owner") {
<tr asp-controller="Team" asp-action="Player" asp-route-id="#player.Id">
<td data-label="NickName" id="nickname"> #player.NickName</td>
<td data-label="Position">#player.Position</td>
<td data-label="MemberSince">#player.MemberSince</td>
</tr>
}
}
</tbody>
</table>
</div>
Repository.cs
public Player GetPlayer(int id)
{ return _ctx.Team.FirstOrDefault(p => p.Id == id); }
public List<Player> GetAllPlayers()
{ return _ctx.Team.ToList(); }
IRepository.cs
Player GetPlayer(int id);
List<Player> GetAllPlayers();
Use orderby along with DateTime parsing.
public List<Player> GetAllPlayers()
{ return _ctx.Team.OrderBy(member => DateTime.Parse(member.MemberSince).Year).ToList(); }
You can use OrderByDesc if you want latest first.

Can not get the expected result in many to many relationship using LINQ in Asp.net C#, MVC, Codefirst application

I'm trying to develop an application using Asp.net C#, MVC, Codefirst approach.
I have two classes as Actors and Movies, which has many to many relationships. (An actor can have many movies, a movie can have many actors)
Now i'm facing a problem, I can retrieve data from both tables but not as expected, I believe something is going wrong at somewhere with the logic of my code.
For instance, I can retrieve a list of movies from database and when i click on each movie it redirects me to the page that belongs to that particular movie which makes sense up to this point, but now i want to retrieve the list of actors that has played role in this particular movie and here i fail. (I can retrieve the whole list of actors that exist in database but not the particular actors that has played role in a particular movie).
These are my models:
This is the Actor Class:
public class Actors
{
public int Id { get; set; }
public string Actor_Name { get; set; }
public string Country { get; set; }
public virtual ICollection<Movies> mvzz { get; set; }
}
And this is the movies class:
public class Movies
{
public int Id { get; set; }
public string Movie_title { get; set; }
public string genre { get; set; }
public virtual ICollection<Actors> actzz { get; set; }
}
This is the controller:
public ActionResult Index()
{
var mvz = _context.mvz;
return View(mvz);
}
public ActionResult Details(int? Id)
{
var movies_Detail = _context.mvz.Include(a=> a.actzz).SingleOrDefault(i=> i.Id==Id);
var actors = _context.act.ToList();
var ViewModel = new MoviesActorsViewModel()
{
Movies = movies_Detail,
Actors = actors
};
return View(ViewModel);
}
}
}
This is the Index View which shows the list of Movies and has a link for the details of each movie individually:
#model IEnumerable<mtmmmmmm.Models.Movies>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<table class="table table-bordered table-hover table-responsive">
#foreach (var mvz in Model)
{
<tbody>
<tr>
<td>#mvz.Id</td>
<td>#Html.ActionLink(mvz.Movie_title, "Details","Movies", new { Id = mvz.Id },null)</td>
</tr>
</tbody>
}
This is the the details view that has to shows the detailed information of of each movie, very particularly It has to show the list of Actors that has played role in that particular movie.
#model mtmmmmmm.ViewModel.MoviesActorsViewModel
#{
ViewBag.Title = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>The list of Actors that has played role in #Model.Movies.Movie_title</h2>
<table class="table table-bordered table-hover table-responsive">
#foreach (var actors in Model.Actors)
{
<tbody>
<tr>
<td>#actors.Id</td>
<td>#actors.Actor_Name</td>
<td>#actors.Country</td>
</tr>
</tbody>
}
And Finally this is the View Model:
public class MoviesActorsViewModel
{
public List<Actors> Actors { get; set; }
public Movies Movies { get; set; }
public MoviesActorsViewModel()
{
Actors = new List<Actors>();
Movies = new Movies();
}
}
I know that something is wrong with the LINQ logic that i'm writing to retrieve the list of actors in the controller class.
If anyone having expertise in this regard is reading this post, Kindly guide me with the correct logic that i should use for LINQ or any other apporach that helps me get the result.
Many thanks in advance for taking your time and reading this post.
I think you need to change
var actors = _context.act.ToList();
to
var actors = movies_Detail.actzz.ToList();

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.

Categories