When i set value of elements in editor template for grid pop up create , posting to controller as null - asp.net-mvc

in my view there are two grid. when i select a row in first grid, second one is binding according to first one.
what i want to do is take common parameters from first one, used in second one create template in readonly or disabled inputs. my problem is input elements take parameter from first grid but, dont post to controller.
Controller Function
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult DonemKursSinifiOlustur([DataSourceRequest] DataSourceRequest request, DonemKursSinifi model,string DonemId, string DersId, string EgitmenId )
{
if (model != null && ModelState.IsValid)
{
Helper.Islemci.DonemKursSinifiTanimla(model);
}
return Json(new[] { model }.ToDataSourceResult(request, ModelState));
}
model.DonemId, model.DersId, model.EgitmenId and DonemId, DersId, EgitmenId come null.
EditorTemplate View for Grid Create and Update
#model Kurslar.Models.DonemKursSinifi
#using (Html.BeginForm("DonemKursSinifiOlustur","Tanim",FormMethod.Post))
{
<table>
<tr>
<td>
Lütfen Gün ve Saati Belirtiniz:
</td>
<td>
#Html.Kendo().AutoCompleteFor(m=>m.Tanim)
</td>
</tr>
<tr>
<td>
Donem :
</td>
<td>
#Html.Kendo().AutoCompleteFor(m=>m.DonemBaslangicBitis)
#Html.HiddenFor(m => m.DonemId)
</td>
</tr>
<tr>
<td>
Ders Adı:
</td>
<td>
#Html.Kendo().AutoCompleteFor(m=>m.DersAdi)
#Html.HiddenFor(m => m.DersId)
</td>
</tr>
<tr>
<td>
Eğitmen
</td>
<td>
#Html.Kendo().AutoCompleteFor(m=>m.EgitmenAdiSoyadi)
#Html.HiddenFor(m => m.DonemId)
</td>
</tr>
</table>}
First AutoCompleteFor works correctly because take input from user, not before setted.
*and my javaScript code to fill parameters to EditorTemplate *
and it works fine
var grid = $("#donemGrid").data("kendoGrid");
var rows = grid.select();
alert(rows);
try {
var donemID = grid.dataItem(rows).DonemId;
var dersID = grid.dataItem(rows).DersId;
var egitmenID = grid.dataItem(rows).EgitmenId;
var dersAdi = grid.dataItem(rows).DersAdi;
var egitmenAdiSoyadi= grid.dataItem(rows).EgitmenAdiSoyadi;
var donemBaslangicBitis = grid.dataItem(rows).DonemBaslangicBitis;
} catch (e) {
alert(e);
}
$("#DonemBaslangicBitis").data("kendoAutoComplete").value(donemBaslangicBitis);
$("#DersAdi").data("kendoAutoComplete").value(dersAdi);
$("#EgitmenAdiSoyadi").data("kendoAutoComplete").value(egitmenAdiSoyadi);
$("#DonemId").val(donemID);
$("#DersId").val(dersID);
$("#EgitmenId").val(egitmenID);
*if needed, my model *
public class DonemKursSinifi
{
[Key]
[Required]
[PersistentProperty(IsAutoIncremented = true)]
public int Id { get; set; }
[PersistentProperty]
public string Tanim { get; set; }
[PersistentProperty]
public int DonemId { get; set; }
[PersistentProperty]
public int DersId { get; set; }
[PersistentProperty]
public int EgitmenId { get; set; }
[PersistentProperty]
public int KontenjanSayisi { get; set; }
[PersistentProperty]
public int TarifeId { get; set; }
[PersistentProperty]
public int IslemNo { get; set; } // default 1
public string EgitmenAdiSoyadi { get; set; }
public string DersAdi { get; set; }
public string DonemBaslangicBitis { get; set; }
}

