Sorry I didn't really know how to title this.
I have a webpage that displays announcements. What I cant seemed to figure out is whether there are any announcements, if there are display saying "There are no announcements".
I've tried stuff like:
if(db.Announcements.toArray().length == 0){
return View(null);
}
but that doesn't work. Where do I deal with things like these? View/Controller?
View:
#model IEnumerable<Remake.Models.Announcement>
#{
ViewBag.Title = "Announcements";
}
<h2>Announcements</h2>
#if (User.Identity.IsAuthenticated)
{ <p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
<b> #Html.DisplayNameFor(model => model.Title)</b>
</th>
<th>
#Html.DisplayNameFor(model => model.Content)
</th>
<th width="10%">
#Html.DisplayName("Date")
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
<b> #Html.DisplayFor(modelItem => item.Title)</b>
</td>
<td>
#Html.DisplayFor(modelItem => item.Content)
</td>
<td>
<b>#Html.DisplayFor(modelItem => item.PostDate)</b>
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.AnnouncementId }) |
#Html.ActionLink("Comments", "Details", new { id = item.AnnouncementId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.AnnouncementId })
</td>
</tr>
}
</table>
}
else
{
<p>Please sign in to create an Announcement</p>
}
Controller:
// GET: Announcements
public ActionResult Index()
{
return View(db.Announcements.ToList());
}
Since your model is defined as IEnumerable<Announcement>, you can simply use Any() to check whether it's empty or not:
#if (Model.Any())
{
// show announcements
foreach (var item in Model)
{
// ...
}
}
else
{
// show message when empty
<p>No announcements</p>
}
See MSDN
Related
I have a usual grid which has edit and save button. When I click the Edit link from the grid it goes to Edit action method, where I can read the Id as a parameter. I am thinking since I can pass the Id then why not the whole model as a parameter to the Edit action? However, I am always getting null. I looked at some examples they all shows passing the id rather than the model object. I wonder why model cannot be passed? Even though when I debug the code I always see item row is binding with the parameter Student from item.
View for Grid with Edit link:
#model IEnumerable<MVC_BasicTutorials.Models.Student>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.StudentName)
</th>
<th>
#Html.DisplayNameFor(model => model.Age)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.StudentName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Age)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.StudentId, std=item }) |
</td>
</tr>
}
</table>
Controller action method:
// Get
public ActionResult Edit(int Id, Student std)
{
var checkSet=std; // coming null
var checkId=Id; //i am seeing the id value
return RedirectToAction("Index");
}
Try the following:
public ActionResult Index()
{
var model = /* prepare view data model */;
return View(model);
}
[HttpPost]
// The second parameter `Id` is removed because of the `Student` already contains it.
public ActionResult Edit(Student std)
{
System.Diagnostics.Debug.WriteLine($"Id= {std.StudentId}, Student Name= {std.StudentName} ");
return RedirectToAction("Index");
}
In the Index.cshtml you can use the Html.BeginForm helper method to specify that the target of the form is the 'Edit' action method.
#model IEnumerable<MVC_BasicTutorials.Models.Student>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.StudentName)
</th>
<th>
#Html.DisplayNameFor(model => model.Age)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
using (Html.BeginForm("Edit", "Home"))
{
#* Prepare a hidden data context to the able the MVC data binding work correctly *#
#Html.Hidden("StudentId", item.StudentId)
#Html.Hidden("StudentName", item.StudentName)
#Html.Hidden("Age", item.Age)
<tr>
<td>
#Html.DisplayFor(modelItem => item.StudentName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Age)
</td>
<td>
#*#Html.ActionLink("Edit", "Edit", new { id = item.StudentId, std = item }) *#
<input type="submit" value="Edit" />
</td>
</tr>
}
}
</table>
I have looked all over and found a number of solutions none of which have given the specific result that I want. I must be missing something obvious!
I am trying to get the list of a users current roles (stored in mysql db) and list show those in the same table as the list of users, below is all I can manage to get to work, a list of all roles that all users are in, not specific to each user. The User to UserRoles is a many-to-many relationship and as such the UseRoles_has_Users table was generated
Usertable
I have created a separate model for the admin index page
Model
namespace ComputerAidedDispatch.Models
{
public class AdminIndex : UserMetaData
{
public IEnumerable<User> AdminUsers { get; set; }
public IEnumerable<UserRoles_has_Users> AdminUserRoles { get; set; }
}
}
Controller
public ActionResult Index(string searchString)
{
var users = from u in db.Users
select u;
var userRoles = from r in db.UserRoles_has_Users
select r;
var adminIndex = new AdminIndex();
adminIndex.AdminUsers = users;
adminIndex.AdminUserRoles = userRoles;
if (!String.IsNullOrEmpty(searchString))
{
adminIndex.AdminUsers = adminIndex.AdminUsers.Where(s => s.username.Contains(searchString));
}
return View(adminIndex);
}
View
#model ComputerAidedDispatch.Models.AdminIndex
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
#using (Html.BeginForm())
{
<p>
User: #Html.TextBox("SearchString")
<input type="submit" value="Search!" class="btn btn-default" />
</p>
}
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.username)
</th>
<th>
#Html.DisplayNameFor(model => model.firstName)
</th>
<th>
#Html.DisplayNameFor(model => model.lastName)
</th>
<th>
#Html.DisplayNameFor(model => model.email)
</th>
<th>
#Html.DisplayNameFor(model => model.loginAttempts)
</th>
<th>
#Html.DisplayNameFor(model => model.accountBanned)
</th>
<th>
#Html.DisplayName("Roles")
</th>
<th>
#Html.DisplayName("Actions")
</th>
<th></th>
</tr>
#foreach (var item in Model.AdminUsers.ToArray())
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.username)
</td>
<td>
#Html.DisplayFor(modelItem => item.firstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.lastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.email)
</td>
<td>
#Html.DisplayFor(modelItem => item.loginAttempts)
</td>
<td>
#Html.DisplayFor(modelItem => item.accountBanned)
</td>
<td>
#foreach(var role in Model.AdminUserRoles)
{
var userRole = role.UserRoles_roleName;
#Html.DisplayFor(modelItem => userRole)
}
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.userId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.userId })
</td>
</tr>
}
</table>
I feel like the .ToArray() in the line
Model.AdminUsers.ToArray()
Could be part of the problem, but that stopped me getting the exception
MySqlException: There is already an open DataReader associated with this Connection which must be closed first.
I'm out of ideas so any help or suggestions greatly appreciated!
Thanks in advance!
Replace this section of your code in your controller:
var users = from u in db.Users
select u;
to be the following:
var users = db.Users.Include(u => u.UserRoles_has_Users.Select(s => s.Role)).ToList();
Then in your view you can do the following:
#foreach (var item in Model.AdminUsers.ToArray())
{
<tr>
//... other stuff
#foreach(var role in item.UserRoles_has_Users)
{
var userRole = role.UserRoles_roleName;
#Html.DisplayFor(modelItem => userRole)
}
//.... other stuff
}
The key here is that you want to loop over the roles in the item not in the role.
Note: the names of your properties may vary, if you include your Entity classes I can correct those.
I had this code and it worked fine:
#model IEnumerable<Moviestore.Models.Movie>
#{
ViewBag.Title = "Index";
}
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
#Html.DisplayNameFor(model => model.Genre)
</th>
<th>
#Html.DisplayNameFor(model => model.Author)
</th>
<th>
#Html.DisplayNameFor(model => model.Year)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
if (item.IsDeleted == 0)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
#Html.DisplayFor(modelItem => item.Author)
</td>
<td>
#Html.DisplayFor(modelItem => item.Year)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.MovieID }) |
#Html.ActionLink("Details", "Details", new { id = item.MovieID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.MovieID })
</td>
</tr>
}
}
</table>
But I needed to add one more model, I done that with Tuple In this way:
#using Moviestore.Models;
#model Tuple<Movie, User>
#{
ViewBag.Title = "Index";
}
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(tuple => tuple.Item1.Title)
</th>
<th>
#Html.DisplayNameFor(tuple => tuple.Item1.Genre)
</th>
<th>
#Html.DisplayNameFor(tuple => tuple.Item1.Author)
</th>
<th>
#Html.DisplayNameFor(tuple => tuple.Item1.Year)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
if (item.IsDeleted == 0)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
#Html.DisplayFor(modelItem => item.Author)
</td>
<td>
#Html.DisplayFor(modelItem => item.Year)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.MovieID }) |
#Html.ActionLink("Details", "Details", new { id = item.MovieID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.MovieID })
</td>
</tr>
}
}
</table>
But now I have problem with bottom half of code.
From #foreach
I don't know what I need to put instead of #foreach (var item in Model)
And will then #Html.DisplayFor(modelItem => item.Title) also need some changes.
Sorry for long post, I tried to explain the problem as best as I can.
As I mentioned in the comments, the appropriate way to handle this situation (needing more than one model on a particular View page) is to use a ViewModel which contains the models you need (see here for reference).
To answer your specific question, though, you can access each item of the Tuple by its position, e.g. if your model is Tuple<Movie, User>, then you can access the Movie object by model.Item1 and the User object by model.Item2, etc.
But I strongly recommend you take the ViewModel approach that I linked instead.
Hi here is the viewmodel for your requirement:
public class MovieUserViewModel
{
public IEnumerable<Movie> Movie { get; set; }
public IEnumerable<Users> Users { get; set; }
}
With the above viewmodel , you can easily access each class
#foreach (var item in Model.Movie)
#foreach (var item in Model.Users)
Additional info : Understanding ViewModel in ASP.NET MVC
Thanks
Karthik
I`ve made a simple method to count how many Albums do I have in a table, my only question is simple, I want to show the result of the Count method in the AlbumIndex view. Lets say I want to show a label: "Total" and the number besides it, how do I do this in the View?
This is the method(inside a class called Operations, separated from Controllers and Models):
public int AlbumCounter()
{
int x = db.Albums.Count();
return x;
}
This is the ActionResult Method in my AlbumsController(I don`t know what to do, I want to show the result in the Index View)
public ActionResult AlbumCounter()
{
return
}
and here is the Index View:
#model IEnumerable<AlexMusicStore.Models.Album>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Artist.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.AlbumName)
</th>
<th>
#Html.DisplayNameFor(model => model.DateCreated)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Artist.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.AlbumName)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateCreated)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.AlbumID }) |
#Html.ActionLink("Details", "Details", new { id=item.AlbumID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.AlbumID })
</td>
</tr>
}
</table>
I would like to display the total amount (#totalAmount) from the index and show it on the payment page which is the next page. I am trying to use a viewbag but it doesn't seem to work.
This is my index...
#model IEnumerable<charity.Models.Donation>
#{
ViewBag.Title = "Index";
ViewBag.total = "#totalAmount";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.DisplayName)
</th>
<th>
#Html.DisplayNameFor(model => model.Date)
</th>
<th>
#Html.DisplayNameFor(model => model.Amount)
</th>
<th>
#Html.DisplayNameFor(model => model.TaxBonus)
</th>
<th>
#Html.DisplayNameFor(model => model.Comment)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.DisplayName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.Amount)
</td>
<td>
#Html.DisplayFor(modelItem => item.TaxBonus)
</td>
<td>
#Html.DisplayFor(modelItem => item.Comment)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
#{
Decimal totalAmount = 0;
if (Model != null)
{
totalAmount = Model.Sum(x => x.Amount);
}
<label>Total amount donated</label>
<h1 id="amount">#totalAmount</h1>
}
#{
Decimal totaltax = 0;
if (Model != null)
{
totaltax = Model.Sum(x => x.TaxBonus);
}
<label>Total tax bonus</label>
<h1 name="amount">#totaltax</h1>
}
This is my payment page...
#{
ViewBag.Title = "Payment";
}
<h2>Payment</h2>
<form>
<h1>#ViewBag.total</h1>
</form>
Index and payment code from the controller...
public ActionResult Index()
{
return View(db.Donations.ToList());
}
public ActionResult Payment() {
return View();
}
Try to use a Session Variable instead of your ViewBag.
It will store the total as an int.
Session["totalAmount"] = Model.Sum(x => x.Amount);