I am trying to call multiple partials in parent view. I have tried multiple way but could not succeed. I think there is something missing in View. Please guide me where i am going wrong.
Note: I have partials in the question. Please suggest me.
The following error:
System.InvalidOperationException: 'The model item passed into the
dictionary is of type 'Aplication.Models.ABC.ClsA', but this
dictionary requires a model item of type
'System.Collections.Generic.IEnumerable`1[Aplication.Models.ABC.first]'.'
Model
public class ClsA
{
public List<first> firsts{ get; set; }
public List<second> seconds{ get; set; }
}
public class first
{
public string Name { get; set; }
public string Address { get; set; }
}
public class second
{
public string Details{ get; set; }
public string Age{ get; set; }
}
Controller
public ActionResult ABC()
{
SDetails sDetails=new SDetails();
var model = new ClsA();
model.firsts = sDetails.Rst();
model.seconds = sDetails.Rs();
return View(model);
}
View
#model Aplication.Models.ABC.ClsA
#Html.Partial("_PartialA");
#Html.Partial("_PartialB.cshtml")
_PartialA
#model IEnumerable<Aplication.Models.ABC.first>
<table>
<tr>
<th>#Html.DisplayNameFor(m => m.Name)</th>
<th>#Html.DisplayNameFor(m => m.Address)</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Address)
</td>
</tr>
}
</table>
_PartialB
#model IEnumerable<Aplication.Models.ABC.second>
<table>
<tr>
<th>#Html.DisplayNameFor(m => m.Details)</th>
<th>#Html.DisplayNameFor(m => m.Age)</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Details)
</td>
<td>
#Html.DisplayFor(modelItem => item.Age)
</td>
</tr>
}
</table>
#Html.Partial() Takes a second parameter model. If you do not pass the parameter to #Html.Partial() it will automatically pass the model of the current view.
Parameters
htmlHelper
Type: System.Web.Mvc.HtmlHelper
The HTML helper instance that this method extends.
partialViewName
Type: System.String
The name of the partial view to render.
model
Type: System.Object
The model for the partial view.
You need to update your code from
#Html.Partial("_PartialA");
#Html.Partial("_PartialB");
To
#Html.Partial("_PartialA", Model.firsts);
#Html.Partial("_PartialB", Model.seconds)
You do not need to pass the file extension to the #Html.Partial method
This is an example of loading partial view. The controller has an action to load the data in a partial view.
public ActionResult List()
{
var movies = db.Movies;
return PartialView("_list", movies.ToList());
}
In the partial _list view, you can have something like -
#model IEnumerable<WebApplication1.Models.Movie>
<div class="row">
<table class="table table-bordered table-hover" id="moviesTable">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.ID)
</th>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
#Html.DisplayNameFor(model => model.ReleaseDate)
</th>
<th>
#Html.DisplayNameFor(model => model.Genre)
</th>
<th>
#Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<div class="btn-group btn-group-xs">
<i class="fa fa-trash-o"></i>
<i class="glyphicon glyphicon-pencil"></i> Edit
<i class="glyphicon glyphicon-eye-open"></i> View
<i class="glyphicon glyphicon-trash"></i> Delete
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
Now you can render the partial view in the main view like below -
<div class="row">
<div class="col-md-12" id="replacetarget">
#{ Html.RenderAction("List", "Movies"); }
</div>
</div>
Related
i have a problem to collect the values in my text fields .
in each row on my screen i have a text field and the user should be add values there (you can see it from the picture)
exaple of my site
this is my html code:
#using (Html.BeginForm("Create", "User", FormMethod.Post))
{
#Html.AntiForgeryToken()
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.BarCode)
</th>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Profit)
</th>
<th>
Amount
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.BarCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Profit)
</td>
<td>
<form action="/action_page.php">
Amount:
<input type="text" id="amountTag" name="Amount" maxlength="2" placeholder="0" size="4" runat="server" />
</form>
</td>
</tr>
}
<tr>
<td><input type="submit" value="Submit" class="btn btn-default" /></td>
</tr>
</table>
}
and my code is
// POST: User/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
/*Update the Database*/
// TODO: Add insert logic here
string x = Request.Form["amountTag"];
return RedirectToAction("Index");
}
catch
{
return View();
}
}
this code always get Null and i don't have idea why
This section will create a form inside existing form (nested forms), which is not a good way to bind the textbox:
<form action="/action_page.php">
Amount:
<input type="text" id="amountTag" name="Amount" maxlength="2" placeholder="0" size="4" runat="server" />
</form>
The correct way should be like this:
1) Create an int property of Amount in the same viewmodel class as BarCode, Name and Profit properties has.
public class ViewModelName
{
// required unique key for each rows
public int Id { get; set; }
// other 3 properties here
[DisplayName("Amount")]
public int Amount { get; set; }
}
2) Bind the model inside view with HTML helpers using for loop. Here you should add TextBoxFor helper for Amount property to let user input numeric value with HTML attributes you have previously:
#model IEnumerable<ViewModelClassName>
#using (Html.BeginForm("Create", "User", FormMethod.Post))
{
#Html.AntiForgeryToken()
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.BarCode)
</th>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Profit)
</th>
<th>
Amount
</th>
</tr>
#for (int i = 0; i < Model.Count; i++)
{
#Html.HiddenFor(modelItem => modelItem[i].Id)
<tr>
<td>
#Html.DisplayFor(modelItem => modelItem[i].BarCode)
</td>
<td>
#Html.DisplayFor(modelItem => modelItem[i].Name)
</td>
<td>
#Html.DisplayFor(modelItem => modelItem[i].Profit)
</td>
<td>
#* Amount *#
#Html.LabelFor(modelItem => modelItem[i].Amount)
#Html.TextBoxFor(modelItem => modelItem[i].Amount, new { maxlength = 2, ... })
</td>
</tr>
}
<tr>
<td><input type="submit" value="Submit" class="btn btn-default" /></td>
</tr>
</table>
}
3) Make sure that action method decorated with HttpPostAttribute has list of viewmodel class as parameter.
[HttpPost]
public ActionResult Create(List<ViewModelName> model)
{
try
{
// example to select all amount values
var x = model.Select(x => x.Amount).ToList();
// do something
return RedirectToAction("Index");
}
catch
{
// error handling
return View(model);
}
}
From this point, your model binding should working fine.
Related issue: Need to pass a List<model> to the Http Post in a Controller
Getting an error on the view, at the displaynamefor softwareid line, saying the model SoftwareDTO does not contain a definition for softwareid. I can see it right there in the model.
Model:
public class SoftwareDTO
{
public int SoftwareId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Controller:
public ActionResult Index()
{
List<SoftwareDTO> softwareList = new List<SoftwareDTO>();
var data = _db.Software.ToList();
foreach (var sw in data)
{
SoftwareDTO software = new SoftwareDTO()
{
SoftwareId = sw.SoftwareId,
Name = sw.Name,
Description = sw.Description
};
softwareList.Add(software);
};
return View(softwareList);
}
View:
#model List<Request.Models.SoftwareDTO>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.SoftwareId)
</th>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.SoftwareId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
its because model its a list not an object SoftwareDTO in your razor view
I think you are missing the foreach
SoftwareId is a property of SoftwareDTO class. Your view is strongly typed to a collection of SoftwareDTO objects. So you need to loop through the model(The collection of SoftwareDTO) and access the SoftwareId of each item.
#model List<Request.Models.SoftwareDTO>
<table class="table">
#foreach(var item in Model)
{
<tr>
<td>
#Html.DisplayNameFor(x=> item.SoftwareId)
</td>
</tr>
}
</table>
EDIT : As per the edit in the question, and the comments provided.
Looks like you want to print the display name of the propertes in your table headers. If you do not wish to change the data you are passing from your action method, you can try this
#if (Model.Any())
{
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(x => Model[0].SoftwareId)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(x => item.SoftwareId)
</td>
</tr>
}
</table>
}
This is using the first item in the collection and it's properties to use with DisplayNameFor method. Since i have a if condition to check for at least one item before rendering the table, It will not even render the table if your Model has 0 items.
If you want to show the empty table with headers, you have 2 options.
Write HTML markup for the table header
<table class="table">
<tr>
<th>
<label>Software Id</label>
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(x => item.SoftwareId)
</td>
</tr>
}
</table>
Or if you still want to use the DisplayNameFor helper method to render the table header labels,
Create a new viewmodel
public class TableListVm
{
public List<SoftwareDTO> Items {set;get;}
public SoftwareDto ItemMeta {set;get;}
public TableListVm()
{
ItemMeta= new SoftwareDto();
}
}
And in your GET action, Send this object to your view
public ActionResult Index()
{
var data = _db.Software.ToList().Select(sw=> new SoftwareDTO {
SoftwareId = sw.SoftwareId,
Name = sw.Name,
Description = sw.Description
}).ToList();
var vm= new TableListVm { Items = data };
return View(vm);
}
And in your view which is strongly typed to this new view model.
#model TableListVm
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(x => Model.ItemMeta.SoftwareId)
</th>
</tr>
#foreach (var item in Model.Items)
{
<tr>
<td>
#Html.DisplayFor(x => item.SoftwareId)
</td>
</tr>
}
</table>
Can I pass table td values to controller?
View strongly typed:
#using (Html.BeginForm("PostClick", "Vendor", FormMethod.Post)) {
<table class="tblData">
<tr>
<th>
#Html.DisplayNameFor(model => model.First().SubmittedDate)
</th>
<th>
#Html.DisplayNameFor(model => model.First().StartDate)
</th>
</tr>
<tr>
<td>
#Html.DisplayFor(modelItem => item.SubmittedDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.StartDate)
</td>
</tr>
</table>
<input type="submit" value="submit" />
}
Contoller code:
public void PostClick(FormCollection collection)
{
/*Some Code */
}
How to pass table value from view to controller?
Have used JasonData & Ajax call and able to send the table data to controller.
Want to know any other method can be done because FormCollection data not able to find table values
Your need to generate controls that post back (input, textarea or select) and generate those controls in a for loop (or use a custom EditorTemplate for type Vendor)
View
#model List<Vendor>
#using (Html.BeginForm())
{
<table class="tblData">
<thead>
....
</thead>
<tbody>
for(int i = 0; i < Model.Count; i++)
{
<tr>
<td>#Html.TextBoxFor(m => m[i].SubmittedDate)</td>
<td>#Html.TextBoxFor(m => m[i].StartDate)</td>
</tr>
}
</tbody>
</table>
<input type="submit" value="submit" />
}
Post method
public void PostClick(List<Vendor> model)
{
/*Some Code */
}
I got a list of:
public class Items
{
public String Nro_Item { get; set; }
public Sucursal Sucursal { get; set; }
public Areas Area { get; set; }
public Sectores Sector { get; set; }
public bool ID_Estado { get; set; }
}
I'm passing it to this view:
#using ClientDependency.Core.Mvc
#model IEnumerable<TrackingOperaciones.Controllers.Items>
#{
ViewBag.Title = "Ver Items";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<br/>
#using (Html.BeginForm("CargarRecibidos", "Recepcion", FormMethod.Post))
{
<table class="table table-striped table-bordered table-condensed">
<tr>
<th>
Numero
</th>
<th>
Sucursal
</th>
<th>
Area
</th>
<th>
Sector
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Nro_Item)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sucursal.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Area.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sector.Descripcion)
</td>
<td>
#Html.CheckBoxFor(modelItem => item.ID_Estado)
</td>
</tr>
}
</table>
<p>
<input class="btn" name="Guardar" type="submit" value="Guardar"/> |
#Html.ActionLink("Volver al listado de RecepciĆ³n", "Index")
</p>
}
Until there everything is fine: Now the problem is getting back the entire model with the checked values in a controller for processing it like this one:
[HttpPost]
public ActionResult CargarRecibidos(IEnumerable<Items> items)
{
if (ModelState.IsValid)
{
//do something here
}
return RedirectToAction("Index");
}
}
But i'm falling miserably because "items" came back empty in the postback
i'm guess something is wrong with the form
#using (Html.BeginForm("CargarRecibidos", "Recepcion"))
{
<input class="btn" name="Guardar" type="submit" value="Guardar"/>
}
please help me!
Use IEnumerable
Then the controller input parameter will be List
Perhaps also consider using AJAX POST with JSON objects in place of a form submit (more modern/elegant) but submits are fine too.
Part of the problem is it won't post the entire model since only the checkbox is a form value. I think you need to add an additional hidden value in your form to track the item number and then handle the checkbox values specially in the controller. The item number is appended to "checkbox" in the posted values to keep them distinct.
<tr>
<td>
#Html.DisplayFor(modelItem => item.Nro_Item)
#Html.Hidden("Nro_Item", item.Nro_Item)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sucursal.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Area.descripcion)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sector.Descripcion)
</td>
<td>
#Html.CheckBox("checkbox" + item.Nro_Item, item.ID_Estado)
</td>
</tr>
In the controller only bind to the number item so it can be used to process the checkboxes:
[HttpPost]
public ActionResult CargarRecibidos(List<string> nro_item)
{
foreach (string item in nro_item)
{
var checkbox=Request.Form["checkbox" + item];
if (checkbox != "false") // if not false then true,false is returned
{
// Do the action for true...
}
else
{
// Do the action for false
}
}
return View();
}
On click of delete link i want to call DeleteConfirmed Method in my Student Controller.
Student Controller Code
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Student student = db.Students.Find(id);
db.Students.Remove(student);
db.SaveChanges();
return RedirectToAction("Index");
}
Index.cshtml has delete link (last line of code) on click of which i want the DeleteConfirmed to be called but the below expects delete.cshtml to be present.I don't want to show delete view and just want the delete to happen asynhronously.
#model IEnumerable<SMS.Model.Student>
#{
ViewBag.Title = "Student";
}
<h2>Student</h2>
#using (Html.BeginForm()) {
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.RegistrationNo)
</th>
<th>
#Html.DisplayNameFor(model => model.FirstName)
</th>
<th>
#Html.DisplayNameFor(model => model.MiddleName)
</th>
<th>
#Html.DisplayNameFor(model => model.LastName)
</th>
<th>
#Html.DisplayNameFor(model => model.DateofBirth)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.RegistrationNo)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.MiddleName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateofBirth)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Details", "Details", new { id=item.Id }) |
#Ajax.ActionLink("Delete", "Delete", new { id = item.Id },new AjaxOptions { HttpMethod = "Post"})
</td>
</tr>
}
}
Inside the view instead of
#using (Html.BeginForm())
You should have
#using (Html.BeginForm("DeleteConfirmed", "YourControllerName"))
If won't work, removing ActionName("Delete") should do the trick.
Let me know if that was of help.