Update mutiple records in database MVC 5 EF - c#

Good evening,
Now I'll describe my situation:
Here is my Model:
[Table("Items")]
public class Item
{
[Key]
public string Id { get; set; }
public DateTime Generated { get; set; }
public string Content { get; set; }
public string UrlSeo { get; set; }
public bool IsActive { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
}
I;m implementing CRUD operations to DB records, but I need implement one more Action, I need to Update for example UrlSeo property in selected records in one action.
So here is my view:
#model IEnumerable<CheckBoxes.Models.Item>
#{
ViewBag.Title = "Items";
}
<dv class="page-header">
<h3>Items</h3>
</dv>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using (Html.BeginForm("ChangeUrl", "Items", FormMethod.Post))
{
<div class="row">
<div class="form-group-sm">
<div class="col-md-4">
#Html.TextBox("urlSeo", null, new { #class = "form-control" })
</div>
<div class="col-md-offset-2 col-md-4">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
<p>
</p>
</div>
<table class="table">
<tr>
<th>
<input type="checkbox" id="checkAll" />
</th>
<th>
#Html.DisplayNameFor(model => model.Generated)
</th>
<th>
#Html.DisplayNameFor(model => model.Content)
</th>
<th>
#Html.DisplayNameFor(model => model.UrlSeo)
</th>
<th>
#Html.DisplayNameFor(model => model.IsActive)
</th>
<th>
#Html.DisplayNameFor(model => model.Quantity)
</th>
<th>
#Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<th>
<input type="checkbox" class="checkBox" value="#item.Id" />
</th>
<td>
#Html.DisplayFor(modelItem => item.Generated)
</td>
<td>
#Html.DisplayFor(modelItem => item.Content)
</td>
<td>
#Html.DisplayFor(modelItem => item.UrlSeo)
</td>
<td>
#Html.DisplayFor(modelItem => item.IsActive)
</td>
<td>
#Html.DisplayFor(modelItem => item.Quantity)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>
}
#section Scripts{
#Scripts.Render("~/bundles/toastr")
<!--მასიური წაშლა-->
<script>
$(document).ready(function () {
$("#checkAll").click(function () {
$(".checkBox").prop('checked',
$(this).prop('checked'));
});
});
</script>
}
And Finally My Controller:
[HttpPost]
public async Task<ActionResult> ChangeUrl(string urlSeo, string[] id)
{
foreach (var itemId in id)
{
Item item = await db.Items.FindAsync(itemId);
item.UrlSeo = urlSeo;
db.Entry(item).State = EntityState.Modified;
db.Entry(item).Property(x => x.Generated).IsModified = false;
db.Entry(item).Property(x => x.Content).IsModified = false;
db.Entry(item).Property(x => x.IsActive).IsModified = false;
db.Entry(item).Property(x => x.Price).IsModified = false;
db.Entry(item).Property(x => x.Quantity).IsModified = false;
}
await db.SaveChangesAsync();
return Json(new { success = true });
}
Now Question
How to pass all checked items to controller and input from field.
I home someone will help me.

