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.
Related
I have a table with pagination in ASP.Net Core. I have a input where user can search the result by name and a Search button which works as expected. However after the search name input is searched and result is displayed, clicking on the new page number, the model parameter(search name) is not being transferred to the controller action method. The page parameter is however being transferred correctly. How do I go about fixing it?
#model FruitViewModel
#using PagedList.Core.Mvc
<form id="formPostFruit" asp-action="PostFruit" asp-controller="Fruit" asp-route-model="#Model" method="get">
<input name="SearchName" type="text" title="Search Name" class="form-control" placeholder="Search name" asp-for="SearchName" aria-describedby="basic-addon1">
<button id="btnSearch" class="btn btn-secondary btn-sm" type="button" title="Search"><i class="fas fa-search" aria-hidden='true'></i> Search</button>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Quantity</th>
<th>Price</th>
</tr>
</thead>
<tbody>
#if (Model.ResultList != null && Model.ResultList.Count() > 0)
{
#foreach (var item in Model.ResultList)
{
<tr>
<td>
#item.Name
</td>
<td>
#item.Quantity
</td>
<td>
#item.Price
</td>
</tr>
}
}
</tbody>
</table>
#if (Model != null && Model.ResultList != null && Model.ResultList.Count() > 0 && Model.ResultList.PageCount > 1)
{
<pager class="pager" list="#Model.ResultList" asp-action="PostFruit" asp-
controller="Fruit" asp-route-model="#Model" param-page-number="page"
options="#PagedListRenderOptions.Bootstrap4PageNumbersPlusFirstAndLast" />
}
The Controller action
public ActionResult PostFruit(FruitViewModel model, int? page)
{
}
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
I am trying to pass values from a view to a controller in MVC. I am using a ViewModel and normally the values would bind to the properties as long as the names are the same. However because the values are generated via a foreach loop the names of the values do not match the names of the properties in the view model.
I am working around this by assigning the values to a variable in Razor. However one of my values is in a text box on the form and the value is not being passed to the controller and I cannot work out why.
I get a null exception when clicking the button.
VIEW Code is below:
#model PagedList.IPagedList<Mojito.Domain.ViewModels.ShoppingCartProductItem>
#using System.Web.UI.WebControls
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Mojito Products</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().Description)
</th>
<th>
#Html.ActionLink("Price", "Index", new { sortOrder = ViewBag.SortByPrice, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().Quantity)
</th>
<th>
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.TextBoxFor(modelItem => item.Quantity)
</td>
<td>
#{string Description = item.Description;}
#{decimal Price = item.Price;}
#{int Quantity = item.Quantity; }
#using (Html.BeginForm("AddToCart", "ShoppingCart", FormMethod.Post))
{
<div class="pull-right">
#if (Request.Url != null)
{
<input type="text" hidden="true" name="Description" value=#Description />
<input type="text" hidden="true" name="Price" value=#Price />
<input type="text" hidden="true" name="Quantity" value=#Quantity />
#Html.Hidden("returnUrl", Request.Url.PathAndQuery)
<input type="submit" class="btn btn-success" value="Add to cart" />
}
</div>
}
</td>
</tr>
}
</table>
<div class="col-md-12">
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
</div>
#Html.PagedListPager(Model, page => Url.Action("Index",
new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
Controller Code below
public ActionResult AddToCart(Cart cart, MojitoProduct product, string returnUrl, int Quantity =1)
{
if (product != null)
{
cart.AddItem(product, Quantity);
}
return RedirectToAction("Index", new { returnUrl });
}
Do not use foreach. Use a for-loop instead and within this, qualify the full path to your properties using the index.
Better yet: use a Edit- or DisplayTemplate for the ShoppingCartProductItem. This will also keep your path.
You have to use for loop instead of foreach:
#for (int i=0;i < Model.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => Model[i].Description)
</td>
<td>
#Html.DisplayFor(modelItem => Model[i].Price)
</td>
<td>
#Html.TextBoxFor(modelItem => Model[i].Quantity)
</td>
..........................
..........................
..........................
}
you can also post all using one form by posting List<ShoppingCartProductItem>, see Model Binding To A List
Your textboxes so values out of the form.
Try like below
#using (Html.BeginForm("AddToCart", "ShoppingCart", FormMethod.Post))
{
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.TextBoxFor(modelItem => item.Quantity)
</td>
<td>
#{string Description = item.Description;}
#{decimal Price = item.Price;}
#{int Quantity = item.Quantity; }
<div class="pull-right">
#if (Request.Url != null)
{
<input type="text" hidden="true" name="Description" value=#Description />
<input type="text" hidden="true" name="Price" value=#Price />
<input type="text" hidden="true" name="Quantity" value=#Quantity />
#Html.Hidden("returnUrl", Request.Url.PathAndQuery)
<input type="submit" class="btn btn-success" value="Add to cart" />
}
</div>
</td>
</tr>
}
}
I resolved this in the short term by using new and forcing the name of the parameter.
#Html.HiddenFor(modelItem => t.NoOfUsers, new { Name = "NoOfUsers", id = "NoOfUsers" })
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 am trying to implement a simple add operation using MVC Ajax
My code is as follows:
Public Class Model
{
public int number1{get;set;}
public int number2{get;set;}
}
[HttpPost]
public string TestAjax( )
{
int strnum1 = Convert.ToInt32(Request["txtbox1"].ToString());
int strnum2 = Convert.ToInt32(Request["txtbox2"].ToString());
string strnum3 = Convert.ToString(strnum1 + strnum2);
if (strnum3 != null)
{
return strnum3;
}
return string.Empty;
}
It is hitting the Ajax action method. But, i was not able to fetch the values from the request object or from the form collection
I am getting , object reference not set to instance of an object error message.
Updated: Client Side Code
<% using (Ajax.BeginForm("TestAjax", "Reviewer", new AjaxOptions { UpdateTargetId = "textEntered" }))
{ %>
<table align="center">
<tr>
<td class="tdCol1Align">
<label>
Number1</label>
</td>
<td class="tdCol2Align">
<input type="text" id="txtbox1" />
</td>
</tr>
<tr>
<td class="tdCol1Align">
<label>
Number2</label>
</td>
<td class="tdCol2Align">
<input type="text" id="txtbox2" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="Add" class="button" />
</td>
</tr>
</table>
<%
}
%>
<br />
<br />
<span id="textEntered"></span>
Please help..
You need to set the name attribute in your html element:
<input type="text" id="txtbox2" name="txtbox2" />
Update: Based on your model:
[HttpPost]
public int TestAjax(Model mymodel)
{
return mymodel.number1 + mymodel.number2;
}
And in your HTML assuming you are referencing the model:
#model Model
replace your inputs with this accordingly:
#Html.TextBoxFor(model => model.number1)
#Html.TextBoxFor(model => model.number2)
You have to validate that the user only types integer valid values in your textboxes with javascript.