How to send model from parent to child - c#

I have question about how to send model from parent to child using partial view and fancybox.
Here is my model
public class SampleHeaderViewModels
{
[Display(Name = "ID")]
public int intID { get; set; }
[Display(Name = "Field 1")]
public string txtField1 { get; set; }
[Display(Name = "Field 2")]
public string txtField2 { get; set; }
}
public class SampleDetailViewModels
{
[Display(Name = "ID")]
public int intID { get; set; }
[Display(Name = "Line")]
public int intLine { get; set; }
[Display(Name = "Detail 1")]
public string txtDetail1 { get; set; }
}
public class SampleViewModels
{
public SampleHeaderViewModels Header { get; set; }
public List<SampleDetailViewModels> Detail { get; set; }
public SampleDetailViewModels OneDetai { get; set; }
public SampleViewModels()
{
Header = new SampleHeaderViewModels();
Detail = new List<SampleDetailViewModels>();
OneDetai = new SampleDetailViewModels();
}
}
Here is my Index View:
<div class="row">
<div class="block">
<div class="block-content controls">
<div class="col-md-6">
<div class="row-form">
<div class="col-md-4">
#Html.LabelFor(m => m.Header.txtField1, htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-8">
#Html.HiddenFor(m => m.Header.intID)
#Html.TextBoxFor(m => m.Header.txtField1, htmlAttributes: new { #class = "form-control" })
</div>
</div>
<div class="row-form">
<div class="col-md-4">
#Html.LabelFor(m => m.Header.txtField2, htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-8">
#Html.TextBoxFor(m => m.Header.txtField2, htmlAttributes: new { #class = "form-control" })
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="block">
<div class="block-content controls">
<div class="col-md-12">
<div class="row-form">
<table id="tbDataTable" class="table table-bordered">
<thead>
<tr>
<td>
#Html.LabelFor(m => m.Detail.FirstOrDefault().intLine)
</td>
<td>
#Html.LabelFor(m => m.Detail.FirstOrDefault().txtDetail1)
</td>
</tr>
</thead>
<tbody>
#if (Model.Detail != null)
{
foreach (var item in Model.Detail)
{
<tr>
<td>
#Html.DisplayFor(m => item.intLine)
</td>
<td>
#Html.DisplayFor(m => item.txtDetail1)
</td>
</tr>
}
}
</table>
</div>
<div class="row-form">
<div class="col-md-2">
<button type="button" id="btnAddDetail" class="btn btn-info">Add Detail</button>
</div>
</div>
</div>
</div>
</div>
</div>
And my Index Have javascript:
<script>
$("#btnAddDetail").click(function () {
debugger;
var model = #Html.Raw(Json.Encode(Model));
$.ajax({
type: 'POST',
contentType: 'application/json',
url: '/Sample/ViewDetail',
//data: $('#form1').serialize(),
data: JSON.stringify(model),
contentType: "application/json; charset=utf-8",
datatype: 'JSON',
success: function (data) {
// on success, post returned data in fancybox
$.fancybox.open(data,
{
closeClickOutside: false,
iframe: {
preload: true
}
}
); // fancybox
},
error: function (data) {
console.log(data);
}
});
});
</script>
Here is my Partial View:
<div class="col-md-6">
<div class="row-form">
<div class="col-md-4">
#Html.LabelFor(m => m.OneDetai.intLine, htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-8">
#Html.TextBoxFor(m => m.OneDetai.intLine, htmlAttributes: new { #class = "form-control" })
</div>
</div>
<div class="row-form">
<div class="col-md-4">
#Html.LabelFor(m => m.OneDetai.txtDetail1, htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-8">
#Html.TextBoxFor(m => m.OneDetai.txtDetail1, htmlAttributes: new { #class = "form-control" })
</div>
</div>
</div>
<div class="row-form">
<div class="col-md-2">
<button type="submit" id="btnAddLine" class="btn btn-info">Add Detail</button>
</div>
</div>
And this is my Controller
public ActionResult Index()
{
return View(new SampleViewModels());
}
[HttpPost]
public ActionResult ViewDetail(SampleViewModels obj)
{
return PartialView("AddDetail", obj);
}
public ActionResult AddDetail(SampleViewModels obj)
{
obj.Detail.Add(obj.OneDetail);
return View("Index", obj);
}
The idea is: In order to add new detail, I have to click btnAddDetail. And it will open popup. I have to fill the popup and click btnAddLine in child form. And the data will be appear in datatable.
The question is, how I can send my Parent Model to Child model using ajax?
When the button btnAddDetail in Index triggered, I tried to send my model in JSON, but its always send the FIRST STATE of my model. If I set value in Field 1 and Field 2, and press btnAddDetail, my ViewDetail Controller always get null model. Field1 = null, Field2 = null.
I've tried data: $('#form1').serialize(), to send my Model, It won't send my Detail Model. It just send my Header model.
Is there any way to send my Model to partial view, and send it back to my parent view?
Please help me, I haven't find any solution yet.
Thank you.

