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?
Related
I have the following, abridged for clarity and confidentiality, viewmodels:
public class BoqReviewViewModel
{
public List<BoqReviewItemViewModel> Items { get; set; } = new List<BoqReviewItemViewModel>();
}
public static BoqReviewItemViewModel FromEntity(GTT_BOQ_IMPORT import)
{
var ret = new BoqReviewItemViewModel();
ret.BOQ_IMPORT_ID = import.BOQ_IMPORT_ID;
ret.ITEM_CODE = import.ITEM_CODE;
ret.ITEM_DESC = import.ITEM_DESC;
ret.UNIT = import.UNIT;
ret.QTY = import.QTY;
ret.RATE = import.RATE;
ret.AMOUNT = import.AMOUNT;
ret.ITEM_PAYS = import.ITEM_PAYS;
ret.ITEM_CPA = import.ITEM_CPA;
return ret;
}
public GTT_BOQ_IMPORT ToEntity()
{
var ret = new GTT_BOQ_IMPORT();
ret.BOQ_IMPORT_ID = this.BOQ_IMPORT_ID;
ret.ITEM_CODE = this.ITEM_CODE;
ret.ITEM_DESC = this.ITEM_DESC;
ret.UNIT = this.UNIT;
ret.QTY = this.QTY;
ret.RATE = this.RATE;
ret.AMOUNT = this.AMOUNT;
ret.ITEM_PAYS = this.ITEM_PAYS;
ret.ITEM_CPA = this.ITEM_CPA;
return ret;
}
[Key]
public Guid BOQ_IMPORT_ID;
public string ITEM_CODE { get; set; }
public string ITEM_DESC { get; set; }
public string UNIT { get; set; }
public decimal? QTY { get; set; }
public decimal? RATE { get; set; }
public decimal? AMOUNT { get; set; }
public bool? ITEM_PAYS { get; set; }
public bool? ITEM_CPA { get; set; }
public bool IsFlagged { get; set; }
}
Then I have the following GET action for an index type view:
[HttpGet]
public ActionResult BoqReview()
{
var model = new BoqReviewViewModel();
model.CONTRACT_ID = Guid.NewGuid();
model.PROJECT_ID = Guid.NewGuid();
model.Items = GetItems().ToList();
return View(model);
}
Where GetItems is a method that returns an IEnumerable with three fully populated item level viewmodels. When I startup the app, I see a properly populated table with 3 rows with all columns properly populated.
This is the view:
#using (Html.BeginForm("BoqReview", "Boq", FormMethod.Post))
{
<table class="table">
<tr>
<th>
</th>
<th class="col-header">
Item Code
</th>
<th class="col-header">
Item Description
</th>
<th>
Unit
</th>
<th>
Quantity
</th>
<th>
Rate
</th>
<th>
Amount
</th>
<th>
Item Pays
</th>
<th>
Item CPA
</th>
<th>
</th>
</tr>
#for (var i = 0; i < Model.Items.Count; i++)
{
<tr>
<td>
#Html.TextBoxFor(model => model.Items[i].BOQ_IMPORT_ID)
</td>
<td>
#Html.TextBoxFor(model => Model.Items[i].ITEM_CODE)
#Html.ValidationMessageFor(model => Model.Items[i].ITEM_CODE)
</td>
<td>
#Html.TextBoxFor(model => Model.Items[i].ITEM_DESC)
#Html.ValidationMessageFor(model => Model.Items[i].ITEM_DESC)
</td>
<td>
#Html.TextBoxFor(model => Model.Items[i].UNIT, new {style = "width: 120px;"})
#Html.ValidationMessageFor(model => Model.Items[i].UNIT)
</td>
<td>
#Html.TextBoxFor(model => Model.Items[i].QTY)
#Html.ValidationMessageFor(model => Model.Items[i].QTY)
</td>
<td>
#Html.TextBoxFor(model => Model.Items[i].RATE)
#Html.ValidationMessageFor(model => Model.Items[i].RATE)
</td>
<td>
#Html.TextBoxFor(model => Model.Items[i].AMOUNT)
#Html.ValidationMessageFor(model => Model.Items[i].AMOUNT)
</td>
<td>
#Html.DropDownListFor(model => Model.Items[i].ITEM_PAYS, Model.YesNoSelectList)
#Html.ValidationMessageFor(model => Model.Items[i].ITEM_PAYS)
</td>
<td>
#Html.DropDownListFor(model => Model.Items[i].ITEM_CPA, Model.YesNoSelectList)
#Html.ValidationMessageFor(model => Model.Items[i].ITEM_CPA)
</td>
<td>
#Html.CheckBoxFor(model => Model.Items[i].IsFlagged)
</td>
</tr>
}
<tr>
<td colspan="4">
<input type="submit" value="Submit" />
</td>
</tr>
</table>
}
Everything looks perfect, yet when I submit the form:
[HttpPost]
public ActionResult BoqReview(BoqReviewViewModel model)
{
using (var db = new AppDbContext())
{
foreach (var modelItem in model.Items)
{
var updated = modelItem.ToEntity();
db.GttBoqImports.AddOrUpdate(updated);
}
db.SaveChanges();
}
return RedirectToAction("BoqReview");
}
The BOQ_IMPORT_ID field on each item viewmodel is an empty GUID, yet the displayed table shows a proper GUID. All other properties of the item level viewmodels are still populated.
What could be wrong that just this BOQ_IMPORT_ID is not properly model bound? When I debug the network call in Chrome tools, it shows a proper GUID value for each BOQ_IMPORT_ID in the form data posted:
Items[0].BOQ_IMPORT_ID: 610d9a12-920f-43aa-89bc-08b68067a462
Items[0].ITEM_CODE: AA1
Items[0].ITEM_DESC: Some A's and a 1
Items[0].UNIT: kg
Items[0].QTY: 200
...
JUST IN: Renaming the VM property in that class and in the view solved the whole problem. Maybe, despite several VS restarts, a machine restart mighty have somehow helped. This smells of temp files or some caching somewhere.
I have a problem with updating ViewModel by PartialView. PartialView includes Devices along with the location that varies depending on the DropDownList selected by the Customer. (At the bottom I present sample screenshot). The problem is that after accepting the submit button the property Devices in the ViewModel(FiscalizationViewModel) is not updating. Here are examples of models. I'm not sure I'm trying to solve this problem properly.
namespace TestMVC.ViewModels
{
public class FiscalizationViewModel
{
public int CustomerId { get; set; }
public string FiscalizationDate { get; set; }
public List<DevicesToFiscalizationViewModel> Devices { get; set; }
public FiscalizationViewModel()
{
Devices = new List<DevicesToFiscalizationViewModel>();
}
public IEnumerable<DevicesToLocalization> GetSelectedIds()
{
return (from d in Devices where d.Selected select new DevicesToLocalization() { DeviceId = d.DeviceId, LocalizationId = d.LocalizationId }).ToList();
}
}
public class DevicesToFiscalizationViewModel
{
public int DeviceId { get; set; }
public string DeviceName { get; set; }
public bool Selected { get; set; }
public string SerialNumber { get; set; }
public int LocalizationId { get; set; }
public IEnumerable<Localization> Localizations { get; set; }
public DevicesToFiscalizationViewModel()
{
Localizations = new List<Localization>();
}
}
}
Here is the method that is called by the Customer DropDownList event
public PartialViewResult CustomerChanged(int CustomerId)
{
var localizations = db.Localizations.Where(i => i.CustomerId == CustomerId).ToList();
var devicesToFsc = (from d in db.Devices
select new DevicesToFiscalizationViewModel()
{
DeviceId = d.DeviceId,
DeviceName = d.Name,
SerialNumber = d.SerialNumber,
}).ToList();
foreach (var item in devicesToFsc)
{
item.Localizations = localizations;
}
return PartialView("~/Views/Fiscalizations/EditorTemplates/DevicesToFiscalizationViewModel.cshtml", devicesToFsc);
//--------------------------------
$("#customerChanged").on("change", function () {
$.ajax(
{
url: '/Fiscalizations/CustomerChanged?CustomerId=' + $(this).val(),
type: 'GET',
data: "",
contentType: 'application/json; charset=utf-8',
success: function (data) {
$("#devicesToFiscalization").html(data);
}
});
});
This is little partial of Views (Fiscalization create view)
#model TestMVC.ViewModels.FiscalizationViewModel
<table class="table" id="devicesToFiscalization">
<thead>
...
</thead>
#Html.Partial("~/Views/Fiscalizations/EditorTemplates/DevicesToFiscalizationViewModel.cshtml", Model.Devices)
</table>
PartialView:
#model IEnumerable<TestMVC.ViewModels.DevicesToFiscalizationViewModel>
#foreach(var item in Model)
{
<tbody>
<tr>
<td style="text-align:center">
<div class="checkbox">
#Html.EditorFor(m => item.Selected)
</div>
</td>
<td>
#Html.DisplayFor(m => item.DeviceName)
</td>
<td>
#Html.DisplayFor(m => item.SerialNumber)
</td>
<td>
#Html.DropDownList("LocalizationId", new SelectList(item.Localizations, "LocalizationId", "Name"), "Select", htmlAttributes: new { #class = "form-control", style = "width: 200px;" })
</td>
<td>
#Html.HiddenFor(m => item.DeviceId)
</td>
</tr>
</tbody>
Here is a screenshot of how it looks
click
and here is screenshot from debugger with bad result
bad
Based on my understating from your views, your issues is using different models for main view and partial view. You should use exactly the same model in both the model binding could update the model on server side. keep both models TestMVC.ViewModels.FiscalizationViewModel or IEnumerable<TestMVC.ViewModels.DevicesToFiscalizationViewModel>
It works :) Below I show how it looks after changes
main view:
#model TestMVC.ViewModels.FiscalizationViewModel
<div id="devicesToFiscalization">
#Html.Partial("~/Views/Fiscalizations/EditorTemplates/DevicesToFiscalizationViewModel.cshtml", Model)
</div>
Partial view:
#model TestMVC.ViewModels.FiscalizationViewModel
<table class="table">
<thead>
<tr>
<th>
Select
</th>
<th>
Name
</th>
<th>
Serial number
</th>
<th>
Localization
</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Devices.Count; i++)
{
<tr>
<td style="text-align:center">
<div class="checkbox">
#Html.EditorFor(m => m.Devices[i].Selected)
</div>
</td>
<td>
#Html.DisplayFor(m => m.Devices[i].DeviceName)
</td>
<td>
#Html.DisplayFor(m => m.Devices[i].SerialNumber)
</td>
<td>
#Html.DropDownListFor(m => m.Devices[i].LocalizationId, new SelectList(Model.Devices[i].Localizations, "LocalizationId", "Name"), "Select", htmlAttributes: new { #class = "form-control", style = "width: 200px;" })
</td>
<td>
#Html.HiddenFor(m => m.Devices[i].DeviceId)
</td>
</tr>
}
</tbody>
and CustomerChanged method:
public PartialViewResult CustomerChanged(int CustomerId)
{
var localizations = db.Localizations.Where(i => i.CustomerId == CustomerId).ToList();
var Devices = (from d in db.Devices
select new DevicesToFiscalizationViewModel()
{
DeviceId = d.DeviceId,
DeviceName = d.Name,
SerialNumber = d.SerialNumber,
}).ToList();
foreach (var item in Devices)
{
item.Localizations = localizations;
}
var fsc = new FiscalizationViewModel();
fsc.Devices = Devices;
return PartialView("~/Views/Fiscalizations/EditorTemplates/DevicesToFiscalizationViewModel.cshtml", fsc);
}
========================================================================
I'm trying to write this using EditorFor but I have a problem with correctly writing the CustomerChanged method that returns a list of Devices and not expecting this EditorTemplate that looks as follows:
#model TestMVC.ViewModels.DevicesToFiscalizationViewModel
<tr>
<td style="text-align:center">
<div class="checkbox">
#Html.EditorFor(m => m.Selected)
</div>
</td>
<td>
#Html.DisplayFor(m => m.DeviceName)
</td>
<td>
#Html.DisplayFor(m => m.SerialNumber)
</td>
<td>
#Html.DropDownListFor(m => m.LocalizationId, new SelectList(Model.Localizations, "LocalizationId", "Name"), "Select", htmlAttributes: new { #class = "form-control", style = "width: 200px;" })
</td>
<td>
#Html.HiddenFor(m => m.DeviceId)
</td>
</tr>
Main View:
<table class="table" id="devicesToFiscalization">
...
<tbody>
#Html.EditorFor(m => m.Devices)
</tbody>
</table>
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.
I have two tables. First is Development region and second is Zone. Zone has got RegionID as a foreign key. I would like to populate all the row from Zone table that is related with the Region selected from the dropdown list. I cannot figure out why the value is not being passed in url string. Please help me out and suggest the best way to accomplish it. Below are the models, controllers and view.
Model Zone
public class Zone
{
[Key]
public int ZoneID { get; set; }
[Required]
[Display(Name = "Zone Code")]
[RegularExpression(#"^[a-zA-Z]*$"), StringLength(5, ErrorMessage = "Code cannot be more than 5 charachter long")]
[Column("ZCode")]
public string ZoneCode { get; set; }
[Display(Name ="Zone"),RegularExpression(#"^[A-Z]+[a-z]*$"),Required]
public string ZoneName { get; set; }
public int RegionID { get; set; }
public virtual DevRegion devregion { get; set; }
[Required]
[Display(Name ="Active")]
public Boolean isActive { get; set; }
}
Model DevRegions
public class DevRegion
{
[Key]
public int RegionID { get; set; }
[Required]
[Display(Name = "Code")]
[RegularExpression(#"^[a-zA-Z]*$"), StringLength(5, ErrorMessage = "Code cannot be more than 5 charachter long")]
[Column("RCode")]
public string RegionCode { get; set; }
[Required]
[Display(Name ="Region")]
[Column("RName")]
[RegularExpression(#"^[A-Z]+[a-zA-Z\s-]*$", ErrorMessage ="Region can only consist of alphabets, space and dash")]
[StringLength(30,ErrorMessage ="Region cannot exceed 30 characters")]
public string RegionName { get; set; }
[Required]
[Display(Name ="Active")]
public Boolean isActive { get; set; }
}
ZonesController
public class ZonesController : Controller
{
private HuRISContext db = new HuRISContext();
// GET: Zones
public ActionResult Index(int? id)
{
ViewBag.RegionID = new SelectList(db.DevRegions, "RegionID", "RegionName");
var zones = db.Zones.Include(z => z.devregion).Where(x=>x.RegionID==(int)(id??x.RegionID));
return View(zones.ToList());
}
Index.cshtml
#model IEnumerable<HuRIS.Models.Zone>
....
<p>#Html.ActionLink("Create New", "Create")</p>
#using (Html.BeginForm("Index","Zones",FormMethod.Get))
{
#Html.AntiForgeryToken();
<div class="panel panel-info">
<div class="panel-body">
<div class="form-group center-block">
<label for="RegionID" class="control-label">Region:</label>
#Html.DropDownList("RegionID", null, "Show all Zones", htmlAttributes: new { #class = "form-control", #onchange = "this.form.submit();" })
</div>
</div>
</div>
}
<table class="table">
<tr>
<th>#Html.DisplayNameFor(model => model.devregion.RegionName)</th>
<th>#Html.DisplayNameFor(model => model.ZoneCode)</th>
<th>#Html.DisplayNameFor(model => model.ZoneName)</th>
<th>#Html.DisplayNameFor(model => model.isActive)</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.devregion.RegionName</td>
<td>#Html.DisplayFor(modelItem => item.ZoneCode)</td>
<td>#Html.DisplayFor(modelItem => item.ZoneName)</td>
<td>#Html.DisplayFor(modelItem => item.isActive)</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.ZoneID }) |
#Html.ActionLink("Details", "Details", new { id = item.ZoneID }) | #Html.ActionLink("Delete", "Delete", new { id = item.ZoneID })
</td>
</tr>
}
</table>
JQuery
$(document).ready(function () {
$(".form-control").change(function () {
$.ajax({
url: "~/ZonesController/Index",
type: 'GET',
cache: false,
data: { RegionID: $(".form-control").val() },
success: function (data) {
}
});
});
});
index method as shown below
public ActionResult Index()
{
ViewBag.Region = new SelectList(db.DevRegions, "RegionID", "RegionName");
var allzones = db.Zones.Include(z => z.devregion);
return View(allzones.ToList());
}
create new method as Shown below to accept the id selected on dropdown change event and create the partial view to load on the list of data from the table depending on what is selected on the dropdown:
public ActionResult ZoneList(int? id)
{
var zones = db.Zones.Include(z => z.devregion).Where(x => x.RegionID == (int)(id ?? x.RegionID));
return PartialView("~/Views/PartialViews/_ZoneList.cshtml", zones.ToList());
}
changed javascript as follows.
$("#Region").change(function () {
var selectedID = $(this).val();
$.get('/Zones/ZoneList/' + selectedID, function (data) {
$('.table').html(data);
//$('.table').fadeOut("linear");
//$('.table').fadeIn("linear");
});
});
});
on the index.cshtml changed the code as follows:
#model IEnumerable<HuRIS.Models.Zone>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken();
<div class="panel panel-info">
<div class="panel-body">
<div class="form-group center-block">
<label for="RegionID" class="control-label">Region:</label>
#Html.DropDownList("Region", null, "Show all Zones", htmlAttributes: new { #class = "form-control"})
</div>
</div>
</div>
}
#{
Html.RenderPartial("~/Views/PartialViews/_ZoneList.cshtml", Model);
}
partial view _ZoneList.cshtml
#model IEnumerable<HuRIS.Models.Zone>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.devregion.RegionName)
</th>
<th>
#Html.DisplayNameFor(model => model.ZoneCode)
</th>
<th>
#Html.DisplayNameFor(model => model.ZoneName)
</th>
<th>
#Html.DisplayNameFor(model => model.isActive)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.devregion.RegionName)
</td>
<td>
#Html.DisplayFor(modelItem => item.ZoneCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.ZoneName)
</td>
<td>
#Html.DisplayFor(modelItem => item.isActive)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.ZoneID }) |
#Html.ActionLink("Details", "Details", new { id = item.ZoneID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.ZoneID })
</td>
</tr>
}
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.