asp.net mvc onr-to-many details partial view in master main view - asp.net-mvc

I am sorry if im asking same thing for the nth time but i can not find the answer to my question...
I have problem adding partial views...
I have One-to-Many relation in the database tables.
My Model is:
using System;
using System.Collections.Generic;
public partial class Job
{
public Job()
{
this.Flights = new HashSet<Flight>();
}
public int JobID { get; set; }
public string JobNumber { get; set; }
public int ClientID { get; set; }
public virtual Client Client { get; set; }
public virtual ICollection<Flight> Flights { get; set; }
}
My Controller (Create):
// GET: /Jobs/Create
public ActionResult Create()
{
ViewBag.ClientID = new SelectList(db.Clients, "ClientID", "ClientName");
return View();
}
And View (for create Job):
#model AOG.Models.Job
<div class="form-horizontal">
<h4>Job</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.JobNumber, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.JobNumber)
#Html.ValidationMessageFor(model => model.JobNumber)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ClientID, "ClientID", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("ClientID", String.Empty)
#Html.ValidationMessageFor(model => model.ClientID)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
Now if i add partial view (Generated Partial List View) On Create Job Page:
#html.Partial("_PartialFlights");
I get an error: Object reference not set to an instance of an object on
Line 23: #foreach (var item in Model) {
in my partial view. This is the code:
#model IEnumerable<AOG.Models.Flight>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.FlightName)
</th>
<th>
#Html.DisplayNameFor(model => model.FlightETD)
</th>
<th>
#Html.DisplayNameFor(model => model.FlightETA)
</th>
<th>
#Html.DisplayNameFor(model => model.Job.JobNumber)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FlightName)
</td>
<td>
#Html.DisplayFor(modelItem => item.FlightETD)
</td>
<td>
#Html.DisplayFor(modelItem => item.FlightETA)
</td>
<td>
#Html.DisplayFor(modelItem => item.Job.JobNumber)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.FlightID }) |
#Html.ActionLink("Details", "Details", new { id=item.FlightID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.FlightID })
</td>
</tr>}</table>
How ever If i put this in the details view:
#foreach (var item in Model.Flights)
{
<div>
<table>
<tr><th>Flight</th><th>ETD</th><th>ETA</th></tr>
<tr>
<td>#Html.DisplayFor(modelItem => item.FlightName)</td>
<td>#Html.DisplayFor(modelItem => item.FlightETD)</td>
<td>#Html.DisplayFor(modelItem => item.FlightETA)</td>
</tr></table>
</div>
}
It shows everything I need, but i want to learn how to do it with the partial views.
Thank you all so much!

You need to pass an IENumerable<Flight> instance to your partial view, so in stead of:
#html.Partial("_PartialFlights");
...do this:
#html.Partial("_PartialFlights", Model.Flights);

Related

ASP.NET MVC Send List from View to controller

