PartialView data not posting back to controller - asp.net-mvc

I am loading the partial view based on dropdownlist value as suggested in the following links. I am able to show partial View and enter values in textboxes. But when I postback, I am unable to get values in Controller. I am getting all other values except this partial view values
Render Partial View Using jQuery in ASP.NET MVC
div id="divFloorPlans"></div>
$('#ddlFloorPlans').change(function () {
var numberOfFloorPlans = $(this).val();
var data = { "id": numberOfFloorPlans };
$.ajax({
url: "FloorPlans",
type: "POST",
data: data, //if you need to post Model data, use this
success: function (result) {
$("#divFloorPlans").html("");
$("#divFloorPlans").html(result);
}
});
});
#model IList<ViewModels.FloorPlan>
#for (int i = 1; i <= Model.Count; ++i)
{
<div class="col-md-12" >
<div class="col-md-2" >
#Html.DropDownListFor(m => m[i - 1].Bedrooms, ViewData["Bedrooms"] as List<SelectListItem> })
</div>
<div class="col-md-2" >
#Html.DropDownListFor(m => m[i - 1].Bathrooms, ViewData["Bathrooms"] as List<SelectListItem> })
</div>
<div class="col-md-3" >
#Html.TextBoxFor(m => m[i - 1].MinPrice})
#Html.TextBoxFor(m => m[i - 1].MinPrice })
</div>
<div class="col-md-3">
#Html.TextBoxFor(m => m[i - 1].MinSqFt, new { #placeholder = "From" })
#Html.TextBoxFor(m => m[i - 1].MaxSqFt, new { #placeholder = "To"})
</div>
</div>
}
My Model looks like this.
public class ItemEditVM
{
public FloorPlan FloorPlan { get; set; }
public IList<FloorPlan> ListFloorPlans { get; set; }
}
My Controllers
//Partial View Returning Controller
[HttpPost]
public ActionResult FloorPlans(int id)
{
var model = new ItemEditVM();
model.NumOfFloorplans = id;
model.ListFloorPlans = new List<FloorPlan>();
for (int i = 0; i < id; i++)
{
model.ListFloorPlans.Add(new FloorPlan { FloorPlanName = "", Bathrooms = "", Bedrooms = "", MaxPrice = "", MinPrice = "", MaxSqFt = "", MinSqFt = "" });
}
return View("FloorPlan", model.ListFloorPlans);
}
//Create Controller
[HttpPost]
public ActionResult Create(ItemEditVM model)
{
if (ModelState.IsValid)
{
}
}

You partial views model is IList<FloorPlan> which is generating controls with
<input name="[0].MinPrice" ..>
<input name="[1].MinPrice" ..>
which would post back to IList<FloorPlan> model, but your method parameter is ItemEditVM model. You need to the partial view model to be #model ItemEditVM
In the GET method
return View("FloorPlan", model);
and in the view
#model ItemEditVM
#for (int i = 1; i <= Model.ListFloorPlans.Count; ++i)
{
....
#Html.TextBoxFor(m => m.ListFloorPlans[i - 1].MinPrice})
....
}
which will generate the correct name attributes for binding to your model
<input name="ListFloorPlans[0].MinPrice" ..>
<input name="ListFloorPlans[1].MinPrice" ..>

Related

BeginForm not showing initial Dropdown List Value