var model = #Html.Raw(Json.Encode(Model));
will not work, you will always get null...
if you have to make ajax post, you should do this to get values
for textbox values give them id and set your json
var model = {
"Header": {
"intID": 0,
"txtField1": $("#id-textField1").val(),
"txtField2": $("#id-textField2").val(),
},
"Detail": [],
"OneDetai": {
"intID": 0,
"intLine": 0,
"txtDetail1": null
}
}

Related

Modal Bootstrap on ASP.NET MVC

I trying to do a responsive async page with Modal bootstrap, it´s things all right, although when a save object on modal form, is did a update, but the return is to a json page:
The Controller Method returns a Json
using CaelumEstoque.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace CaelumEstoque.Controllers
{
public class ProdController : Controller
{
public static List<Prod> _listaProdutos = new List<Prod>()
{
new Prod { Codigo=01, Descricao="Produto 1", Preco=10 },
new Prod { Codigo=02, Descricao="Produto 2", Preco=15 },
new Prod { Codigo=03, Descricao="Produto 3", Preco=20 }
};
public ActionResult Index()
{
IList<Prod> lista = _listaProdutos;
return View(lista);
}
public ActionResult Details(int id)
{
var existe = _listaProdutos.Find(x => x.Codigo == id);
ViewBag.Detalhes = existe;
return View("parcial", existe);
}
public ActionResult Edit(int id)
{
var existe = _listaProdutos.Find(x => x.Codigo == id);
return View(existe);
}
public ActionResult ParcialEdit(Prod p)
{
var registro = _listaProdutos.Find(x => x.Codigo == p.Codigo);
registro.Descricao = p.Descricao;
registro.Preco = p.Preco;
return Json(registro);
}
public ActionResult parcial()
{
return View();
}
}
}
My Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace CaelumEstoque.Models
{
public class Prod
{
public int Codigo { get; set; }
public string Descricao { get; set; }
public double Preco { get; set; }
}
}
Index View:
#model IEnumerable<CaelumEstoque.Models.Prod>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Codigo)
</th>
<th>
#Html.DisplayNameFor(model => model.Descricao)
</th>
<th>
#Html.DisplayNameFor(model => model.Preco)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr id="prod#(item.Codigo)">
<td>
#Html.DisplayFor(modelItem => item.Codigo)
</td>
<td>
#Html.DisplayFor(modelItem => item.Descricao)
</td>
<td>
#Html.DisplayFor(modelItem => item.Preco)
</td>
<td>
Detalhe
<i class="glyphicon glyphicon-edit"></i>
#*<button class="btn btn-default details" data-id="#item.Codigo"><i class="glyphicon glyphicon-file"></i></button>
<button class="btn btn-danger delete" data-id="#item.Codigo"><i class="glyphicon glyphicon-trash"></i></button>
<button class="btn btn-primary edit" data-id="#item.Codigo"><i class="glyphicon glyphicon-edit"></i></button>*#
</td>
</tr>
}
</table>
<div class="modal" id="modal">
</div>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script>
$(function () {
$('.details').click(function () { // class name selector
var url = $(this).data('url'); // use data(), not attr()
$("#modal").load(url, function () {
$("#modal").modal("show");
})
});
})
/*
$(".edit").click(function () {
var url = $(this).data('url'); // use data(), not attr()
$("#modal").load(url, function () {
$("#modal").modal("show");
})
})
*/
$("#.edit").click(function () {
$.ajax({
type: "POST",
url: "",
data: $('#modal').serialize(),
success: function (data) {
alert('Registro salvo com sucesso.');
$('#modal').modal('hide');
},
error: function (data) {
alert('Erro ao Salvar Registro.');
}
});
});
</script>
Modal View:
#model CaelumEstoque.Models.Prod
#{
Layout = null;
}
<div class="modal-dialog">
<div class="modal-content">
#using (Ajax.BeginForm("ParcialEdit", "Prod", new AjaxOptions { UpdateTargetId = "Error", InsertionMode = InsertionMode.Replace, OnSuccess = "OnSuccess(data)" }))
{
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title">Editar produto</h4>
</div>
<div class="modal-body">
<div class="form-horizontal">
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Codigo, new { #class = "control-label col-md-3" })
<div class="col-md-9">
#Html.TextBoxFor(model => model.Codigo, new { #class = "form-control", #readonly = "readonly" })
#Html.ValidationMessageFor(model => model.Codigo)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Descricao, new { #class = "control-label col-md-3" })
<div class="col-md-9">
#Html.TextBoxFor(model => model.Descricao, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Descricao)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Preco, new { #class = "control-label col-md-3" })
<div class="col-md-9">
#Html.TextBoxFor(model => model.Preco, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Preco)
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" value="Salvar" class="btn btn-primary salvar" />
#*<input type="button" value="Salvar" class="btn btn-primary salvar" data-url="#Url.Action("ParcialEdit", "Prod", new {p = Model })" /> *#
<input type="button" value="Cancelar" class="btn btn-default" data-dismiss="modal" />
</div>
}
</div>
</div>
<script>
</script>
I want to know what is my mistake
Thank you

How to avoid multiple submit of form in ASP.NET MVC?

I tried to write a code and scripts using ASP.NET MVC 5. Was I use modal to do Create, Update, and Delete functionality which is working properly but when it comes with Creating, and Updating because I enable remote validations, it works at first but suddenly when you click again the submit button it will submit or post the data. In short, my validation is not working. Please, I need help.
Model:
[Key]
[Display(Name = "ID")]
[Column("LAND_TYPE_CAT_ID", Order = 0, TypeName = "bigint")]
public long CategoryId { get; set; }
[Display(Name = "Category Name")]
[StringLength(100)]
[Column("LAND_TYPE_CAT", Order = 1, TypeName = "nvarchar")]
public string CategoryName { get; set; }
[Display(Name = "Description")]
[StringLength(255)]
[Column("LAND_TYPE_CAT_DESC", Order = 2, TypeName = "nvarchar")]
public string CategoryDescription { get; set; }
[Display(Name = "Created Date")]
[Column("CREATE_DATE", Order = 3, TypeName = "datetime")]
public DateTime? CreateDate { get; set; }
[Display(Name = "Modified Date")]
[Column("MODIFIED_DATE", Order = 4, TypeName = "datetime")]
public DateTime? ModifiedDate { get; set; }
[Display(Name = "Last Modified By")]
[StringLength(255)]
[Column("LAST_MODIFIED_BY", Order = 5, TypeName = "nvarchar")]
public string LastModifiedBy { get; set; }
ViewModels:
For Create:
[Display(Name = "Category Name")]
[Required(ErrorMessage = "This field is required.")]
[Remote("ValidateCreate", "Category", ErrorMessage = "This type already exists.")]
public string CategoryName { get; set; }
For Update:
[Display(Name = "Category Name")]
[Required(ErrorMessage = "This field is required.")]
[Remote("ValidateEdit", "Category", AdditionalFields = "CategoryId, CategoryName",
ErrorMessage = "This type already exists.")]
public string CategoryName { get; set; }
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(LandTypeCategoryCreateViewModels viewModel)
{
if (ModelState.IsValid)
{
var vm = new LandTypeCategory
{
CategoryName = viewModel.CategoryName,
CategoryDescription = viewModel.CategoryDescription,
CreateDate = DateTime.Now,
LastModifiedBy = "Tester"
};
_context.LandTypeCategories.Add(vm);
await _context.SaveChangesAsync();
TempData["Created"] = "New category type added.";
var url = Url.Action("Index", "Category", new {id = viewModel.CategoryId});
return Json(new {success = true, url});
}
return PartialView("_Create", viewModel);
}
public async Task<ActionResult> Edit(long? id)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var vm = await _context.LandTypeCategories.FindAsync(id);
if (vm == null)
return HttpNotFound();
var viewModel = new LandTypeCategoryEditViewModels
{
CategoryId = vm.CategoryId,
CategoryName = vm.CategoryName,
CategoryDescription = vm.CategoryDescription
};
return PartialView("_Edit", viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(LandTypeCategoryEditViewModels viewModel)
{
if (ModelState.IsValid)
{
var vm =
await _context.LandTypeCategories.SingleAsync(x => x.CategoryId == viewModel.CategoryId);
vm.CategoryName = viewModel.CategoryName;
vm.CategoryDescription = viewModel.CategoryDescription;
vm.ModifiedDate = DateTime.Now;
vm.LastModifiedBy = "Modify Tester";
_context.Entry(vm).State = EntityState.Modified;
await _context.SaveChangesAsync();
TempData["Updated"] = "Category type updated.";
var url = Url.Action("Index", "Category", new {id = viewModel.CategoryId});
return Json(new {success = true, url});
}
return PartialView("_Edit", viewModel);
}
Remote Validation:
public async Task<JsonResult> ValidateCreate(string CategoryName)
{
return
Json(
await _context.LandTypeCategories.AllAsync(
c => c.CategoryName.ToLower() != CategoryName.ToLower()), JsonRequestBehavior.AllowGet);
}
public async Task<JsonResult> ValidateEdit(int CategoryId, string CategoryName)
{
var category = await _context.LandTypeCategories.FindAsync(CategoryId);
var result = true;
if (category.CategoryName.ToLower() != CategoryName.ToLower())
result =
await _context.LandTypeCategories.AllAsync(
c => c.CategoryName.ToLower() != CategoryName.ToLower());
return Json(result, JsonRequestBehavior.AllowGet);
}
Index.cshtml
#model IEnumerable<MvcPPT.Models.LandTypeCategory>
#{
ViewBag.Title = "Category";
}
<div class="container">
<br />
<br />
<br />
#Html.ActionLink("Add New", "Create", "Category", new { ViewBag.CategoryId }, new { data_modal = "", #class = "btn btn-primary", style = "position: absolute;background-color: #3498db; border-color: #3498db;" })
<table class="table table-hover table-bordered" id="same-datatable" style="font-size: smaller; width: 100%;">
<thead>
<tr>
<th>#Html.DisplayNameFor(model => model.CategoryId)</th>
<th>#Html.DisplayNameFor(model => model.CategoryName)</th>
<th>#Html.DisplayNameFor(model => model.CategoryDescription)</th>
<th>#Html.DisplayNameFor(model => model.CreateDate)</th>
<th>#Html.DisplayNameFor(model => model.ModifiedDate)</th>
<th>#Html.DisplayNameFor(model => model.LastModifiedBy)</th>
<th>Action</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.CategoryId)</td>
<td>#Html.DisplayFor(modelItem => item.CategoryName)</td>
<td>#Html.DisplayFor(modelItem => item.CategoryDescription)</td>
<td>#Html.DisplayFor(modelItem => item.CreateDate)</td>
<td>#Html.DisplayFor(modelItem => item.ModifiedDate)</td>
<td>#Html.DisplayFor(modelItem => item.LastModifiedBy)</td>
<td>
#Html.ActionLink("Edit", "Edit", "Category", new { id = item.CategoryId }, new { data_modal = "", #class = "btn btn-warning btn-xs" })
#Html.ActionLink("Delete", "Delete", "Category", new { id = item.CategoryId }, new { data_modal = "", #class = "btn btn-danger btn-xs" })
</td>
</tr>
}
</tbody>
</table>
</div>
<div id="myModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div id="myModalContent"></div>
</div>
</div>
</div>
_Create.cshtml
#model MvcPPT.ViewModels.LandTypeCategoryCreateViewModels
<div class="modal-header" style="background-color: #3498db; color: #fff;">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Add New Category Type</h4>
</div>
#using (Html.BeginForm())
{
<div class="modal-body">
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new {#class = "text-danger"})
<div class="form-group">
#Html.LabelFor(model => model.CategoryName, new {#class = "control-label col-md-4"})
<div class="col-md-8">
#Html.EditorFor(model => model.CategoryName, new {htmlAttributes = new {#class = "form-control"}})
#Html.ValidationMessageFor(model => model.CategoryName, "", new {#class = "text-danger"})
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CategoryDescription, new {#class = "control-label col-md-4"})
<div class="col-md-8">
#Html.EditorFor(model => model.CategoryDescription, new {htmlAttributes = new {#class = "form-control"}})
#Html.ValidationMessageFor(model => model.CategoryDescription, "", new {#class = "text-danger"})
</div>
</div>
<div class="modal-footer" style="padding-right: 0px;">
<input class="btn btn-success" type="submit" value="Save"/>
<button class="btn btn-default" type="button" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
}
#Scripts.Render("~/bundles/jqueryval")
_Edit.cshtml
#model MvcPPT.ViewModels.LandTypeCategoryCreateViewModels
<div class="modal-header" style="background-color: #3498db; color: #fff;">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Add New Category Type</h4>
</div>
#using (Html.BeginForm())
{
<div class="modal-body">
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new {#class = "text-danger"})
<div class="form-group">
#Html.LabelFor(model => model.CategoryName, new {#class = "control-label col-md-4"})
<div class="col-md-8">
#Html.EditorFor(model => model.CategoryName, new {htmlAttributes = new {#class = "form-control"}})
#Html.ValidationMessageFor(model => model.CategoryName, "", new {#class = "text-danger"})
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CategoryDescription, new {#class = "control-label col-md-4"})
<div class="col-md-8">
#Html.EditorFor(model => model.CategoryDescription, new {htmlAttributes = new {#class = "form-control"}})
#Html.ValidationMessageFor(model => model.CategoryDescription, "", new {#class = "text-danger"})
</div>
</div>
<div class="modal-footer" style="padding-right: 0px;">
<input class="btn btn-success" type="submit" value="Save"/>
<button class="btn btn-default" type="button" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
}
#Scripts.Render("~/bundles/jqueryval")
jQuery How Modal Call:
// Add new
$.ajaxSetup({ cache: false });
$("a[data-modal]").on("click",
function (e) {
$("#myModalContent").load(this.href,
function () {
$("#myModal").modal({
keyboard: true
},
"show");
bindForm(this);
});
return false;
});
function bindForm(dialog) {
$("form", dialog).submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (result.success) {
$("#myModal").modal("hide");
window.location.reload();
} else {
$("#myModalContent").html(result);
bindForm(dialog);
}
}
});
return false;
});
}
since both create and edit forms are partial views which i am guessing will render on same Main view i will advice you to remove the
#Scripts.Render("~/bundles/jqueryval")
from both partial pages and add the line in the top of main page since when you click the create button it will load the script bundle and again when you click the edit it will load them for the 2nd time
next is properly write the #gtml.begin form tags like
#using (Html.BeginForm(ActionName , ControllerName, FormMethod.Post))
i am not sure how is your form post is workng now
Option 1:
You can disable the button once it is submitted then.
$('form').submit(function() {
$(this).find(':submit').attr('disabled', 'disabled');
});
Option 2:
By creating a action filter. (So here you can validate duplication of anti-forgery token.)
How do I prevent multiple form submission in .NET MVC without using Javascript?