ok, probably you have repeated the id in the grid and also have the same name attributes in the same form to do this:
#Html.HiddenFor(m => m.DersId)
mabe you can do somethin like this:
form:
#model Kurslar.Models.DonemKursSinifi
#using (Html.BeginForm("DonemKursSinifiOlustur","Tanim", FormMethod.Post, new { id="myform"}))
{
<input type="hidden" value="" name="Tanim" />
<input type="hidden" value="" name="DonemBaslangicBitis" />
<input type="hidden" value="" name="DonemId" />
<input type="hidden" value="" name="DersAdi" />
<input type="hidden" value="" name="DersId" />
<input type="hidden" value="" name="EgitmenAdiSoyadi" />
<input type="hidden" value="" name="DonemId" />
}
table:
<table>
<tr>
<td>Lütfen Gün ve Saati Belirtiniz:</td>
<td>#Html.Kendo().AutoCompleteFor(m=>m.Tanim)</td>
</tr>
<tr>
<td>Donem :</td>
<td>#Html.Kendo().AutoCompleteFor(m=>m.DonemBaslangicBitis) #Html.HiddenFor(m => m.DonemId)</td>
</tr>
<tr>
<td>Ders Adı:</td>
<td>#Html.Kendo().AutoCompleteFor(m=>m.DersAdi) #Html.HiddenFor(m => m.DersId)</td>
</tr>
<tr>
<td>Eğitmen</td>
<td>#Html.Kendo().AutoCompleteFor(m=>m.EgitmenAdiSoyadi) #Html.HiddenFor(m => m.DonemId)</td>
</tr>
</table>
js:
var
grid = $("#donemGrid").data("kendoGrid"),
rows = grid.select(),
form = $('#myform');
form.find('input[name="DonemBaslangicBitis"]').val(grid.dataItem(rows).DonemBaslangicBitis);
form.find('input[name="DersAdi"]').val(grid.dataItem(rows).DersAdi);
form.find('input[name="EgitmenAdiSoyadi"]').val(grid.dataItem(rows).EgitmenAdiSoyadi);
form.find('input[name="DonemId"]').val(grid.dataItem(rows).DonemId);
form.find('input[name="DersId"]').val(grid.dataItem(rows).DersId);
form.find('input[name="EgitmenId"]').val(grid.dataItem(rows).EgitmenId);
form.submit();

Related

Null value in viewmodel after Post Action