Where was problem in view here is necessary give name for checkbox, witch equals part of controller.
#foreach (var item in Model)
{
<tr>
<th>
<input type="checkbox" class="checkBox" value="#item.Id" name="id" />
</th>
Everything worked fine, yes one more thing, better to use:
return RedirectToAction("Index");
So this is working solution.

Related

IList binding Razor Pages

Trying to bind IList so that I can update the fields that I have. However, ending up with an empty list with OnPostAsync. Not sure what I'm missing.
My code looks as follows:
[BindProperty]
public IList<Runbook_Serverlist_Plus> RunbookServerListPlus { get; set; }
This list is filled with the OnGetAsync function using the below code:
public async Task OnGetAsync()
{
var listRunbookServerList = await _context.Runbook_Serverlist.ToListAsync();
RunbookServerListPlus = listRunbookServerList.Select(item => new Runbook_Serverlist_Plus(item)).ToList();
}
So from my model I first get the IList<Runbook_Serverlist> and then I create a new list for Runbook_Serverlist_Plus.
Idea is to have a sort of a base class of Runbook_Serverlist, then put a Runbook_Serverlist_Plus on top, in which I can set specific fields which I can later use to update some fields.
See code below:
public class Runbook_Serverlist_Plus
{
[BindProperty]
public Runbook_Serverlist Bc {get; set; }
public Runbook_Serverlist_Plus(Runbook_Serverlist bsBc)
{
Bc = bsBc;
CheckCompleted = false;
}
public bool CheckCompleted { get; set; }
}
In my cshmtl the code is as follows:
<form method="post">
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Servername)
</th>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Status)
</th>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Cluster)
</th>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.StatusChange)
</th>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.PreRun)
</th>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Ordering)
</th>
<th></th>
</tr>
</thead>
<tbody>
#for (var i = 0; i < Model.RunbookServerListPlus.Count; i++)
{
var item = Model.RunbookServerListPlus[i];
<tr>
<td>
#Html.DisplayFor(modelItem => item.Bc.Servername)
</td>
<td>
#Html.DisplayFor(modelItem => item.Bc.Status)
</td>
<td>
#Html.DisplayFor(modelItem => item.Bc.Cluster)
</td>
<td>
#Html.DisplayFor(modelItem => item.Bc.StatusChange)
</td>
<td>
#Html.DisplayFor(modelItem => item.Bc.PreRun)
</td>
<td>
#Html.DisplayFor(modelItem => item.Bc.Ordering)
</td>
<td>
<input hidden asp-for="#item.Bc.Servername" class="form-control" />
<input asp-for="#item.CheckCompleted" class="form-control"/>
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<input type="submit" value="Update" class="btn btn-primary" />
</div>
</form>
So I have a checkbox for the CheckCompleted item and when doing a post, I would like to see all the checkboxes which are marked.
When I do a submit/post, I would expect the RunbookServerListPlus to be filled. However, this one is empty all the time.
What am I missing?
Post function is for now nothing else then:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
return RedirectToPage("./Index");
}
Firstly,you can add hidden inputs to bind model data,form post will pass inputs' value.And .net core bind model with name attribute.If you want to bind data with list,you need to set name as list[index].xxx.
And If you only want to pass Runbook_Serverlist_Plus when CheckCompleted is checked,you can use js to change the name of hidden inputs to right format before form post.Here is a demo.
Models:
public class Runbook_Serverlist_Plus
{
[BindProperty]
public Runbook_Serverlist Bc { get; set; }
public Runbook_Serverlist_Plus(Runbook_Serverlist bsBc)
{
Bc = bsBc;
CheckCompleted = false;
}
public Runbook_Serverlist_Plus()
{
}
public bool CheckCompleted { get; set; }
}
public class Runbook_Serverlist
{
public string Servername { get; set; }
public string Status { get; set; }
public string Cluster { get; set; }
public string StatusChange { get; set; }
public string PreRun { get; set; }
public string Ordering { get; set; }
}
cshtml:
<form method="post">
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Servername)
</th>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Status)
</th>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Cluster)
</th>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.StatusChange)
</th>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.PreRun)
</th>
<th>
#Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Ordering)
</th>
<th></th>
</tr>
</thead>
<tbody>
#for (var i = 0; i < Model.RunbookServerListPlus.Count; i++)
{
var item = Model.RunbookServerListPlus[i];
<tr>
<td>
#Html.DisplayFor(modelItem => item.Bc.Servername)
</td>
<td>
#Html.DisplayFor(modelItem => item.Bc.Status)
</td>
<td>
#Html.DisplayFor(modelItem => item.Bc.Cluster)
</td>
<td>
#Html.DisplayFor(modelItem => item.Bc.StatusChange)
</td>
<td>
#Html.DisplayFor(modelItem => item.Bc.PreRun)
</td>
<td>
#Html.DisplayFor(modelItem => item.Bc.Ordering)
</td>
<td>
<input asp-for="#item.CheckCompleted" class="form-control" name="RunbookServerListPlus[index].CheckCompleted" />
<input hidden asp-for="#item.Bc.Servername" class="form-control" name="RunbookServerListPlus[index].Bc.Servername" />
<input hidden asp-for="#item.Bc.Status" class="form-control" name="RunbookServerListPlus[index].Bc.Status" />
<input hidden asp-for="#item.Bc.Cluster" class="form-control" name="RunbookServerListPlus[index].Bc.Cluster" />
<input hidden asp-for="#item.Bc.StatusChange" class="form-control" name="RunbookServerListPlus[index].Bc.StatusChange" />
<input hidden asp-for="#item.Bc.PreRun" class="form-control" name="RunbookServerListPlus[index].Bc.PreRun" />
<input hidden asp-for="#item.Bc.Ordering" class="form-control" name="RunbookServerListPlus[index].Bc.Ordering" />
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<input type="submit" value="Update" class="btn btn-primary" />
</div>
</form>
<script>
$("form").submit(function () {
var index = 0;
$("tbody tr").each(function () {
var lasttd = $(this).find('td:last-child');
if (lasttd.find("input")[0].checked) {
lasttd.find("input").each(function () {
$(this).attr("name", $(this).attr("name").replace("index",index));
})
index++;
}
})
})
</script>
cshtml.cs(I use fake data to test):
[BindProperty]
public List<Runbook_Serverlist_Plus> RunbookServerListPlus { get; set; }
public void OnGet()
{
RunbookServerListPlus = new List<Runbook_Serverlist_Plus> {
new Runbook_Serverlist_Plus { Bc = new Runbook_Serverlist { Cluster = "c1", Ordering = "1", PreRun="p1", Servername="sname1", Status="status1", StatusChange="statuschange1" } },
new Runbook_Serverlist_Plus { Bc = new Runbook_Serverlist { Cluster = "c2", Ordering = "2", PreRun="p2", Servername="sname2", Status="status2", StatusChange="statuschange2" } },
new Runbook_Serverlist_Plus { Bc = new Runbook_Serverlist { Cluster = "c3", Ordering = "3", PreRun="p3", Servername="sname3", Status="status3", StatusChange="statuschange3" } }
};
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
return RedirectToPage("./Index");
}
result:
Update(Pass a whole list):
Firstly,remove js in the first demo.
And then change td like this:
<td>
<input asp-for="#item.CheckCompleted" class="form-control" name="RunbookServerListPlus[#i].CheckCompleted" />
<input hidden asp-for="#item.Bc.Servername" class="form-control" name="RunbookServerListPlus[#i].Bc.Servername" />
<input hidden asp-for="#item.Bc.Status" class="form-control" name="RunbookServerListPlus[#i].Bc.Status" />
<input hidden asp-for="#item.Bc.Cluster" class="form-control" name="RunbookServerListPlus[#i].Bc.Cluster" />
<input hidden asp-for="#item.Bc.StatusChange" class="form-control" name="RunbookServerListPlus[#i].Bc.StatusChange" />
<input hidden asp-for="#item.Bc.PreRun" class="form-control" name="RunbookServerListPlus[#i].Bc.PreRun" />
<input hidden asp-for="#item.Bc.Ordering" class="form-control" name="RunbookServerListPlus[#i].Bc.Ordering" />
</td>
result:
Check data passed to handler:
Only one of the handlers fires on each request, depending on the HTTP verb that was used to make the request. OnGet is executed when the page is requested using HTTP Get method. OnPost is executed by the POST method.
The web is stateless. That means that variables initialised on one request are not available to another request. If you want to work with the collection in the OnPost method, you need to instantiate it again in the OnPost handler.
More details on my site here: https://www.learnrazorpages.com/razor-pages/handler-methods

Why parameter of the action method is null when view is posted?

This is an ASP.NET MVC project. I have a view that displays a collection of BookRentViewModel items.
When I click on the button in the view, the view is posted to an action method called rent. rent action method has a parameter called items of type IEnumerable<BookRentViewModel>.
Here is the code of the view:
#model IEnumerable<DaramSerl.Models.ViewModels.BookRentViewModel>
#using (Html.BeginForm("rent", "RentBook", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.bookName)
</th>
<th>
#Html.DisplayNameFor(model => model.isRented)
</th>
<th>
#Html.DisplayNameFor(model => model.startDate)
</th>
<th>
#Html.DisplayNameFor(model => model.endDate)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.EditorFor(modelItem => item.bookName)
</td>
<td>
#Html.EditorFor(modelItem => item.isRented)
</td>
<td>
#Html.EditorFor(modelItem => item.startDate)
</td>
<td>
#Html.EditorFor(modelItem => item.endDate)
</td>
</tr>
}
</table>
<input type="submit" value="Create" class="btn btn-primary" />
}
And here is the action method:
[HttpPost]
public async Task<ActionResult> rent(IEnumerable<BookRentViewModel> items)
{
if (ModelState.IsValid)
{
return RedirectToAction("/Index");
}
return View();
}
And here is the BookRentViewModel:
public class BookRentViewModel
{
[Key]
public int bookId{ get; set; }
public string bookName { get; set; }
public bool isRented { get; set; }
public DateTime startDate { get; set; }
public DateTime endDate { get; set; }
}
The problem is that items parameter is always null when rent action is triggered.
Any idea why items is null and does not get the collection from the view?
UPDATE
I used fiddler to see if the collection is posted to the server but it seems it cannot be parsed into BookRentViewModel items.
UPDATE3
Here is screenshot from fiddler with the collection sent from the view:
Doesnt look like you're setting a value for public int bookId - if thats the case this will fail validation as its a non-nullable type.
Either way, set a breakpoint in your controller method and check the errors on ModelState - see Get error message if ModelState.IsValid fails?
Edit
To include properties but not show them on your view, use the hidden field razor tag helper:
#Html.HiddenFor(x => x.bookId)
I tried reproduce source code.
You can change model mapping in cshtml file as below
#for (int i = 0; i < Model.Count();i++ )
{
<tr>
<td>#Html.TextBox("items[" + #i + "].bookName",
Model.ElementAt(i).bookName
)</td>
<td>#Html.CheckBox("items[" + #i + "].isRented",
Model.ElementAt(i).isRented
)</td>
<td>#Html.TextBox("items[" + #i + "].startDate",
Model.ElementAt(i).startDate
)</td>
<td>#Html.TextBox("items[" + #i + "].endDate",
Model.ElementAt(i).endDate
)</td>
</tr>
}
rent.cshtml file
#model IEnumerable<WebApplication2.Controllers.BookRentViewModel>
#using (Html.BeginForm("rent", "Rent", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.bookName)
</th>
<th>
#Html.DisplayNameFor(model => model.isRented)
</th>
<th>
#Html.DisplayNameFor(model => model.startDate)
</th>
<th>
#Html.DisplayNameFor(model => model.endDate)
</th>
</tr>
#*#foreach (var item in Model)
{
<tr>
<td>
#Html.EditorFor(modelItem => item.bookName)
</td>
<td>
#Html.EditorFor(modelItem => item.isRented)
</td>
<td>
#Html.EditorFor(modelItem => item.startDate)
</td>
<td>
#Html.EditorFor(modelItem => item.endDate)
</td>
</tr>
}*#
#for (int i = 0; i < Model.Count();i++ )
{
<tr>
<td>#Html.TextBox("items[" + #i + "].bookName",
Model.ElementAt(i).bookName
)</td>
<td>#Html.CheckBox("items[" + #i + "].isRented",
Model.ElementAt(i).isRented
)</td>
<td>#Html.TextBox("items[" + #i + "].startDate",
Model.ElementAt(i).startDate
)</td>
<td>#Html.TextBox("items[" + #i + "].endDate",
Model.ElementAt(i).endDate
)</td>
</tr>
}
</table>
<input type="submit" value="Create" class="btn btn-primary" />
}