Post Updated readonly values to Action in MVC

I have below form which is of method=get.
#using (Html.BeginForm("Search", "Home", FormMethod.Get, htmlAttributes: new { #class = "main-search", id = "frmsearch", role = "form" })) {
<div class="row">
<div class="col-md-3 col-sm-3">
<div class="form-group">
<label for="type">Property Type</label>
#Html.ListBoxFor(m => m.searchModel.CategoriesId, Model.searchModel.Categories, htmlAttributes: new { id = "type", multiple = "multiple", #class = "animate", data_transition_parent = ".dropdown-menu", title = "All" })
</div>
<!-- /.form-group -->
</div>
<div class="col-md-3 col-sm-3">
<div class="form-group">
<label for="location">Location</label>
#Html.DropDownListFor(m => m.searchModel.LocationID, Model.searchModel.Locations, htmlAttributes: new { id = "location", multiple = "multiple", #class = "animate", data_transition_parent = ".dropdown-menu", title = "All" })
</div>
<!-- /.form-group -->
</div>
<div class="col-md-3 col-sm-3">
<div class="form-group">
<label>Status</label>
#Html.DropDownListFor(m => m.searchModel.StatusID, Model.searchModel.Status, htmlAttributes: new { id = "status", multiple = "multiple", #class = "animate", data_transition_parent = ".dropdown-menu", title = "All" })
</div>
<!-- /.form-group -->
</div>
<div class="col-md-2 col-sm-3">
<div class="form-group">
<label>Price</label>
<div class="ui-slider" id="price-slider-category" data-value-min="#Model.searchModel.MinPrice" data-value-max="#Model.searchModel.MaxPrice" data-value-type="price" data-currency="₹" data-currency-placement="before">
<div class="values clearfix">
#Html.TextBoxFor(m => m.searchModel.MinPrice, htmlAttributes: new { id = "value-min", #class = "value-min", name = "value-min[]", #readonly = "readonly", style = "padding:0px" })
#Html.TextBoxFor(m => m.searchModel.MaxPrice, htmlAttributes: new { id = "value-max", #class = "value-max", name = "value-max[]", #readonly = "readonly", style = "padding:0px" })
</div>
<div class="element"></div>
</div>
</div>
<!-- /.form-group -->
</div>
<div class="col-md-1 col-sm-3">
<div class="form-group">
<label></label>
<button type="submit" style="color:white" id="searchSubmit" class="btn btn-block blue waves-effect">
<i class="fa fa-search"> </i>
</button>
</div>
<!-- /.form-group -->
</div>
<!--/.col-md-6-->
</div>
<!--/.row-->
}
and I have this JS to post form values through AJAX
$(document).on('click', '#searchSubmit', function (e) {
var _form = $(this).closest('form');
var _url = _form.attr('action');
var formData = _form.serialize();
var request = $.get(_url, formData);
request.complete(function (response) {
})
})
Here is my model
public class SearchFilters
{
public SearchFilters()
{
MinPrice = 10000;
MaxPrice=8000000;
}
public IEnumerable<SelectListItem> Categories { get; set; }
public int[] CategoriesId { get; set; }
public IEnumerable<SelectListItem> Locations { get; set; }
public int[] LocationID { get; set; }
public IEnumerable<SelectListItem> Status { get; set; }
public int[] StatusID { get; set; }
public int MinPrice { get; set; }
public int MaxPrice { get; set; }
}
and this is my controller method to process the search request.
[HttpGet]
public ActionResult Search([Bind(Prefix = "searchModel")]SearchFilters smodel)
{
ProjectsViewModel model = new ProjectsViewModel();
//search db and fill model
return PartialView("_PropertyDetails", model);
}
The UI rendering happens for min and max value using noUiSlider plugin and thus inputs are readonly but gets updated through update option of noUiSlider. But whenever model is received in Server it comes as default value assigned to model variables even after update. The values doesn't get updated when inspected in DOM but its reflected in UI. Yes it is because of readonly property of textbox but Is there any other way to post the readonly property values in these type of situations? Below are few screenshots of how UI looks and DOM and model values when it is received.
UI
DOM
Model
UPDATE
I can see the posted values in URL as ...searchModel.MinPrice=₹2%2C189%2C090.00&searchModel.MaxPrice=₹5%2C772%2C480.00 But not in model. Not sure how to get on this..
₹ and , formatting makes the MinPrice and MaxPrice as strings. And as a result those are not getting bind to int properties. Just remove the formatting and send them in GET, then they will be getting bind to int properties.