I am using BeginForm and the initial value of one of the Dropdown's is not being set properly. The value is held in a SelectLitemItem and is correctly shown in the preceding Table (in the Index view). The available values provided for list are also correct. It always defaults to "Create" which has a value of "1" even when it should be "Update" which has a value of "2".
The Model.RuleType.Value is shown correctly if I just display it on the form.
I cannot see what I'm doing wrong. I can see no duplicate ID/ Name and have tried including a Hidden field.
There is another dropdown that happens to use a common value for both Value and Text and that works.
Any ideas?
Thanks.
#model AMS.Web.Areas.Admin.Models.RuleActionModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true) #Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.RuleType, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.Partial("Partials/_RuleTypeDropdown") #Html.ValidationMessageFor(model => model.RuleType)
</div>
</div>
RuleTypeDropdown
#using Kendo.Mvc.UI;
#(Html.Kendo().DropDownList()
.Name("RuleType")
.DataTextField("Text")
.DataValueField("Value")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("RuleTypeList", "List", new { Area = "Admin" });
});
})
)
Model
public class RuleActionModel
{
public RuleActionModel() { }
public RuleActionModel(RuleAction ruleAction)
{
...
RuleType = new SelectListItem()
{
Value = ruleAction.RuleType.ToString(),
Text = ((RuleType)(ruleAction.RuleType)).EnumToString()
};
}
[Display(Name = "Type")]
public SelectListItem RuleType { get; set; }
Controller
public ActionResult Edit(Guid? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
RuleAction ruleAction = UnitOfWork.RuleActionRepository.FirstOrDefault(x => x.ID == id);
if (ruleAction == null)
{
return HttpNotFound();
}
var model = new RuleActionModel(ruleAction);
return View(model);
}

Sessions in MVC 5 asp.net

I am doing a project about an Chinese food ordering system, and I am wanting show selected items in a view on another page. I am trying to use sessions, but I keep getting different errors, like "The model item passed into the dictionary is of type" and "object reference is not set to an instance of an object". How can I select the data, and show them in a different view? The project is linked up to a database, the DishID and other instances should be connected through the database.
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using KinaRest.Models;
using KinaRest.View_Models;
using KinaRest.Infrastructure;
namespace KinaRest.Controllers
{
public class TakeawayController : Controller
{
private Basket basket = new Basket();
[ChildActionOnly]
public ActionResult BasketItemsList()
{
Basket basket = new Basket();
return View("_Basket", basket.Items);
}
// GET: /Takeaway/
private ChinaContext db = new ChinaContext();
[HttpGet]
public ActionResult Index()
{
return View(db.Dish.ToList());
}
[HttpPost]
public ActionResult Index(BasketItem basketItem)
{
//Repository repository = new Repository();
if (Session["Basket"] == null)
{
Session["Basket"] = new Basket();
}
else
{
basket = (Basket)Session["Basket"];
}
basket.AddItem(basketItem);
return View("Test");
}
}
}
Model 1: Basket
namespace KinaRest.Infrastructure
{
public class Basket
{
private List<BasketItem> items = new List<BasketItem>();
public List<BasketItem> Items { get { return items; } }
public void AddItem(BasketItem bi) {
items.Add(bi);
}
}
}
Model 2: BasketItem
namespace KinaRest.Infrastructure
{
public class BasketItem
{
public int DishId {get; set; }
public int Number { get; set; }
public decimal Price { get; set; }
}
}
In this view, we are trying to collect the data, such as the ID, the quantity(number) and price with a form:
#model IEnumerable<KinaRest.Models.Dish>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<div class="form-group">
#using (Html.BeginForm())
{
foreach (var item in Model)
{
<div class="col-md-10">
#Html.DisplayFor(modelItem => item.DishId)
</div>
<div class="col-md-10">
#Html.DisplayFor(modelItem => item.Title)
</div>
<div class="col-md-10">
#Html.DisplayFor(modelItem => item.Price)
</div>
<div class="col-md-10">
#Html.DisplayFor(modelItem => item.Description)
</div>
<div class="col-md-10">
#Html.DisplayFor(modelItem => item.Type.Type1)
</div>
<img src="#Url.Content("~/content/images/" + item.Image)" />
#Html.EditorFor(model => item.Number, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => item.Number, "", new { #class = "text-danger" })
<input type="submit" value="Tilføj" class="btn btn-default" />
}
}
</div>
In this view, we are trying to access the sessions data:
#model List<KinaRest.Infrastructure.BasketItem>
#{
ViewBag.Title = "Test";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Test</h2>
<ul>
#foreach (var item in Model)
{
<li>
#Html.DisplayFor(modelItem => item.Number)
</li>
}
</ul>
and yes, I am new to MVC and I am still learning. Hope you guys can help.
[HttpGet]
public ActionResult Order(int id)
{
Dish dish = db.Dish.Single(d=> d.DishId == id); //database call here
BasketItem basketItem = new BasketItem(){DishId = dish.?, Number = dish.?, Price = dish.Price }; // create a new BasketItem
Basket basket; //create reference outside if block
//Repository repository = new Repository();
if (Session["Basket"] == null)
{
basket = new Basket();
Session["Basket"] = basket;
}
else
{
basket = (Basket)Session["Basket"];
}
basket.AddItem(basketItem);
return View("Test", basket.Items); //or return View(((Basket)Session["Basket"]).Items); // give the view the data
}
take out the class field basket. As far as i know the controller is instanciated every time when a request is to be processed
View for ordering
#model IEnumerable<KinaRest.Models.Dish>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<table>
<tr><th></th><th>Dish</th><th></th></tr>
#foreach(var item in Model)
{
<tr><td><img src="#Url.Content("~/content/images/" + item.Image)" /></td><td>#html.displayfor(item => item.Name)</td><td>#Html.ActionLink("Add", "Order", "TakeAway", new {id = item.DishId})</td></tr>
}
</table>

How to create view for given model

I am new to asp .net mvc 4.0. i have given model. i am not getting how can i create view for model. I am facing problem at IList JournalEntries. other entry i am able to do.
public class Journal : BaseClass
{
public virtual string VoucherNo { get; set; }
public virtual DateTime VoucherDate { get; set; }
public string VoucherDateView {
get
{
return VoucherDate.ToShortDateString();
}
}
public IList<JournalEntry> JournalEntries { get; set; }
public IList<Ledger> Accounts { get; set; }
public double TotalAmount
{
get
{
double sum = 0;
if (JournalEntries != null && JournalEntries.Count>0)
foreach (var journal in JournalEntries)
sum = journal.Principal + journal.Interest+sum;
return sum;
}
}
}
I have tried below view but add entry doesn't works.
#model Sms.CoreSociety.Journal
#{
ViewBag.Title = "Create";
}
#{
string data = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model);
}
<script type="text/javascript">
$(document).ready(function () {
$('#document').validate();
$("#VoucherDate").mask("99/99/9999", { placeholder: " " });
function entryVm(entries) {
var self = this;
self.entryList = ko.observableArray(entries);
self.entry = ko.observable();
self.rowClick = function(entry1) {
alert("Delete alert");
self.dispatchList.remove(entry1);
};
self.addEntry = function() {
alert("Add alert");
this.entryList.push({ AccountName_AccountHead: "", DebitCredit: "", Principal: "0.0", Interest: "0.0", Narration: ""});
};
}
var models = #Html.Raw(Json.Encode(Model.JournalEntries)) ;
ko.applyBindings(new entryVm(models));
});
</script>
#using (Html.BeginForm(null, null, FormMethod.Post, new Dictionary<string, object>() { { "class", "form-horizontal" }, { "id", "document" } }))
{
#Html.ValidationSummary(true)
<fieldset>
<div class="row">
<div class="span1">
<label>Voucher No</label>
</div>
<div class="span5">
#Html.DisplayFor(model => model.VoucherNo)
</div>
</div>
<div class="row">
<div class="span1">
<label>Voucher Date</label>
</div>
<div class="span5">
#Html.TextBoxFor(model => model.VoucherDate, "{0:dd/MM/yyyy}", new Dictionary<string, object>() { { "class", "required" } })
</div>
</div>
<div class="row">
<div class="span1">
<label>Amount</label>
</div>
<div class="span5">
#Html.DisplayFor(model => model.TotalAmount)
</div>
</div>
<input type="submit" value="Save" class="btn" id="submit"/>
#if (Model.Id != new Guid())
{
<div style="float: right">
<a class="btn btn-danger" href='#Url.Action("Delete")/#Model.Id' aria-hidden="true">Delete</a>
</div>
}
</fieldset>
}
<h4>Journal Entry</h4>
<p >Entry for<span data-bind="text: entryList().length"> </span> entry(s)</p>
<button data-bind="click: addEntry" class="btn">Add Record</button>
<table>
<tbody data-bind="template: { name: 'entryRowTemplate', foreach: entryList }"></tbody>
</table>
<script type="text/html" id="entryRowTemplate">
<tr>
<td>AccountName_AccountHead: \$ <input data-bind="value: AccountName.AccountHead"/> </td>
<td>DebitCredit: \$ <input data-bind="value: DebitCredit"/></td>
<td>Principal: \$ <input data-bind="value: Principal"/></td>
<td>Interest: \$ <input data-bind="value: Interest"/></td>
<td>Narration: \$ <input data-bind="value: Narration"/></td>
<td>Delete</td>
</tr>
</script>
below is my Journal controller
using System;
using System.Linq;
using System.Web.Mvc;
using Sms.CoreSociety;
using System.Collections.Generic;
namespace SmsModernUI.Controllers
{
public class JournalController : BaseController
{
//
// GET: /AccountGroup/
public ActionResult Index()
{
var journals = Repository.GetAll<Journal>().OrderBy(x => x.VoucherNo);
return View(journals);
}
public ActionResult Create(Guid id)
{
if (id == new Guid())
{
var journal = new Journal();
string lastvoucherno = Repository.GetAll<Journal>().OrderBy(x => x.VoucherNo).Last().VoucherNo;
journal.VoucherNo = (int.Parse(lastvoucherno) + 1).ToString();
journal.VoucherDate = System.DateTime.Now;
journal.JournalEntries = new List<JournalEntry>();
journal.Accounts = Repository.GetAll<Ledger>();
return PartialView(journal);
}
var journal1 = Repository.Get<Journal>(id);
journal1.JournalEntries = Repository.GetAll<JournalEntry>(x => x.Journal.Id == id);
journal1.Accounts = Repository.GetAll<Ledger>();
return PartialView(journal1);
}
[HttpPost]
[ValidateInput(false)]
public ActionResult Create(Journal journal)
{
if (journal.Id == new Guid())
{
var jj = Repository.Save(journal);
foreach (var journalentry in journal.JournalEntries)
{
journalentry.Id = jj.Id;
Repository.Save(journalentry);
}
}
else
{
Journal jr = Repository.Get<Journal>(journal.Id);
var entries = Repository.GetAll<JournalEntry>(x=>x.Journal.Id == journal.Id);
foreach (var entry in entries)
{
Repository.Delete(entry);
}
var jj = Repository.Save(journal);
foreach (var journalentry in journal.JournalEntries)
{
journalentry.Id = jj.Id;
Repository.Save(journalentry);
}
}
return RedirectToAction("Index");
}
public ActionResult Index1()
{
Journal journal1 = Repository.Get<Journal>(new Guid("7A6EEBBC-2F3A-4A27-ACF8-A1D40115A68F"));
journal1.JournalEntries = Repository.GetAll<JournalEntry>(x => x.Journal.Id == journal1.Id);
journal1.Accounts = Repository.GetAll<Ledger>();
return View(journal1);
}
public ActionResult Delete(Guid id)
{
Journal jr = Repository.Get<Journal>(id);
var entries = Repository.GetAll<JournalEntry>(x => x.Journal.Id == jr.Id);
foreach (var entry in entries)
{
Repository.Delete(entry);
}
var result = Repository.Delete(jr);
return RedirectToAction("Index");
}
[HttpPost]
public ActionResult Create1(Journal journal)
{
var temp = journal;
return RedirectToAction("Create",journal.Id);
}
}
}
Views are not genereted from models. You need Controller Action method to pass your model to View.
public ActionResult()
{
var model = new Journal
{
//**define here value of model's properties, that you need in View
}
return View(model);
}
EDITED: After your addition.
I would devide it into two parts. Create ViewModel and pass it from View To Controller.
public JurnalViewModel
{
public Journal journal {get; set;}
public IList<JournalEntry> JournalEntries {get; set;}
}
Than in Create action first create journal and after foreach JournalEntries in model create new JournalEntry.
EDITED 2 To your comment. Quick sample:
[HttpPost]
public ActionResult Create (JurnalViewModel model)
{
var journal = new Journal();
db.Journals.Add(journal);
journal.name = model.journal.name
.....
//**some code
db.SaveChanges()
foreach(var item in model.JournalEntries )
{
var entry = new JournalEntry()
db.JournalEntries .Add(entry);
entry.property = item.property;
....
//**some code
db.SaveChanges()
}
}
Your problem is that you have no class constructor for JournalEntries.
public Journal()
{
JournalEntries = new List<JournalEntry>();
Accounts = new List<Ledger>();
}
Right click to your Action method inside controller and click add view then check create strongly typed-view checkbox then choose your desired model from dropdown in displayed dialogue box

