I am new to MVC and I am trying populate a list of item in the MVC view class, but the model object is null in the .cshtml file during the startup.
#foreach (var element in Model)
Thanks for your help.
My Code:
public class HomeController : Controller
{
List<ModelMath> mathList = new List<ModelMath>();
[HttpPost]
public ActionResult Submit(FormCollection fc)
{
mathList = new List<ModelMath>();
int num = Convert.ToInt32(fc["Num"]);
while(num > 1)
{
ModelMath modelMath = new ModelMath();
modelMath.Number = num;
mathList.Add(modelMath);
num--;
}
return View(mathList);
}
}
Model class:
public class ModelMath
{
public int Number { get; set; }
}
Index.cshtml
#{
ViewBag.Title = "Home Page";
}
<h3><b>HTTPPost Method</b></h3>
#using (Html.BeginForm("Submit", "Index", FormMethod.Post))
{
<table>
<tr>
<td>Enter a Number: </td>
<td>#Html.TextBox("Num")</td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Submit"></td>
</tr>
</table>
}
<h4 style="color:purple">
<div class="panel-body">
<div class="col-md-12" style="margin-top: 15px;">
<table class="table table-bordered table-responsive table-hover">
<tr>
<th>Input Numbers </th>
</tr>
#foreach (var element in Model)
{
<td>#d.Number</td>
}
</table>
</div>
</div>
</h4>
Could you please let me know what's wrong with my code? Thanks again for your help.
In your Index function, you need to populate the model and pass to the view. Something like
Public ActionResult Index()
{
var myList = new List<example>();
return view(myList)
}
and in your view:
#model List<example>
That is what populates your index view model. It would help if you show us the controller function returning your index view.
you should write the type of Model at first of your View
#model List<ModelMath>
and for showing a view you need [HttpGet] attribute action
[HttpGet]
Public ActionResult Index()
{
//var mathList= new list<ModelMath>();
return view(mathList)
}
Related
when I run my code it seems that my HttpGet method works fine. But when I try to return the value to my HttpPost action it just runs my HttpGet method and then I get an "NullReferenceException" error.
Here is my code.
My Actions in my controller:
[HttpGet]
public IActionResult AddMovie(int? id)
{
List<Movie> movieList = new List<Movie>();
movieList = dbContext.Movies.ToList();
AddMovieViewModel viewModel = new AddMovieViewModel()
{
movies = movieList,
customer = dbContext.Customers.Where(s => s.CustomerId == id).FirstOrDefault()
};
return View(viewModel);
}
[HttpPost]
public IActionResult AddMovie (int id,int cid)
{
Customer customer = dbContext.Customers.Where(s => s.CustomerId == cid).FirstOrDefault();
Movie movie = dbContext.Movies.Where(s => s.MovieId == id).FirstOrDefault();
customer.BorrowingMovies.Add(movie);
customer.BorrowingMovies.Add(movie);
return View();
}
And here my view
#model MovieExampleAppDotNetCore.ViewModels.AddMovieViewModel
#{
ViewData["Title"] = "AddMovie";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>AddMovie</h1>
<label>Add movie for: #Model.customer.Name</label>
<table style="width:100%" class="table table-bordered table-hover">
<tr>
<th>Name</th>
</tr>
#foreach (var movie in Model.movies)
{
<tr>
<td>#movie.Name</td>
<td>
#Html.ActionLink("Select", "AddMovie", new { id = movie.MovieId, cid = Model.customer.CustomerId })
</td>
</tr>
}
</table>
I hope someone can help me with my problem.
The HTML ActionLink does not work with POST so is hitting your GET method. See this question.
To overcome and resolve your issue, wrap the button in a Form, something like this should do the trick.
#using (Html.BeginForm("AddMovie", "ControllerName", new { id = movie.MovieId, cid = Model.customer.CustomerId }, FormMethod.Post))
{
<button class="btn btn-primary" type="submit">
Add Movie
</button>
}
I want to use 3 partial views to display my search result(Client name) in 3 different tables. I do not want to show any info from the tables before the search has been completed. As i have understood you can only use one model per view, unless you make some workarounds.
I have tried to make a view model so i can reference the multiple tables from both the index and the partial views. But can't figure it out. Since the methods for the 3 different tables will be the pretty much same i am only going to post the code for the client table. Any help or pointers would be much appreciated
ViewModel:
public class ViewModel
{
public List<Clients> allClients { get; set; }
public List<OrderLines> allOrders { get; set; }
public List<ViewNewOrderSum> allViewNewOrderSum { get; set; }
}
HomeController:
using testForAutofill.Models;
public class HomeController : Controller
{
test_Db_Context db = new test_Db_Context();
// GET: Home
public ActionResult Index()
{
ViewModel vm = new ViewModel();
vm.allClients = GetClients();
return View();
}
private List<Clients> GetClients()
{
List<Clients> clientList = new List<Clients>();
clientList = db.Clients.ToList();
return clientList;
}
[HttpPost]
public ActionResult Index(string searchTerm)
{
Scaleit_Db_Context db = new Scaleit_Db_Context();
List<Clients> orderSums;
if (string.IsNullOrEmpty(searchTerm))//Fix this!
{
orderSums = db.Clients.ToList();
}
else
{
orderSums = db.Clients.Where(x => x.Name.Equals(searchTerm)).ToList();
}
return View(orderSums);
}
IndexView:
#using testForAutofill.Models;
#model testForAutofill.Models.ViewModel
#if (Model.allClients != null && Model.allClients.Count() > 0)
{
#using (Html.BeginForm())
{
<b>Kundenavn:</b>
#Html.TextBox("searchTerm", null, new { id = "txtSearch" })
<input type="submit" value="🔍 Search" class="btn btn-primary" id="btn-search" />
#using (Html.BeginForm())
{
<div class="card-container">
<div class="card border-primary mb-3 card-client" style="max-width: 40rem;">
<div class="card-header">Kunde</div>
<div class="card-body">
<table class="table table-hover">
#foreach (Clients clients in Model.allClients)
{
#Html.Partial("_Client", clients)
}
</table>
</div>
</div>
</div>
}
_Client:
#model testForAutofill.Models.ViewModel
//Tried both DisplayFor and not.
<tr>
<th>Kunde:</th>
<td>#Html.Model.allClients.Name</td>// This is where the error gets
// thrown.
</tr>
<tr>
<th>Org.nr:</th>
<td>#Html.DisplayFor(modelItem => clients.OrgNr)</td>
</tr>
<tr>
<th>Adresse:</th>
<td>#Html.DisplayFor(modelItem => clients.Address1)</td>
#if (clients.Address2 != null)
{
<td>#Html.DisplayFor(modelItem => clients.PostNr)</td>
}
</tr>
The program/webpage doesnt run, and i get the error message:
" CS1061: 'HtmlHelper' does not contain a definition for
'Model' and no extension method 'Model' accepting a first argument of
type 'HtmlHelper' could be found (are you missing a using
directive or an assembly reference?)".
At the commented line in the Partial view.
TRY:
Set object on viewData
inside controller:
ActionResult SomeView(){
ViewData["object"] = theObj;
return View();
}
inside cshtml:
#using objectNamespace
#(((objectType)ViewData["object"]).name)
In my ASP.Net MVC project I have following ViewModel
public class ApproveItemViewModel
{
[Required]
public int ItemId { get; set; }
[Required]
public string ItemCode { get; set; }
}
I have following two methods in controller
[HttpGet]
public ActionResult ListPendingItems()
{
var items = new List<ApproveItemViewModel>();
//add few items here in above list
return View(vms);
}
[HttpPost]
public JsonResult ApproveItem(ApproveItemViewModel viewmodel)
{
return Json(new { success = success }, JsonRequestBehavior.AllowGet);
}
Now in my razor view what I want is to call ApporveItem method using Ajax calls for each individual item. so I created multiple ajax form using below code.
#model IEnumerable<ApproveItemViewModel>
#foreach (var item in Model)
{
using (Ajax.BeginForm("ApproveItem", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
UpdateTargetId = "dane"
}))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<table>
<tr>
<td>#Html.LabelFor(m => item.ItemId)</td>
<td>#Html.DisplayFor(m => item.ItemId)</td>
</tr>
<tr>
<td>#Html.LabelFor(m => item.ItemCode)</td>
<td>#Html.TextBoxFor(m => item.ItemCode))</td>
</tr>
<tr>
<td><input type="submit" value="Approve" /></td>
</tr>
</table>
}
}
However in the controller action method parameter I get both ItemId and ItemCode as 0 and null respectively. Whats the problem here, could anyone help please? How can we pass the viewmodel to action using ajax?
The problem is most likely that the Model Binder in the view doesn't know how to bind your list of ApproveItemViewModel's.
See this answer for an explanation: https://stackoverflow.com/a/21191624/2521893
#model IEnumerable<ApproveItemViewModel>
#for (int i = 0; i < Model.Count; i++)
{
using (Ajax.BeginForm("ApproveItem", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
UpdateTargetId = "dane"
}))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<table>
<tr>
<td>#Html.LabelFor(m => Model[i].ItemId)</td>
<td>#Html.DisplayFor(m => Model[i].ItemId)</td>
</tr>
<tr>
<td>#Html.LabelFor(m => Model[i].ItemCode)</td>
<td>#Html.TextBoxFor(m => Model[i].ItemCode))</td>
</tr>
<tr>
<td><input type="submit" value="Approve" /></td>
</tr>
</table>
}
}
Cause of this issue is 'parameter' name. You need to keep same name for both controller post action's parameter(ie, viewmodel) and iterating model(item) in cshtml side, then only binding should happened. See the two different solutions below.
Solution 1 : Modify cshtml page:-
Replace #foreach (var item in Model) with #foreach (var viewmodel in Model)
ie,
#foreach (var viewmodel in Model)
Solution 2 : Modify controller action:-Change ApproveItem action's parameter name.
ie,
[HttpPost]
public JsonResult ApproveItem(ApproveItemViewModel item)
{
return Json(new { success = success }, JsonRequestBehavior.AllowGet);
}
I am encountering the following error:
A data source must be bound before this operation can be performed.
I have a text box, the user enters a name, and clicks the submit button. The name is added to a list. I have researched the error but everything I try gives me the same error. Any insight on what I am doing wrong will be appreciated.
Model:
namespace RangeTest.Models
{
public class UserNameModel
{
[Key]
public int Id { get; set; }
[Display(Name = "Names Added List")]
public string FullName { get; set; }
}
}
Controller:
public ActionResult Admin()
{
return View();
}
[HttpPost]
public ActionResult Admin(UserNameModel model, IEnumerable<RangeTest.Models.UserNameModel> t)
{
List<UserNameModel> userList = new List<UserNameModel>();
model.FullName = t.FirstOrDefault().FullName;
userList.Add(model);
return View(userList.ToList());
}
View (Admin.cshtml):
#model IEnumerable<RangeTest.Models.UserNameModel>
#{
ViewBag.Title = "";
}
<div class="container"></div>
<div class="jumbotron">
#using (Html.BeginForm("Admin", "UserNames", FormMethod.Post, new { #id = "WebGridForm" }))
{
#Html.ValidationSummary(true)
WebGrid dataGrid = new WebGrid(Model, canPage: false, canSort: false);
//Func<bool, MvcHtmlString> func =
//(b) => b ? MvcHtmlString.Create("checked=\"checked\"") : MvcHtmlString.Empty;
<div class="table-bordered">
<div class="Title">Admin - Add names to range list</div><br />
<table id="TblAdd"class="table">
<tr>
#{
RangeTest.Models.UserNameModel t = new RangeTest.Models.UserNameModel();
}
#Html.Partial("_AddDynTable", t)
</table>
</div>
<div class="table-responsive">
<div class="Title">Names Added to Range List</div>
<table class="table">
<tr>
<td >
#dataGrid.GetHtml(columns: dataGrid.Columns(dataGrid.Column(format: #<text>#item</text>),
dataGrid.Column("", format: (item) => Html.ActionLink("Delete", "Delete", new { id = item.id }))))
</td>
</tr>
</table>
</div>
}
</div>
Partial View (_addDynTable.cshtml)
#model RangeTest.Models.UserNameModel
<tr>
<td>
Enter Full Name: #Html.TextBoxFor(m => m.FullName)
#*<input type="button" value="Create" id="ClickToAdd" />*#<input class="CreateBtn" type="submit" value="Add to List" /></td>
</tr>
Can you link info about the error please?
One thing I can see is your t object is null when you pass it to the partial view
RangeTest.Models.UserNameModel t = new RangeTest.Models.UserNameModel();
A new UserNameModel with no data in it, if your error is there that might be the problem
I got a stored procedure which i show in the view for edits. I made a strong type of the stored procedure. When i edit the fields and then press the save button, the parameter "cm" is always empty. And it's not showing a list but just 1 record.
The custom model:
public class CustomModel
{
public string Description { get; set; }
public System.Data.Linq.ISingleResult<GetItems_ListResult> ItemList { get; set;}
}
This part of the controller sends it to the view:
public ActionResult Details(int id)
{
var row = dataContext.Items.FirstOrDefault(x => x.ItemID == id);
var cm = new CustomModel();
cm.ItemList = dataContext.GetItem_List(row);
cm.Description = row.Description;
return View(cm);
}
This controller receives data from the view:
[HttpPost]
public ActionResult UpdateItems(CustomModel cm)
{
return RedirectToAction("Index");
}
This is the view:
#model TestWeb.Models.CustomModel
#using (Html.BeginForm("UpdateItems", "Item", FormMethod.Post))
{
<table>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
#foreach (var p in Model.ItemList.ToList())
{
<tr>
<td>
#Html.HiddenFor(mdl => p.ItemId)
</td>
<td>#p.Name</td>
<td>
#Html.EditorFor(mdl => p.Description)
</td>
</tr>
}
</table>
<p>
<input type="submit" value="save" />
</p>
}
What am i doing wrong here?
Try the following:
Make a GetItems_ListResult.cshtml like this:
<tr>
<td>
#Html.HiddenFor(mdl => mdl.ItemId)
</td>
<td>#Model.Name</td>
<td>
#Html.EditorFor(mdl => mdl.Description)
</td>
</tr>
Then in your for loop do this:
#for (int i = 0; i < Model.ItemList.Count(); i++)
{
#Html.EditorFor(m => m.ItemsList[i])
}
Update: I didn't quite notice you were using an ISingleResult. You could do this instead:
//Since it'll have none or one element..
if(Model.ItemList != null && Model.ItemList.Any())
{
#Html.EditorFor(m => m.ItemList.First())
}
Have you read this blog post? http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/ Steve covers editing lists in asp mvc.
Once your read that take a look at this nuget package http://nuget.org/packages/BeginCollectionItem