So my Index view renders the view called StudentWellnessReviews retrieves reviews from the dbo.Review Table. Everything was working until I tried to setup pagination for the StudentWellnessReviews view in the ReviewsController. The error was:
Only one 'model' statement is allowed in a file.
ReviewsController
public class ReviewsController : Controller
{
private SizaData_1Entities db = new SizaData_1Entities();
// GET: Reviews
public ActionResult Index()
{
return View();
}
//Student Wellness Reviews
public ActionResult StudentWellnessReviews(int page = 1, int pageSize = 4)
{
using (var context = new SizaData_1Entities())
{
List<Review> listReviews = context.Reviews.SqlQuery("select * from dbo.Review where WellnessService='Student Wellness Service'").ToList();
PagedList<Review> userreview = new PagedList<Review>(listReviews, page, pageSize);
return View(userreview);
}
}
StudentWellnessReviews View:
#model IEnumerable<Siza.Models.Review>
#{
ViewBag.Title = "Index";
Layout = "";
}
#model PagedList.IPagedList<Siza.Models.Review>
#using PagedList.Mvc;
<table class="table text-center width:50%">
#foreach (var item in Model)
{
<tr>
<td>
<h5>Username</h5>
</td>
<td>
<p>
<div align="left">#Html.DisplayFor(modelItem => item.Username)</div>
</p>
</td>
</tr>
<tr>
<td>
<h5>Wellness Service</h5>
</td>
<td>
<p>
<div align="left">#Html.DisplayFor(modelItem => item.WellnessService)</div>
</p>
</td>
</tr>
<tr>
<td>
<h5>Rating</h5>
</td>
<td>
<p>
<div align="left">#Html.DisplayFor(modelItem => item.Rating)</div>
</p>
</td>
</tr>
<tr>
<td>
<h5>Feedback</h5>
</td>
<td>
<p>
<div align="left"> #Html.TextAreaFor(modelItem => item.Feedback, new {#readonly = true})</div>
</p>
</td>
</tr>
<tr>
<td>
<h5>Date Created</h5>
</td>
<td>
<p>
<div align="left"> #Html.DisplayFor(modelItem => item.Date)</div>
</p>
</td>
</tr>
<tr><td colspan="2"><hr class="active"/></td></tr>
}
#Html.PagedListPager(Model, Page => Url.Action("StudentWellnessReviews",
new { Page, pageSize = Model.PageSize} ))
Showing #Model.FirstItemOnPage to #Model.LastItemOnPage of #Model.TotalItemCount Reviews
</table>
Part of Index view
#using Siza.Controllers
#{
ViewBag.Title = "Index";
}
#{Html.RenderAction("StudentWellnessReviews", "Reviews");}
Assistance would be greatly appreciated.
The problem is you cannot define model for your View multiple times, right n ow you are saying that your view is strongly typed with both IEnumerable<Siza.Models.Review> and PagedList.IPagedList<Siza.Models.Review> which cannot be, so what i see is you just need PagedList.IPagedList<Siza.Models.Review> so remove the top line where you are setting model to IEnumerable<Siza.Models.Review> to be like:
#model PagedList.IPagedList<Siza.Models.Review>
#using PagedList.Mvc;
#{
ViewBag.Title = "Index";
Layout = "";
}
.................
Your rest view
Related
I am quite new to ASP.NET with razor, I think I may have gotten a concept wrong.
All I am doing is instantiating my model, letting it retrieve data from the local db and returning it to the view.
The code is working fine, but when I put a stop point into the beginning of the GET it runs into that stoppoint literally hundreds of times before coming to a result.
This of course impacts performance massively.
Let me show you what I have done (briefly):
My controller has one ref to the model:
public class GlobalTaggingController : BaseCmsEditorController
{
public GlobalTaggingViewModel model = new GlobalTaggingViewModel();
public ActionResult Index(string searchword = "")
{
return View(model);
}
// ... cut for brevity
}
The viewmodel looks like that:
public class GlobalTaggingViewModel : BaseViewModel
{
public List<NodeModel> MainNodes
{
get
{
var globalTaggingLocalizedManager = new GlobalTaggingLocalizationManager();
var manager = new GlobalTaggingManager();
var mainlevel = manager.GetAllItemsOnLevel(0);
var subLevel = manager.GetAllItemsOnLevel(1);
var subsubLevel = manager.GetAllItemsOnLevel(2);
var resMainCat = new List<NodeModel>();
// ... cut for brevity
}
}
}
This is my view (which is very long and has many loops):
#model Application.Areas.Administration.Models.GlobalTaggingViewModel
#{
ViewBag.Title = "Administration - Video";
var positionNr = 0;
}
<form action="#Url.Action("Index")" method="POST" id="mainForm">
<div class="divHeader Administration">
<div class="divHeaderInner">
for (int i = 0; i < Model.MainNodes.Count(); i++)
{
string catId = "CatId" + i.ToString();
string classToHideCatId = "classToHideCatId" + i.ToString();
string rowCounter = "rowCounter" + i.ToString();
<tr class="mainCatRow">
<td>
<table class="mytable">
<thead>
</thead>
<tr class="#rowCounter rowHeight">
<td class="column0">
<div>
<img src="#Url.Content("~/Content/images/icons/icon-open.png")" id="#catId" class="buttonLayoutMain" />
</div>
</td>
<td class="column1">
<table class="tableInCol1">
<tr>
<td class="editButtonClassLeft">
<div class="mainCat">
#Model.MainNodes[i].name
</div>
</td>
<td class="editButtonClassRight">
<div>
<a onclick="javascript:Base.Popup.Open('#Url.Action("Index", "GlobalTaggingEditor", new {area = "Cms", id = Model.MainNodes[i].Id})', 1236, 800); return false;" href="#" class="ButtonEdit"><span class="mif-pencil"></span></a>
</div>
</td>
</tr>
</table>
<td>
<td>
<div class="mainCat mainCol">
#Model.MainNodes[i].nameEng
</div>
<td>
<td>
<div class="mainCat mainCol">
#Model.MainNodes[i].name
</div>
<td>
<td>
<div class="mainCat mainCol">
#Model.MainNodes[i].nameSpanisch
</div>
<td>
<td>
<div class="mainCat mainCol">
#Model.MainNodes[i].nameFra
</div>
<td>
<td>
<div class="mainCat mainCol">
#Model.MainNodes[i].namePort
</div>
<td>
<td>
<div class="mainCat mainCol">
#Model.MainNodes[i].nameRuss
</div>
<td class="column9">
Again this is working code, but it is called over and over and over again.
Did I maybe set something up wrong?
EDIT:
Going through my code in single steps, I found out that my model is recreated again once I am going through the razor page.
Specifically here:
<td class="column1">
<table class="tableInCol1">
<tr>
<td class="editButtonClassLeft">
<div class="mainCat">
#Model.MainNodes[i].name
</div>
</td>
<td class="editButtonClassRight">
<div>
<a onclick="javascript:Base.Popup.Open('#Url.Action("Index", "GlobalTaggingEditor", new {area = "Cms", id = Model.MainNodes[i].Id})', 1236, 800); return false;" href="#" class="ButtonEdit"><span class="mif-pencil"></span></a>
</div>
</td>
</tr>
</table>
Why would that start the model over again?
Ok, so as I put everything inside the GET of the model, intead of doing it over a constructor, I was able to get around this issue.
I have a index page the code looks like this
#model PagedList.IPagedList<PartialViews.Models.Customer>
#using PagedList.Mvc
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<div class="container">
<table class="table">
<tr>
<th>
Title
</th>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Email Address
</th>
<th>
Phone Number
</th>
<th>
Modified Date
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmailAddress)
</td>
<td>
#Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
#Html.DisplayFor(modelItem => item.ModifiedDate)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.CustomerID }) |
#Html.ActionLink("Details", "Details", new { id = item.CustomerID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.CustomerID })
</td>
</tr>
}
</table>
#Html.PagedListPager(Model,page=>Url.Action("Index",new{page,pageSize=Model.PageSize}))
</div>
My CustomersController has this code
private AdventureWorksLT2012Entities db = new AdventureWorksLT2012Entities();
// GET: Customers
public ActionResult Index(int page=1, int pageSize=10)
{
List<Customer> customers = db.Customers.ToList();
PagedList<Customer> cust = new PagedList<Customer>(customers,page,pageSize);
return View(cust);
//return View(db.Customers.ToList());
}
Heres the Main page where i want the Customers List from the Index action to be shown
#model PartialViews.Models.Customer
#{
ViewBag.Title = "Main";
}
<body>
<div class="container">
<h2>Customer's List</h2>
<div id="dvCustomerDetails" style="width: 50%; height: 130px;display: none"></div>
</div>
</body>
<script type="text/javascript">
$.ajax({
url: 'Customers/Index',
contentType: 'application/html;',
type: 'GET',
dataType:'html'
})
.success(function(result) {
$('#dvCustomerDetails').html(result);
})
</script>
I want to display this table onto a new page as a partial view using ajax jquery but I am having trouble implementing it.
I was able to use RenderPartial method to display it as a partial view but i am having trouble doing it with ajax. Any help or suggestion will be appreciated.
I am using the following code:
Controller:
public ActionResult Update(int studentId = 0, int subjectId = 0)
{
Engine engine = new Engine(studentId, subjectId);
List<Chapter> chapterList = engine.GetChapters();
return View(chapterList);
}
[HttpPost]
public ActionResult Update(List<Chapter> model)
{
return View(model);
}
Update.cshtml:
#model IEnumerable<Chapter>
#{
ViewBag.Title = "Update";
}
<h2>
Update</h2>
#using (Html.BeginForm("Update", "StudyPlan", FormMethod.Post))
{
<fieldset>
<table>
#foreach (var item in Model)
{
<tr>
<td>
#item.name
</td>
<td>
#Html.CheckBoxFor(chapterItem => item.included)
</td>
</tr>
}
</table>
<input type="submit" value="submit" />
</fieldset>
}
I want when a user selects checkboxes, the response should come in httppost method of controller. But I am getting null value Update method. Am I doing something wrong
You need to use for instead of foreach. In that case checkbox will be rendered as
<input type='checkbox' name='Model[0].included'/>
<input type='checkbox' name='Model[1].included'/>
...
and then ModelBinder will successfully create model
Example:
#model List<Chapter>
#{
ViewBag.Title = "Update";
}
<h2>
Update</h2>
#using (Html.BeginForm("Update", "StudyPlan", FormMethod.Post))
{
<fieldset>
<table>
#for (int i =0;i<Model.Count;i++)
{
<tr>
<td>
#Model[i].name
</td>
<td>
#Html.CheckBoxFor(chapterItem => Model[i].included)
</td>
</tr>
}
</table>
<input type="submit" value="submit" />
</fieldset>
}
PS. in that example Model changed to List<> from IEnumerable
It happens because MVC analyze expression in CheckBoxFor method. And it this expression is array accessor, then it generates different control name. And based on Name ModelBinder successfully creates List<>
As Sergey suggested, use a for loop, but try this:
#for (int i =0;i<Model.Count;i++)
{
<tr>
<td>
#Html.HiddenFor(m => m[i].id)
#Html.DisplayFor(m => m[i].name)
</td>
<td>
#Html.CheckBoxFor(m => m[i].included)
</td>
</tr>
}
I have a list of transactions. When I click one of them, I'd like to be able to display the edit form (populated with the selected item's data) to the right of the list. Any ideas?
Below is the partial view that displays the list of transactions.
#model IEnumerable<BudgetPlus.Models.Transaction>
#{
ViewBag.Title = "Index";
}
<p>
#Html.ActionLink("Create New", "Create", null, new { #class = "button-link" })
</p>
<table>
<thead>
<tr>
<th class="column-Date">Date</th>
<th class="column-Description">Description</th>
<th class="column-Category">Category</th>
<th class="column-Amount">Amount</th>
<th class="action-button"></th>
<th class="action-button"></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.Category.DisplayName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Amount)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id })
</td>
<td>
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</tbody>
</table>
<div>
#Html.EditorForModel("Edit")
</div>
And this is what the edit method in my TransactionController looks like.
public ActionResult Edit(int id)
{
Transaction transaction = db.Transactions.Find(id);
ViewBag.CategoryId = new SelectList(db.Categories, "Id", "DisplayName", transaction.CategoryId);
return View(transaction);
}
Probably the easiest way to achieve this is to use Ajax.Actionlink helper.
In your for loop have this instead of Html.Actionlink:
#Ajax.ActionLink("Edit", "Edit", new { id=item.Id }, new AjaxOptions { UpdateTargetId = "editor", HttpMethod = "Get", InsertionMode = InsertionMode.Replace });
And on the right side of your table:
<div id="editor"></div>
Then have a partial view for editing the Transaction, which will be rendered into the div with id "editor". You are using EditorForModel helper so I assume you have a partial view for editing already.
In your actionmethod return the partial view instead:
return PartialView("YourPartialView", transaction);
My application needs to do an HTTP post of a table with checkboxes . On the controller side I will need to traverse the table and perform certain operations for each row that was checked.
The things that I need to do are:
Identify whether a row is checked
Here is my code:
view :
#model IEnumerable<LinqToTwitter.User>
#{
ViewBag.Title = "Page d'accueil";
}
<h2>Twitter</h2>
<table>
<tr>
<td>
<input id="Checkbox1" type="checkbox" />
</td>
</tr>
#foreach (var tweet in Model)
{
<tr>
<td>
<input id="rowIDs" type="checkbox" />
</td>
<td>
<img alt="" src="#tweet.ProfileImageUrl" />
</td>
<td>
<strong>#tweet.Name</strong>
<br />
Friends: <strong>#tweet.FriendsCount</strong>
</td>
</tr>
}
</table>
controller :
{.....
string nextCursor = "-1";
List<LinqToTwitter.User> result = new List<LinqToTwitter.User>();
while (!string.IsNullOrEmpty(nextCursor) && nextCursor != "0")
{
var followers =
(from tweet in twitterCtx.User
where tweet.Type == UserType.Followers &&
tweet.ID == auth.UserId &&
tweet.Cursor == nextCursor
select tweet).ToList();
result.AddRange(followers);
nextCursor = followers[0].CursorMovement.Next;
}
return View(result);
}
Please help. Thanks.
If you want to post input tags to server, they must be in a form tag. Then your html must be something like this:
#model IEnumerable<LinqToTwitter.User>
#{
ViewBag.Title = "Page d'accueil";
}
<h2>
Twitter</h2>
#using (Html.BeginForm())
{
<table>
<tr>
<td>
<input id="Checkbox1" type="checkbox" />
</td>
</tr>
#foreach (var tweet in Model)
{
<tr>
<td>
<input id="#("chk" + #tweet.ID.ToString())" type="checkbox" name="#("chk" + #tweet.ID.ToString())" />
</td>
<td>
<img alt="" src="#tweet.ProfileImageUrl" />
</td>
<td>
<strong>#tweet.Name</strong>
<br />
Friends: <strong>#tweet.FriendsCount</strong>
</td>
</tr>
}
</table>
}
note how to define form tag by HtmlHelper and define of checkbox to have unique ID.
and your controller code like this:
Dictionary<int, bool> isChecked = new Dictionary<int, bool>();
foreach (LinqToTwitter.User item in twitterCtx.User)
{
if (Request.Form["chk" + item.ID.ToString()] != null && Request.Form["chk" + item.ID.ToString()] == "on")
isChecked.Add(item.ID, true);
else
isChecked.Add(item.ID, false);
}
now isChecked Dictionary is contain each item's Id and whether is check or not.