TextboxFor passes text, but RadioButtonFor does not

I'm trying to pass a RadioButtonFor to the model.
Controller
[HttpPost]
public ActionResult Contact(ApplicationCommentType model)
{
//send email here
//reload form
ApplicationCommentType appdata = new ApplicationCommentType();
appdata.CommentTypeData = db.CommentTypes.ToList();
return View(appdata);
}
ApplicationCommentType
public class ApplicationCommentType
{
public IEnumerable<CommentType> CommentTypeData { get; set; }
public String CommentTypeDataSelection { get; set; }
public String Name { get; set; }
public String Email { get; set; }
public String Comment { get; set; }
}
CommentType
public partial class CommentType
{
public int CommentTypeID { get; set; }
public string CommentTypeDesc { get; set; }
}
View
#using(#Html.BeginForm("Contact", "Home", FormMethod.Post, new{ #class ="form-horizontal"})){
<fieldset>
<legend>Contact Us</legend>
<div class="form-group">
#Html.LabelFor(x => x.Email, new {#class="col-lg-2 control-label"})
<div class="col-lg-10">
#Html.TextBoxFor(x => x.Email, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(x => x.Name, new { #class = "col-lg-2 control-label" })
<div class="col-lg-10">
#Html.TextBoxFor(x => x.Name, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<label for="textArea" class="col-lg-2 control-label">Questions, Comments, or Concerns</label>
<div class="col-lg-10">
#Html.TextAreaFor(x => x.Comment, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<label class="col-lg-2 control-label">Comment Type</label>
<div class="col-lg-10">
#foreach (var item in Model.CommentTypeData)
{
<div class="radio">
<label>
#Html.RadioButtonFor(x => x.CommentTypeData, item.CommentTypeDesc)
#Html.LabelFor(m => m.CommentTypeData, item.CommentTypeDesc, item.CommentTypeID)
</label>
</div>
}
#Html.HiddenFor(x => x.CommentTypeDataSelection)
</div>
</div>
</fieldset>
}
Now this kind of works, all the textbox items work. Placing a break point on the [HttpPost] return yields the following values.
Comment: "awesome"
CommentTypeData: Count = 0
CommentTypeDataSelection: null
Email: "example#example.com"
Name: "John Smith"
Shouldn't CommentTypeData have a count? If I check the request the selected value is there.
Request.Params["CommentTypeData"]: "General Improvement Suggestion"
So why is the Model not updated? Is it a requirement to manually update the Model from the Request object?
You can use #Html.RadioButtonFor but you should make sure that item.CommentTypeDesc compatible with Radio type.
Refer to MVC4: Two radio buttons for a single boolean model property
Hope it helps.