I am getting null values in the controller http post part from the view model. All the values are null. I am not able to access the view model properties and select list values as well. How to solve the null values and access the selected city from the model for updating the database using db context.
I searched other similar questions but those results didnt help.
It will be of great help if anyone can solve the issue.
Model Class:
namespace MvcCoreAngular.ViewModels
{
public class DetailedResultEdit
{
public int employeeid { get; set; }
public string name { get; set; }
public List<SelectListItem> citieslist { get; set; }
public int cityid { get; set; }
public string department { get; set; }
public string gender { get; set; }
}
}
HTML:
#model IEnumerable<MvcCoreAngular.ViewModels.DetailedResultEdit>
#{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm("Edit", "Home", FormMethod.Post))
{
#foreach (var item in Model)
{
<table>
<tr>
#Html.Label("Name")
#Html.TextBoxFor(model => item.name)
<br />
</tr>
<tr>
#Html.Label("Department")
#Html.TextBoxFor(model => item.department)
<br />
</tr>
<tr>
#Html.Label("Cities")
#Html.DropDownListFor(model => item.cityid, item.citieslist, "", null)
<br />
</tr>
<tr>
<input type="submit" value="Submit" id="btnSubmit" />
</tr>
</table>
}
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(DetailedResultEdit mo)
{
//IEnumerable<tblcities> citieslist = from c in _context.tblcities.ToList<tblcities>().GroupBy(x=> x.cityname).Select(x=> x.First());
if (ModelState.IsValid) {
var empdata = _context.tblemployee.Find(mo.employeeid);
empdata.cityid = mo.cityid;
empdata.department = mo.department;
empdata.name = mo.name;
_context.SaveChanges();
}
Firstly,your code don't bind the data correctly,so the edit action cannot get the data.Besides,you didn't pass employeeid to action,so you can add a hidden input in the view,and then you can use _context.tblemployee.Find.
Here is a demo worked:
Controller:
[HttpGet]
public IActionResult Edit() {
List<tblemployee> tblemployees = _context.tblemployee.ToList();
List<DetailedResultEdit> detailedResultEdits = new List<DetailedResultEdit>();
List<SelectListItem> list = new List<SelectListItem> { new SelectListItem { Text = "NY", Value = "1" }, new SelectListItem { Text = "Boston", Value = "2" }, new SelectListItem { Text = "Dover", Value = "3" } };
foreach (tblemployee t in tblemployees) {
DetailedResultEdit temp = new DetailedResultEdit();
temp.cityid = t.cityid;
temp.name = t.name;
temp.employeeid = t.employeeid;
temp.department = t.department;
temp.gender = t.gender;
temp.citieslist = list;
detailedResultEdits.Add(temp);
}
return View(detailedResultEdits);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(DetailedResultEdit mo)
{
if (ModelState.IsValid)
{
var empdata = _context.tblemployee.Find(mo.employeeid);
empdata.cityid = mo.cityid;
empdata.department = mo.department;
empdata.name = mo.name;
_context.Attach(empdata).State = EntityState.Modified;
_context.SaveChanges();
Edit();
}
return View();
}
View:
#model IEnumerable<DetailedResultEdit>
#{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
#foreach (var item in Model)
{
#using (Html.BeginForm("Edit", "TestDB", FormMethod.Post))
{
<table>
<tr>
<input hidden name="employeeid" value="#item.employeeid" class="form-control" />
#Html.Label("Name")
<input name="name" value="#item.name" class="form-control" />
<br />
</tr>
<tr>
#Html.Label("Department")
<input name="department" value="#item.department" class="form-control" />
<br />
</tr>
<tr>
#Html.Label("Cities")
<select name="cityid"
asp-for="#item.cityid"
asp-items="#item.citieslist">
</select>
<br />
</tr>
<tr>
<input type="submit" value="Submit" id="btnSubmit" />
</tr>
</table>
}
}
tblemployee:
public class tblemployee
{
[Key]
public int employeeid { get; set; }
public string name { get; set; }
public int cityid { get; set; }
public string department { get; set; }
public string gender { get; set; }
}
result:

MVC using IEnumerable<Model> with Razor is null after post to controller

My Model
public class ActivityModel
{
public int Id { get; set; }
public String Nick { get; set; }
public String TripName { get; set; }
[DisplayFormat(DataFormatString = "{0:hh\\:mm}", ApplyFormatInEditMode = true)]
public TimeSpan? FromTime { get; set; }
[DisplayFormat(DataFormatString = "{0:hh\\:mm}", ApplyFormatInEditMode = true)]
public TimeSpan? ToTime { get; set; }
public String FromPlace { get; set; }
public String ToPlace { get; set; }
public String activityType { get; set; }
[DisplayFormat(DataFormatString = "{0:dd.MM.yyyy}", ApplyFormatInEditMode = true)]
public DateTime? Timestamp { get; set; }
public String Weather { get; set; }
public int Difficulty { get; set; }
public bool Reviewed { get; set; }
}
My View row looks like this
#model IList<ActivityModel>
#for (int i = 0; i < Model.Count; i++)
{
if (!(bool)Model[i].Reviewed)
{
<tr>
#using (Html.BeginForm("Accept", "Overview", FormMethod.Post, new { activityModel = Model }))
{
#Html.AntiForgeryToken()
<td>
#Html.DisplayFor(m => Model[i].Timestamp)
#Html.HiddenFor(m => Model[i].Timestamp)
</td>
<td>
#Html.DisplayFor(m => Model[i].Nick)
#Html.HiddenFor(m => Model[i].Nick)
</td>
<td>
#Html.DisplayFor(m => Model[i].TripName)
#Html.HiddenFor(m => Model[i].TripName)
</td>
<td>
#Html.DisplayFor(m => Model[i].FromTime)
#Html.HiddenFor(m => Model[i].FromTime)
</td>
<td>
#Html.DisplayFor(m => Model[i].FromPlace)
#Html.HiddenFor(m => Model[i].FromPlace)
</td>
<td>
#Html.DisplayFor(m => Model[i].ToTime)
#Html.HiddenFor(m => Model[i].ToTime)
</td>
<td>
#Html.DisplayFor(m => Model[i].ToPlace)
#Html.HiddenFor(m => Model[i].ToPlace)
</td>
<td>
#Html.TextBoxFor(m => Model[i].Difficulty, new { id = "Difficulty" })
<--!#Html.HiddenFor(m => Model[i].Difficulty)--!>
<div style="visibility:hidden">
#Html.HiddenFor(m => Model[i].Id)
#Html.HiddenFor(m => Model[i].Reviewed)
#Html.HiddenFor(m => Model[i].activityType)
#Html.HiddenFor(m => Model[i].Weather)
</div>
</td>
<td>
<input type="submit" name="btn_accept" value="Accept" />
</td>
}
</tr>
}
}
And my Controller is this
public ActionResult Index()
{
List<ActivityModel> activities_web = new List<ActivityModel>();
//someLogicForFilling
return View(activities_web);
}
[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult Accept(ActivityModel activityModel)
{
return RedirectToAction("Index");
}
And the problem is that in ActionResult Accept is ActivityModel always NULL empty 0 ...
I really spent whole day on it for now and I don't know where is the problem i tried almost 20 solutions and nothing worked for me..
Rendering the page and showing all values is OK but when I try to POST them like nothing is posted.
Model binding will work when the posted data matches with the property structure of the class you are using as your HttpPost action method parameter.
Your current view code is generating HTML code like this
<input name="[0].Id" type="hidden" value="101">
<input name="[1].Id" type="hidden" value="202">
Assuming you have 2 items in the collection you are passing to the view.
You can see that the name attribute value is [0].Id and [1].Id. But your Accept action method's parameter is a single ActivityModel object and the property names are like Id, FromPlace etc. For model binding to work, the names of your input and the property name should match.
You can rewrite your view code to generate the correct name attribute value for your hidden inputs. You may simply use the pure HTML code to create the hidden input and set the value from your model item or use the Html.HiddenFor helper method.
#foreach (var item in Model.Where(a => a.Reviewed == false))
{
<input type="hidden" name="FromPlace" value="#item.FromPlace" />
#Html.Hidden("ToPlace", item.ToPlace)
#Html.Hidden(nameof(ActivityModel.Id), item.Id)
}
Here is the full code (excluded some properties to save space).
#model IList<ActivityModel>
<table class="table table-striped">
#foreach (var item in Model.Where(a => a.Reviewed == false))
{
using (Html.BeginForm("Accept", "Process", FormMethod.Post))
{
#Html.AntiForgeryToken()
<tr>
<td>
#Html.DisplayFor(m => item.FromPlace)
#Html.Hidden("FromPlace", item.FromPlace)
</td>
<td>
#Html.DisplayFor(m => item.ToPlace)
#Html.Hidden("ToPlace", item.ToPlace)
</td>
<td>
#Html.Hidden(nameof(ActivityModel.Id),item.Id)
<input type="submit" name="btn_accept" value="Accept" />
</td>
</tr>
}
}
</table>
But ideally, if you are trying to update the status of a single entity /record, all you need is the Id (primary key) of that record. that means, you really do not need all the properties populated. In that case, you need the hidden input element for the Id property value. You can always query the db to get the full entity using this Id if needed. ( Never trust data coming from client)

How to get client side generated class list to MVC post action argument?

I have one form where I am generating some control dynamically (Which is list some class . in image add product artwork section) When I click on submit button how can i get this values in post Action method's argument so that I can use this value in collection.
For reference I have attached the image where i have option for multiple Artwork oprion
[HttpPost]
public ActionResult Add(Graphic graphicToAdd,Enumerable<GraphicArtwork> artworkOption)
{
// I want value in artworkOption
}
public class GraphicArtwork
{
[Key]
public int GraphicArtworkId { get; set; }
public int GraphisId { get; set; }
[Required(ErrorMessage = "The {0} is required.")]
[DisplayName("Option Text")]
[StringLength(500)]
public string ArtOptionText { get; set; }
public decimal Price { get; set; }
[DisplayName("Active")]
public bool IsActive { get; set; }
public DateTime CreatedDate { get; set; }
[NotMapped]
public int TotalRecordCount { get; set; }
}
This is my view :
<div class="editor-field PrintOptions">
<table data-bind="visible :customArtworks().length > 0">
<thead>
<tr>
<td class="editor-label">Option</td>
<td class="editor-label">Price</td>
<td></td>
</tr>
</thead>
<tbody data-bind="foreach: customArtworks">
<tr>
<td>
<input placeholder="Enter Artwork Text" type="text" data-bind="value: ArtOptionText'}" />
</td>
<td>
<input placeholder="Enter Price" type="text" data-bind="value: Price" />
</td>
<td>
<img title="Add" src="~/Content/images/icon_add.png">
<img title="Delete" style="margin-left:10px;" src="~/Content/images/icon_delete.png">
</td>
</tr>
</tbody>
</table>
</div>
For more detail : I am generating my dynamical control using knockout.js
// Ko Implemntation
function GraphicArtwork(ArtOptionText, Price) {
var self = this;
self.ArtOptionText = ArtOptionText;
self.Price = Price;
self.formattedPrice = ko.computed(function () {
var price = self.Price;
return price ? "$" + price.toFixed(2) : "0.00";
})
}
function GraphicArtworkViewModel() {
var self = this;
self.customArtworks = ko.observableArray([GraphicArtwork(null, null)]);
self.add = function () {
self.customArtworks.push(new GraphicArtwork(null, null));
};
self.remove = function (GraphicArtwork) {
self.customArtworks.remove(GraphicArtwork);
};
}
ko.applyBindings(new GraphicArtworkViewModel());
Add This binding :
<td>
<input placeholder="Enter Artwork Text" type="text" data-bind="value: ArtOptionText,attr:{name: '['+$index()+'].ArtOptionText'}" />
</td>
<td>
<input placeholder="Enter Price" type="text" data-bind="value: Price,attr:{name: '['+$index()+'].Price'}" />
</td>
AND in Code Behind
public ActionResult Add(Graphic graphicToAdd,IEnumerable<GraphicArtwork> listOfGraphicArtwork)
{
// listOfGraphicArtwork will hold all the required data
}

Simple form submission gives missing resource on postback

Apologies if this seems mundane, but I am a huge beginner to MVC and this seemingly simple task is giving me a massive headache.
I can't understand why my code isn't working. I'm submitting a form from my Index.cshtml and the postback is telling me the resource /Index (the page I am posting from) doesn't exist.
Could I please get some help on what I am doing wrong?
My View (Index.cshtml):
#model MyProject.Connection
#{
ViewBag.Title = "Index";
}
<div id="container" class="container centered primary">
#using (Html.BeginForm(FormMethod.Post))
{
<img src="#Url.Content("/Content/images/default.png")" alt="CMGR Web" />
<div class="divider"></div>
<fieldset id="fs_server" class="borderless!T">
<legend>Server details</legend>
<table>
<tr>
<td>
#Html.LabelFor(c => c.serverHost)
</td>
<td>
#Html.TextBoxFor(c => c.serverHost)
</td>
</tr>
<tr>
<td>
#Html.LabelFor(c => c.instanceName)
</td>
<td>
#Html.TextBoxFor(c => c.instanceName)
</td>
</tr>
</table>
</fieldset>
<fieldset id="fs_user" class="borderless!T">
<legend>Your credentials</legend>
<table>
<tr>
<td>
#Html.LabelFor(c => c.username)
</td>
<td>
#Html.TextBoxFor(c => c.username)
</td>
</tr>
<tr>
<td>
#Html.LabelFor(c => c.password)
</td>
<td>
#Html.PasswordFor(c => c.password)
</td>
</tr>
</table>
</fieldset>
<div class="divider"></div>
<table>
<tr>
<td>
#Html.CheckBoxFor(c => c.remember)
#Html.Label("Remember me?")
</td>
<td>
<input type="submit"/>
</td>
</tr>
</table>
}
</div>
My Model (Connection.cs):
namespace MyProject.Models
{
public class Connection
{
[Display(Name="Server Host")]
public string serverHost { get; set; }
[Display(Name="Instance Name")]
public string instanceName { get; set; }
[Display(Name = "Username")]
public string username { get; set; }
[Display(Name = "Password")]
public string password { get; set; }
[Display(Name = "Remoting Password")]
public string remotingPassword { get; set; }
[Display(Name = "Persistent")]
public bool remember { get; set; }
}
}
My Controller (IndexController.cs)
namespace MyProject.Controllers
{
public class IndexController : Controller
{
//
// GET: /Login/
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
private ActionResult Index(Connection channel)
{
return View();
}
}
}
Your Post ActionResult is set to Private so it isnt accessible. Change it to public
private ActionResult Index(Connection channel)
{
return View();
}
public ActionResult Index(Connection channel)
{
return View();
}

Passing back child entity from MVC view to controller

I'm trying to delete entries which are marked (checked) in view, but not sure how to pass back the collection back to the controller
my mode is:
Group which has ICollection<SubGroup> SubGroups and SubGroup has ICollection<Event> Events
I pass Group to the view and iterate and display Event details including a checkbox so if it's checked the event entry should be deleted.
When I get the postback to the controller, Group.SubGroups is null
How do I make sure the child entities are passed back to the controller?
Can I use #Html.CheckBox instead Of <input type="checkbox"... ?
Update: Model
public class Group
{
[Key]
public int GroupId { get; set; }
public virtual IList<SubGroup> SubGroups { get; set; }
....
}
public class SubGroup
{
[Key]
public int SubGroupId { get; set; }
public virtual IList<Event> Events { get; set; }
....
}
public class Events
{
[Key]
public int EventId { get; set; }
public string EventName { get; set; }
public bool IsDeleted { get; set; }
....
}
I am passing Group to the view (see below) as the Model and want to delete events which are checked by the user
View:
#using System.Globalization
#model NS.Models.Group
#{
ViewBag.Title = "Edit";
}
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Booking Details</legend>
<div class="display-label">
Group Name
</div>
<div class="display-field">
#Html.DisplayFor(model => model.GroupName)
</div>
<div class="display-field">
#foreach (var b in Model.SubGroup)
{
groupNo += 1;
<table class="main" style="width: 80%; margin-top: 10px">
<tr>
<th>
#Html.DisplayName("Sub Group ")
#Html.DisplayName(b.SubGroupName)
</th>
</tr>
<table class="main" style="width: 80%;">
<tr>
<th>Event</th>
<th>Delete</th>
</tr>
#foreach (var ev in b.Events)
{
<tr>
<td>
#Html.DisplayFor(modelItem => ev.EventName)
</td>
<td>
<input type="checkbox" id="eventToDelete" name="eventToDelete" value="#ev.EventId" />
</td>
</tr>
}
</table>
</table>
}
</div>
<p>
<input type="submit" name="xc" value="Delete" class="button" />
</p>
</fieldset>
}
Thank You
Try this...
public ActionResult ViewName(FormCollection collection)
{
if(collection['eventToDelete']!=null && collection['eventToDelete'].ToString()!="")
{
//delete....
}
return....
}
Try this
public ActionResult ViewName(Group model)
{
if(model != null && ModelState.IsValid)
{
//delete....
}
return....
}

Resources