problems with html helper method

I can't figure out how to send a parameter from a dropdownlist to my model. Could someone please show me an example of how to do this?
As always you start by defining a model:
public class MyViewModel
{
public string SelectedValue { get; set; }
public SelectList Items
{
get
{
return new SelectList(new[]
{
new SelectListItem { Value = "1", Text = "item 1" },
new SelectListItem { Value = "2", Text = "item 2" },
new SelectListItem { Value = "3", Text = "item 3" },
}, "Value", "Text");
}
}
}
Controller:
public class HomeController: Controller
{
public ActionResult Index()
{
var model = new MyViewModel();
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
// You will get the selected value inside model.SelectedValue here
// => do something with it
....
}
}
Strongly typed view:
<% using (Html.BeginForm()) { %>
<%= Html.DropDownListFor(x => x.SelectedValue, Model.Items) %>
<input type="submit" value="OK" />
<% } %>
public ActionResult Edit(int id)
{
Affiliate affiliate = affiliateRepository.GetAffiliate(id);
List<SelectListItem> StateList = new List<SelectListItem>();
SelectListItem item;
Dictionary<string, string> dictState = S127Global.Misc.getStates();
foreach (KeyValuePair<string, string> k in dictState)
{
item = new SelectListItem();
item.Text = k.Value;
item.Value = k.Key;
StateList.Add(item);
}
item = new SelectListItem();
item.Text = " - Select State - ";
item.Value = "";
StateList.Insert(0, item);
//create new select list with affiliate.state as the selected value in ViewData
ViewData["State"] = new SelectList(StateList.AsEnumerable(), "Value", "Text",affiliate.State);
return View(affiliate);
}
code for view
<div class="editor-label">
<%: Html.LabelFor(model => model.State) %>
</div>
<div class="editor-field">
<%: Html.DropDownList("State")%>
<%: Html.ValidationMessageFor(model => model.State) %>
</div>