ASP.NET MVC4 IEnumerable empty on post

I have read several answers on this issue but despite this, it would appear I have developed code blindness.
I have the following view model:
public class IndividualProductVm
{
public virtual Products Products { get; set; }
public ProductSummary ProductSummary { get; set; }
public virtual IEnumerable<ProductSimpleResponse> ProductSimpleResponse { get; set; }
}
This is then passed into a view and then a partial view:
#model Websites.ViewModels.IndividualProductVm #{ ViewBag.Title = "Edit"; }
<h2>Edit</h2>
#using (Html.BeginForm(null, null, FormMethod.Post, new { name = "form", id = "mainForm" })) { #Html.AntiForgeryToken() #Html.ValidationSummary(true, "", new { #class = "text-danger" }) #Html.HiddenFor(model => model.Products.Id) #Html.HiddenFor(model
=> model.ProductSummary.SupplierId) Html.RenderPartial("_IndividualProduct", Model);
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index", new { id = Model.ProductSummary.SupplierId }, new { #class = "btn btn-default" })
</div>
#section Scripts { #Scripts.Render("~/bundles/jqueryval") }
#model Websites.ViewModels.IndividualProductVm
<div>
#Html.LabelFor(model => model.Products.ProductCode, htmlAttributes: new { #class = "control-label col-md-2" })
<div>
#Html.DisplayFor(model => model.Products.ProductCode, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div style="clear:both;"></div>
<div>
#Html.LabelFor(model => model.Products.ProductDescription, htmlAttributes: new { #class = "control-label col-md-2" })
<div>
#Html.DisplayFor(model => model.Products.ProductDescription, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<table class="table">
<tr>
<th>
Present
</th>
</tr>
#foreach (var item in Model.ProductSimpleResponse)
{
<tr>
#Html.HiddenFor(modelItem => item.Id)
#Html.HiddenFor(modelItem => item.SupplierId)
#Html.HiddenFor(modelItem => item.ProductCode)
<td>
#Html.EditorFor(modelItem => item.Present)
</td>
</tr>
}
</table>
However, when I enter the edit post, my viewmodel is null for the IEnumerable<ProductSimpleResponse> but fine for the other two classes.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(IndividualProductVm model)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index", new { id = model.ProductSummary.SupplierId });
}
return View(model.Products);
}
If someone can explain what I'm doing wrong, I'd be most grateful.
Your property name is ProductSimpleResponse, alhtough the type is ProductSvhcSimpleResponse, so to iterate through it you should have.
#foreach (var item in Model.ProductSimpleResponse)
NOT
#foreach (var item in Model.ProductSvhcSimpleResponse)
use List because
IEnumerable is suitable just for iterate through collection and you can not modify (Add or Remove) data IEnumerable bring ALL data from server to client then filter them, assume that you have a lot of records so IEnumerable puts overhead on your memory.
public class IndividualProductVm
{
public virtual Products Products { get; set; }
public ProductSummary ProductSummary { get; set; }
public virtual List<ProductSvhcSimpleResponse> ProductSimpleResponse { get; set; }
}
More help click here

Categories

Resources