I'm trying to create a product model with ID,Name and a list of specifications like above:
My model:
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
public virtual List<Spec> Specifications { get; set; }
}
public class Spec
{
public int SpecID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
My Controller:
public ActionResult Create(Product product,List<Spec> Specifications)
{
......
}
My View:
using (Html.BeginForm("Create", "Products", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Product</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-2"><h3>Specifications</h3></div>
<div class="col-md-10">
<table id="tblSkills" cellpadding="0" cellspacing="0" class="table table-responsive">
<thead>
<tr>
<th style="width:150px">Name</th>
<th style="width:150px">Description</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
<tfoot>
<tr>
<td><input type="text" id="Name1" /></td>
<td><input type="text" id="Description" /></td>
<td>
<input type="button" id="btnAdd" class="btn btn-success btn-sm" value="Add" />
</td>
</tr>
</tfoot>
</table>
<br />
<input type="button" id="btnSave" value="SaveAll" class="bntbtn-block btn-success" />
<br />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
so it should looks like this:
I also added some Scripts so that I can enter or remove specifications, the information will be displayed inside a tbody tag in a table.
The problem is that I don't really know how to pass my list of specifications to my controller, or should I try another way of input multiple specifications instead of using table. I'm looking for a way to input it using HTMLHelper like the one I did with Product's Name.
I apologize if my question is unclear. If you have any question to understand more, feel free to ask me. Thanks for any advise or solution.
To pass the model to a view from controller you need to:
public ActionResult Create(List<Spec> Specifications)
{
return View(Specifications);
}
and in your view add these to on top of the view:
#using PathOfYourSpecificationsModel
#model List<Spec>
using (Html.BeginForm("Create", "Products", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Product</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-2"><h3>Specifications</h3></div>
<div class="col-md-10">
<table id="tblSkills" cellpadding="0" cellspacing="0" class="table table-responsive">
<thead>
<tr>
<th style="width:150px">Name</th>
<th style="width:150px">Description</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
<tfoot>
<tr>
<td><input type="text" id="Name1" /></td>
<td><input type="text" id="Description" /></td>
<td>
<input type="button" id="btnAdd" class="btn btn-success btn-sm" value="Add" />
</td>
</tr>
</tfoot>
</table>
<br />
<input type="button" id="btnSave" value="SaveAll" class="bntbtn-block btn-success" />
<br />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
After user clicks add button you need another [HttpPost] method for Create. Which should look like this:
[HttpPost]
public ActionResult Create(List<Spec> Specifications)
{
// Specifications should be filled with view values.
// Do your logic here. Ex: Save the data to database
}
For adding dynamic control fields, it is advised to use helper methods.
The AddNewRow helper method will return the html elements can one can make changes like changing the html attributes.
the html attributes should be unique and it is advised to use increment value for each element.
the attributes of html elements returned from helper method are changed in addNewRow() of javascript function.
Detailed steps are provided below.
In Product Model
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
public List<Spec> Specifications { get; set; }
}
public class Spec
{
public int SpecID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsRemoved { get; set; }
}
In Controller
public class ProductController : Controller
{
// GET: Product
public ActionResult AddProduct()
{
Product product = new Product();
product.Specifications = new List<Spec>()
{
new Spec()
};
return View(product);
}
[HttpPost]
public ActionResult AddProduct(Product product)
{
return View(product);
}
}
In AddProduct.cshtml
#model Product
#using WebApplication3.Models
#{
ViewBag.Title = "AddProduct";
}
#helper AddNewRow()
{
<tr id="trRow_0">
<td>
#Html.HiddenFor(x => Model.Specifications[0].IsRemoved, new { id = "hdnSpecIsRemoved_0" })
#Html.TextBoxFor(x => Model.Specifications[0].Name, new { id = "txtSpecName_0" })
</td>
<td>
#Html.TextBoxFor(x => Model.Specifications[0].Description, new { id = "txtSpecDesc_0" })
</td>
<td>
Remove Row
</td>
</tr>
}
<h2>AddProduct</h2>
#using (Html.BeginForm("AddProduct", "Product", FormMethod.Post))
{
<div>
#Html.LabelFor(x => x.Name)
#Html.TextBoxFor(x => x.Name)
</div>
<table>
<thead>
<tr>
<th>
#Html.LabelFor(x => x.Specifications[0].Name)
</th>
<th>
#Html.LabelFor(x => x.Specifications[0].Description)
</th>
<th>
Action
</th>
</tr>
</thead>
<tbody id="tBody">
#for (int i = 0; i < Model.Specifications.Count; i++)
{
string trRow = "trRow_" + i;
<tr id="#trRow">
<td>
#Html.HiddenFor(x => Model.Specifications[i].IsRemoved, new { id = "hdnSpecIsRemoved_" + i })
#Html.TextBoxFor(x => Model.Specifications[i].Name, new { id = "txtSpecName_" + i })
</td>
<td>
#Html.TextBoxFor(x => Model.Specifications[i].Description, new { id = "txtSpecDesc_" + i })
</td>
<td>
Remove Row
</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="2">
<br />
<button type="button" onclick="addNewRow()">Add New Row</button>
</td>
</tr>
</tfoot>
</table>
<br />
<button type="submit">Save All</button>
}
<script type="text/javascript">
function addNewRow() {
var totalSpecCount = $('#tBody tr').length;
var newRowData = `#(AddNewRow())`;
newRowData = newRowData.replaceAll("Specifications[0]", "Specifications[" + totalSpecCount + "]")
newRowData = newRowData.replaceAll("txtSpecName_0", "txtSpecName_" + totalSpecCount);
newRowData = newRowData.replaceAll("txtSpecDesc_0", "txtSpecDesc_" + totalSpecCount);
newRowData = newRowData.replaceAll("trRow_0", "trRow_" + totalSpecCount);
newRowData = newRowData.replaceAll("removeRow(0)", "removeRow(" + totalSpecCount+")");
newRowData = newRowData.replaceAll("hdnSpecIsRemoved_0", "hdnSpecIsRemoved_" + totalSpecCount);
$('#tBody').append(newRowData);
}
function removeRow(recordId) {
var trId = "#trRow_" + recordId;
var hdnSpec = "#hdnSpecIsRemoved_" + recordId;
$(hdnSpec).val(true);
$(trId).hide();
}
</script>
Here, the method addNewRow will call the helper methods and change the html attributes of the element based on row count.
In strongly typed view, the index values should unique for the list so that it can be posted using model binding
Final Result
Note: In remove row method we have to hide the element instead of removing the element completely. This is used to achieve post the list directly. To know what the rows that are removed a flag called IsRemoved is to true.
If we remove the element, the index value will not be in sequence and one cannot post the form.

How to make an insert form and a table displaying data from database in a single view in MVC?

I'm making a CRUD but I want the create and read parts to be in a single MVC view. The create part is done, I've been trying to fill an HTML table with data from a database table when the view loads, but it won't let me do both things at once in a single view.
Here's the view header:
#model Console.Models.Product
#{
ViewBag.Title = "Create";
}
Here's the insert form:
#using (Html.BeginForm())
{
<div class="box-body">
<div class="form-horizontal">
#Html.AntiForgeryToken()
#Html.Hidden("productID", 0)
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="col-md-6">
#Html.EditorFor(model => model.productName, new { htmlAttributes = new { #class = "form-control", #name = "txtProductName", #id = "txtProductName" } })
</div>
#Html.ValidationMessageFor(model => model.productName, "", new { #class = "text-danger", Type = "productName" })
</div>
<div class="form-group">
<div class="col-md-6">
#Html.EditorFor(model => model.productQuantity, new { htmlAttributes = new { #class = "form-control", #name = "txtProductQuantity", #id = "txtProductQuantity" } })
</div>
#Html.ValidationMessageFor(model => model.productQuantity, "", new { #class = "text-danger" })
</div>
<div class="form-group">
<div class="col-md-6">
#Html.EditorFor(model => model.productColor, new { htmlAttributes = new { #class = "form-control", #name = "txtProductColor", #id = "txtProductColor" } })
</div>
#Html.ValidationMessageFor(model => model.productColor, "", new { #class = "text-danger" })
</div>
</div>
</div>
}
This is the table that should show the products that are inserted into the database in the form above:
<table id="Data_table" class="table table-bordered table-striped">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.productName)
</th>
<th>
#Html.DisplayNameFor(model => model.productQuantity)
</th>
<th>
#Html.DisplayNameFor(model => model.productColor)
</th>
<th>
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.productName)
</td>
<td>
#Html.DisplayFor(modelItem => item.productQuantity)
</td>
<td>
#Html.DisplayFor(modelItem => item.productColor)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.productID }, new { #class = "btn btn-success btn-sm" })
#Html.ActionLink("Delete", "Delete", new { id = item.productID }, new { #class = "btn btn-danger btn-sm" })
</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<th><div class="panel-footer">Total = #Model.Count()</div></th>
</tr>
</tfoot>
</table>
Problem is that I get an error at the foreach telling me to use IEnumerable with the model but whenever I do, the insert form gets an error. Is there any way to get around this?
Edit:
Here's the view model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Console.Models
{
public class ProductViewModel
{
public int productID{ get; set; }
public string productName{ get; set; }
public int productQuantity{ get; set; }
public string productColor{ get; set; }
public IEnumerable<Product> Products { get; set; }
}
}
In your view you do pass a single model, and then you try to iterate over it, that of course is not possible.
You should use view models. Create a view model that contains both the fields you need for the form and the list of products you want to iterate over on foreach.
#model ProductViewModel
#{
ViewBag.Title = "Create";
}
Create a view model, like this:
public class ProductViewModel {
public string ProductName { get; set; }
// Other fields for the form
public IEnumerable<Product> Products { get; set; } // Your list of products for the table
}
And then in your view:
#Html.EditorFor(model => model.ProductName,
// Continue with the form
#foreach (var item in Model.Products)
{ //...continue with your table

Multiple kendo grids in view using MVC Razor #foreach

Is it possible to create multiple kendo grids using MVC Razor #foreach?
I've tried the following and nothing is rendering in the view, it looks like the data is correct as I can see the correct JSON data in the script but no grid displays
#using Kendo.Mvc.UI
#model ProjectMVC.Models.IndexViewModel
#{
ViewData["Heading"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
#{
int gridIndex = 0;
foreach (var Heading in Model.Headings)
{
gridIndex++;
var Groups = Model.Groups.Where(x => x.Group == Heading);
tblGroups Group = Model.Groups.Where(x => x.Group == Heading).First();
#(Html.Kendo().Grid(Groups)
.Name($"grid{gridIndex}")
.Columns(columns =>
{
columns.Bound(c => c.Date).Width(140);
columns.Bound(c => c.User).Width(190);
columns.Bound(c => c.Category);
columns.Bound(c => c.Group).Width(110);
})
.Pageable()
.Filterable()
.Scrollable()
)
}
}
The following code does work using <\table> instead of Html.Kendo().Grid but I have been unable to recreate this using a kendo grid instead of tables. Can anyone point out where I might be going wrong?
Specifically this is aspnet core mvc.
MODEL:
public class tblGroups
{
[Key]
public int ID { get; set; }
public DateTime Date { get; set; }
public string User { get; set; }
public string Category { get; set; }
public string Group { get; set; } //<<Want separate tables split by this field
}
public class IndexViewModel
{
public List<tblGroups> Groups { get; set; }
public List<string> Headings { get; set; }
Public IndexViewModel()
{
Groups = new List<tblGroups>();
Headings = new List<string>();
}
}
VIEW:
#model MVC.Models.IndexViewModel
#{
ViewData["Heading"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
#{
foreach (var Heading in Model.Headings)
var Groups = Model.Groups.Where(x => x.Group == Heading);
tblGroups Group = Model.Groups.First(x => x.Prodcut == Heading);
<text>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => Group.Date)
</th>
<th>
#Html.DisplayNameFor(model => Group.User)
</th>
<th>
#Html.DisplayNameFor(model => Group.Category)
</th>
<th>
#Html.DisplayNameFor(model => Group.Group)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Groups)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.User)
</td>
<td>
#Html.DisplayFor(modelItem => item.Category)
</td>
<td>
#Html.DisplayFor(modelItem => item.Group)
</td>
<td>
</td>
</tr>
}
</tbody>
</table>
</text>
}
}
CONTROLLER:
public class tblGroupsController : Controller
{
public async Task<IActionResult> Index()
{
var allGroups = await _context.tblGroups.ToListAsync();
var Headings = allGroups.Select(x => x.Group).Distinct();
var model = new Models.IndexViewModel()
{
Groups = allGroups,
Headings = Headings
};
return View(model);
}
}
In order to use the same partial view multiple times, grid ID should be unique so passing the ID in partial view data is one possible solution. I have used the same grid multiple times in a PartialView by passing some parameters and retrieving different data via these parameters as shown below:
View:
<div class="row">
<div class="col-lg-6">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title" id="panel-title">New Issues</h3>
</div>
<div>
#Html.Partial("_List", new ViewDataDictionary { { "name", "grid-all-issues" }, { "style", "border:none; height:622px;" }, { "pageSize", "25" } })
</div>
</div>
</div>
<div class="col-lg-6">
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title" id="panel-title">Active Issues</h3>
</div>
<div>
#Html.Partial("_List", new ViewDataDictionary { { "name", "grid-waiting-issues" }, { "style", "border:none; height:273px;" }, { "pageSize", "10" } })
</div>
</div>
</div>
<div class="col-lg-12 top-10">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title" id="panel-title">Watched Issues</h3>
</div>
<div>
#Html.Partial("_List", new ViewDataDictionary { { "name", "grid-watched-issues" }, { "style", "border:none; height:273px;" }, { "pageSize", "10" } })
</div>
</div>
</div>
</div>
</div>
</div>
PartialView:
#(Html.Kendo().Grid<Models.ViewModel>()
.HtmlAttributes(new { style = #ViewData["style"].ToString() })
.Name(#ViewData["name"].ToString())
//...
.Columns(columns =>
{
columns.Bound(m => m.Key).Title("Issue No");
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(Convert.ToInt32(#ViewData["pageSize"]))
)
)
Update: You can pass column parameter by using an approach below.
For passing parameter to a PartialView in ASP.NET MVC:
#Html.Partial("~/PathToYourView.cshtml", null, new ViewDataDictionary { { "VariableName", "some value" } })
And to retrieve the passed in values:
#{
string valuePassedIn = this.ViewData.ContainsKey("VariableName") ?
this.ViewData["VariableName"].ToString() : string.Empty;
}
Hope this helps...

How to call a method from the View? MVC

I have a View with a <input type="submit" value="Create" /> when a User click create the Action Method should be activated and the Result written in the db.
At the moment when a User click Create Button in the View nothing happen. Could you tell me what I'm doing wrong? thanks
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TestGuestBook.Models;
using TestGuestBook.Models.Repositories;
using TestGuestBook.ViewModels;
namespace TestGuestBook.Controllers
{
[HandleError]
public class HomeController : Controller
{
ICommentRepository _repository;
public HomeController()
{
_repository = new CommentRepository();
}
// Dependency Injection enabled constructors
public HomeController(ICommentRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
// Get all Comments
List<Comment> commentItems = _repository.FindAll().ToList();
// Create the ViewModel and associate the list of comments
CommentListCreateViewModel viewModel = new CommentListCreateViewModel();
viewModel.CommentItems = commentItems;
return View(viewModel);
}
public ActionResult Create()
{
CommentListCreateViewModel createViewModel = new CommentListCreateViewModel();
return View(createViewModel);
}
[HttpPost]
public ActionResult Create(CommentListCreateViewModel createViewModel)
{
if (ModelState.IsValid)
{
Comment comment = new Comment
{
Nominative = createViewModel.Nominative,
Email = createViewModel.Email,
Content = createViewModel.Content
};
_repository.Add(comment);
_repository.Save();
}
return View();
}
}
}
View
#model TestGuestBook.ViewModels.CommentListCreateViewModel
#{
ViewBag.Title = "Index";
}
<h2>
Index</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>ListAddCommentsViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Nominative)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Nominative)
#Html.ValidationMessageFor(model => model.Nominative)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Content)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Content)
#Html.ValidationMessageFor(model => model.Content)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<table>
<tr>
<th>
Nominative
</th>
<th>
Email
</th>
<th>
Content
</th>
<th>
</th>
</tr>
#foreach (var item in Model.CommentItems)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Nominative)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.Content)
</td>
<td>
</td>
</tr>
}
</table>
You need to direct the form to your Create controller method:
#using (Html.BeginForm("Create", "Home"))
You can leave it as Html.BeginForm() and after the save, call return RedirectToAction("Index"); The added item should now show in the list. It was probably saving all along, it just wasn't being re-directed to the Index view afterwards.