Null values in HTML form from MVC view

I would like to save users steps and have each row in my MVC index view be a form.
I am using the HTML.Begin form inside the foreach to build the individual forms. The page renders without errors and the form submits without problems, but I can not bind to a model inside the controller - thus all the submitted data is lost.
I have validated that the form values are there to begin with when the form is submitted: item.Completed=true&item.Completed=false&item.Comment=HELLO+WORLD+&item.FinalizeStepId=1&item.StepId=1, but the controller does not accept them and the FinalizeStepViewModel object is created with null values.
So how do I get the form to pass back the data correctly?
This might be my second question ever on Stackoverflow, so let me know what additional information I might need to add.
Thanks.
=== Model =====
public class FinalizeStepViewModel
{
public int FinalizeStepId { get; set; }
// foreign key from Step table
public int StepId { get; set; }
// name of taks from Step table
public string StepDesc { get; set; }
[DisplayName("Review Data")]
public string ReviewFormulaValue { get; set; }
[Required]
public bool Completed { get; set; }
[DisplayName("Fiscal Year")]
public int FiscalYear { get; set; }
// Period for the adjustment
[Required]
public int Period { get; set; }
[Required]
public string UserID { get; set; }
[Required]
[DisplayName("Created By")]
public string CreatedBy { get; set; }
[Required]
[DisplayName("Created At")]
public DateTime CreatedAt { get; set; }
public string Comment { get; set; }
==== View ==========
#model IEnumerable
#{
ViewBag.Title = "Index";
// is everything completed, if yes => enabled
string alldone = "enabled";
}
<h2>Finalize Checklist</h2>
<table class="table">
<tr>
<th>
Completed
</th>
<th>
Finalized Task
</th>
<th>
Review Data
</th>
<th>
#Html.DisplayNameFor(model => model.Comment)
</th>
<th></th>
<th></th>
#*<th>
#Html.DisplayNameFor(model => model.FiscalYear)
</th>
<th>
#Html.DisplayNameFor(model => model.Period)
</th>
<th>
#Html.DisplayNameFor(model => model.CreatedBy)
</th>
<th>
#Html.DisplayNameFor(model => model.CreatedAt)
</th>
<th>
#Html.DisplayNameFor(model => model.UserID)
</th>*#
<th></th>
</tr>
#foreach (var item in Model)
{
//<form action="/FinalizeSteps/Checklist/" method="post">
//#using (Html.BeginForm("Login", "Account", FormMethod.Post))
//// <form action="/Account/Login" action="post">
using (Html.BeginForm("EditFromChecklist", "FinalizeSteps", FormMethod.Post, new { finalizeStepPassed = Model }))
{
<tr>
<td>
<div class="form-group" style="text-align: center; vertical-align: text-top;">
<div class="checkbox">
#Html.EditorFor(modelItem => item.Completed)
#if (item.Completed == false) { alldone = "disabled"; }
</div>
</div>
</td>
<td>
<h4>#Html.DisplayFor(modelItem => item.StepDesc)</h4>
</td>
<td style="text-align: center;">
#Html.DisplayFor(modelItem => item.ReviewFormulaValue)
</td>
<td>
<div class="form-group" style="width: 300px;">
#Html.EditorFor(modelItem => item.Comment, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(modelItem => item.Comment, "", new { #class = "text-danger" })
</div>
</td>
<td>
<div class="form-group">
#Html.EditorFor(modelItem => item.FinalizeStepId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(modelItem => item.FinalizeStepId, "", new { #class = "text-danger" })
</div>
</td>
<td>
<div class="form-group">
#Html.EditorFor(modelItem => item.StepId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(modelItem => item.FinalizeStepId, "", new { #class = "text-danger" })
</div>
</td>
#*<td>
#Html.DisplayFor(modelItem => item.FiscalYear)
</td>
<td>
#Html.DisplayFor(modelItem => item.Period)
</td>
<td>
#Html.DisplayFor(modelItem => item.CreatedBy)
</td>
<td>
#Html.DisplayFor(modelItem => item.CreatedAt)
</td>
<td>
#Html.DisplayFor(modelItem => item.UserID)
</td>*#
<td>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
#Html.ActionLink("Save", "EditFromChecklist", new { FinalizeStepId = item.FinalizeStepId, StepId = item.StepId, Completed = item.Completed, Comment = item.Comment })
#*#Html.ActionLink("Edit", "Edit", new { id = item.FinalizeStepId }) |
#Html.ActionLink("Details", "Details", new { id = item.FinalizeStepId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.FinalizeStepId })*#
</td>
</tr>
}
}
</table>
=== Controller Method ====
[HttpPost]
public ActionResult EditFromChecklist([Bind(Include = "FinalizeStepId,StepId,Completed,Comment")] FinalizeStepViewModel finalizeStepPassed)
{
// Do we have a FinalizeStepId?
if (finalizeStepPassed.FinalizeStepId != 0)
{
// Yes, this is an edit
...
Change your EditFromChecklist action's parameter from finalizeStepPassed to item.
Or you could use a partial view to submit your data.
_FinalizeStepPartial.cshtml
#model FinalizeStepViewModel
using (Html.BeginForm("EditFromChecklist", "FinalizeSteps"))
{
#Html.EditorFor(model => model.Completed)
// rest of your form
}
and in the main view inside of loop call the partial
#foreach (var item in Model)
{
#Html.Partial("_FinalizeStepPartial",item)
}
You should bind to a IList instead of IEnumerable, and instead of
#foreach (var item in Model)
{
#Html.EditorFor(modelItem => item.Completed)
}
Use this syntax
#for( int i=0; i < Model.Count; i++ )
{
#Html.EditorFor(modelItem => Model[i].Completed)
}
Here is an earlier topic that also discussed this: How to pass IEnumerable list to controller in MVC including checkbox state?

Populate form from table select with asp.net mvc

I have a table with data, how can I populate a form on the same page with the data when the edit button is clicked. Basically is should be the same as this example but without using knockoutjs
http://jsfiddle.net/jiggle/2cr2f/
#model IEnumerable<GenomindApp2.Areas.RulesEngine.ViewModels.GeneViewModel>
#{
ViewBag.Title = "Index2";
}
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.GeneValue)
</th>
<th>
#Html.DisplayNameFor(model => model.GeneCode)
</th>
<th>
#Html.DisplayNameFor(model => model.GeneName)
</th>
<th>
#Html.DisplayNameFor(model => model.GeneComments)
</th>
<th>
#Html.DisplayNameFor(model => model.WildType)
</th>
<th>
#Html.DisplayNameFor(model => model.WildTypeAllele)
</th>
<th>
#Html.DisplayNameFor(model => model.AtRiskAllele)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.GeneCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.GeneName)
</td>
<td>
#Html.DisplayFor(modelItem => item.GeneComments)
</td>
<td>
#Html.DisplayFor(modelItem => item.WildType)
</td>
<td>
#Html.DisplayFor(modelItem => item.WildTypeAllele)
</td>
<td>
#Html.DisplayFor(modelItem => item.AtRiskAllele)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { }) |
#Html.ActionLink("Details", "Details", new { }) |
#Html.ActionLink("Delete", "Delete", new { })
</td>
</tr>
}
</table>
You should do it like that:
Model:
public class ModelB
{
public int Age { get; set; }
public string Name { get; set; }
}
Controller:
public ActionResult MyAction()
{
var model = new List<ModelB>
{
new ModelB{Age = 2, Name = "Bob"},
new ModelB{Age = 7, Name = "Sam"},
};
return View(model);
}
[HttpPost]
public ActionResult MyAction(List<ModelB> model)
{
//whatever
}
View:
#model List<TestWebApplication.Models.ModelB>
...
#using (Html.BeginForm())
{
for (int i = 0; i < Model.Count; i++)
{
Age: #Html.EditorFor(modelItem => Model[i].Age);
Name: #Html.EditorFor(modelItem => Model[i].Name);
<br />
}
<input type="submit"/>
}
Please note that I used for instead of foreach. When you populate a form you shouldn't use foreach - it will not render well.