MVC - Problem with DataBinding to a Collection using a Custom Template

I am trying to bind to a Model that has a collection property, specifically a List. For the purposes of this example, this represents a list of user roles:
public class RolesModel
{
private List<SelectListItem> _Roles = null;
public string Name { get; set; }
public List<SelectListItem> Roles
{
get {
if (_Roles == null) { _Roles = new List<SelectListItem>(); }
return _Roles;
}
set { _Roles = value; }
}
}
I am binding this to a strongly-typed view via the following Controller:
public class TestController : Controller
{
RolesModel myModel = new RolesModel();
[HttpGet]
public ActionResult Edit()
{
myModel.Name = "Joe Bloggs";
myModel.Roles = new List<SelectListItem>
{
new SelectListItem { Value = "1", Text = "Member", Selected = true },
new SelectListItem { Value = "2", Text = "Manager", Selected = true },
new SelectListItem { Value = "3", Text = "Administrator", Selected = false }
};
return View(myModel);
}
[HttpPost]
public ActionResult Edit(RolesModel m)
{
// !!! m.Roles is always empty !!!
return View("Results", m);
}
}
This then invokes the following view:
#model MyProject.WebUI.Models.RolesModel
#using (Html.BeginForm())
{
<p>
#Html.LabelFor(m => m.Name)
#Html.EditorFor(m => m.Name)
</p>
<div>
#Html.EditorFor(m => m.Roles, "CheckBoxList")
</div>
<p>
<input type="submit" value="Save" />
</p>
}
Note the template specific call to my custom editor template in '/Views/Shared/EditorTemplates/CheckBoxList.cshtml' this looks like this:
#model List<System.Web.Mvc.SelectListItem>
<h3>Type: #Html.LabelFor(m => m)</h3>
<ul>
#for (int i = 0; i < Model.Count; i++)
{
<li>
#Html.CheckBoxFor(m => m[i].Selected)
#Html.LabelFor(m => m[i].Selected, Model[i].Text)
#Html.HiddenFor(m => m[i].Value)
</li>
}
</ul>
The idea being that each SelectListItem is represented by the Html rendered by the loop.
The first part of the process appears to work correctly, The form is presented as expected and you can update the 'Name' text box and the check/uncheck the checkboxes.
The problem is that when the form is posted back to the controller, the Roles collection is never populated.
I'm new to MVC and thought that the framework actually re-constructed the model data from the post via the enforced form element naming convention. I'm obviously missing an important point and I'm hoping someone can point me in the right direction.
Thanks, and apologies for the long post.
Here's how you could proceed:
#model MyProject.WebUI.Models.RolesModel
#using (Html.BeginForm())
{
<p>
#Html.LabelFor(m => m.Name)
#Html.EditorFor(m => m.Name)
</p>
<div>
<ul>
#Html.EditorFor(m => m.Roles)
</ul>
</div>
<p>
<input type="submit" value="Save" />
</p>
}
and inside the EditorTemplate (/Views/Shared/EditorTemplates/SelectListItem.cshtml):
#model System.Web.Mvc.SelectListItem
<h3>Type: #Html.LabelFor(m => m)</h3>
<li>
#Html.CheckBoxFor(m => m.Selected)
#Html.LabelFor(m => m.Selected, Model.Text)
#Html.HiddenFor(m => m.Value)
</li>
Notice the simplification of the editor template. It no longer takes a List<SelectListItem> as model but simply a SelectListItem. It will automatically be invoked for each element of the Roles collection so that you don't need to write any loops. Just follow the conventions.
I would also simplify your view model like this:
public class RolesModel
{
public string Name { get; set; }
public IEnumerable<SelectListItem> Roles { get; set; }
}
and your controller:
public class TestController : Controller
{
public ActionResult Edit()
{
var myModel = new RolesModel
{
Name = "Joe Bloggs",
Roles = new[]
{
new SelectListItem { Value = "1", Text = "Member", Selected = true },
new SelectListItem { Value = "2", Text = "Manager", Selected = true },
new SelectListItem { Value = "3", Text = "Administrator", Selected = false }
}
};
return View(myModel);
}
[HttpPost]
public ActionResult Edit(RolesModel m)
{
// m.Roles should be correctly bound
return View("Results", m);
}
}

Resources