How to add a list to a View Model MVC

I'm using MVC 3 with View Model, in my case I have a View Model that should display a list of items and also a form for inserting some input.
I have problem in my View because I'm not able to associate the Form for inserting the data with the view model, could you tell me what I'm doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using TestGuestBook.Models;
namespace TestGuestBook.ViewModel
{
public class ListAddCommentsViewModel
{
public int CommentId { get; set; }
[Required]
public string Nominative { get; set; }
[Email]
public string Email { get; set; }
[Required]
public string Content { get; set; }
public List<Comment> CommentItems { get; set; }
}
}
View
#model IEnumerable<TestGuestBook.ViewModel.ListAddCommentsViewModel>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>ListAddCommentsViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CommentId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CommentId)
#Html.ValidationMessageFor(model => model.CommentId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Nominative)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Nominative)
#Html.ValidationMessageFor(model => model.Nominative)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Content)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Content)
#Html.ValidationMessageFor(model => model.Content)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
CommentId
</th>
<th>
Nominative
</th>
<th>
Email
</th>
<th>
Content
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CommentId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Nominative)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.Content)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
You dont need to pass a Collection to your View. Only one object of the ViewModel is enough. Your ViewModel already have property to holde the collection (List of Comments)
So in your GET Action, return only one instance of this viewModel to the View
public ActionResult GetComments(int postId)
{
var viewModel=new ListAddCommentsViewModel();
viewModel.CommentItems =db.GetComments(postId);
return View(viewModel);
}
and now in your View, Let it bind to a single instance of ListAddCommentsViewModel
#model TestGuestBook.ViewModel.ListAddCommentsViewModel
And Inside your view, to Show your List of comments, use the Collection type property (Model.CommentItems) in your ViewModel
#foreach (var item in Model.CommentItems) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CommentId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Nominative)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.Content)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { #id=item.PrimaryKey }) |
#Html.ActionLink("Details", "Details", new { #id=item.PrimaryKey }) |
#Html.ActionLink("Delete", "Delete", new { #id=item.PrimaryKey })
</td>
</tr>
}
This is the best solution, I had checked almost all information and this is the one working!! Thanks
public ActionResult UploadFile(UploadFileViewModel model)
{
if (ModelState.IsValid)
{
var file = model.File;
var parsedContentDisposition =
ContentDispositionHeaderValue.Parse(file.ContentDisposition);
var filename = Path.Combine(_environment.WebRootPath,
"Uploads", parsedContentDisposition.FileName.Trim('"'));
file.SaveAsAsync(filename);
}
return View();
}

Resources