How to pass argument to ASP.NET MVC 3 controller that is called via onclick attribute of a html button?

I have the following View code (ASP:NET MVC 3):
#using(Html.BeginForm()){
#Html.ValidationSummary(true)
<table>
<tr>
<th>
City
</th>
<th>
Hotel
</th>
<th>
Room name
</th>
<th>
Number of beds
</th>
<th>
Price per night
</th>
<th></th>
</tr>
<tr>
<td>
#Html.DisplayFor(x=>Model.SelectedRoom.Hotel.City.Name)
</td>
<td>
#Html.DisplayFor(x => Model.SelectedRoom.Hotel.Name)
</td>
<td>
#Html.DisplayFor(x => Model.SelectedRoom.Name)
</td>
<td>
#Html.DisplayFor(x => Model.SelectedRoom.NumberOfBeds)
</td>
<td>
#Html.DisplayFor(x => Model.SelectedRoom.PricePerNight)
</td>
</tr>
</table>
<input type="hidden" name="RoomID" value="#Model.SelectedRoom.RoomID" id="RoomID" />
<br />
<br />
<p>
From: #Html.TextBoxFor(m=>m.DateOne, new {#class="datepicker1", #readonly="readonly" })
#Html.ValidationMessageFor(m=>m.DateOne)
To: #Html.TextBoxFor(m => m.DateTwo, new { #class = "datepicker2", #readonly = "readonly" })
#Html.ValidationMessageFor(m=>m.DateTwo)
</p>
<p>
Total cost : #Html.TextBoxFor(m=>m.TotalCost, new {#class="TotalAmount", #readonly="readonly" })
</p>
<br />
<input type="button" id="Reserve" value="Confirm" onclick = "window.location.href='/Home/MakeReservation'+#Model" />
}
Here is my Model definition for this View:
public class MakeReservationViewModel
{
BusinessLogic bl;
public MakeReservationViewModel()
{
bl = new BusinessLogic();
}
public Room SelectedRoom { get; set; }
[Required(ErrorMessage="Please select a starting date")]
public DateTime DateOne { get; set; }
[Required(ErrorMessage = "Please select an ending date")]
public DateTime DateTwo { get; set; }
public decimal TotalCost { get; set; }
}
How to call *MakeReservation controller action from above View by clicking on a button and setting it's onclick attribut to MakeReservation properly?*
Here is my Controller:
[HttpPost]
public ViewResult MakeReservation(MakeReservationViewModel mrvm)
{
if (ModelState.IsValid)
{
}
return View();
}
This is the error I ger:
Object reference not set to an instance of an object.
on this line:
How to make model accept hidden field?
SOLVED.
I added :
#Html.TextBoxFor(m => m.SelectedRoom.RoomID, new {#class="RoomID", #hidden="hidden" })
instead of previous way that used not strongly typed property.

Categories

Resources