Getting viewmodel value null on Http Post method, - c#

My View page, it contains many dynamic controls
I know this question has been asked and answered a dozen of times but none of the solutions help me.
I have a following ViewModel which is consisted of QuestionBatch data model,listResponseTag and a list of listQuestion data model.
View Model
public class VM_Questionaire
{
public QuestionBatch ThequestionBatch { get; set; }
public List<Question> listQuestion { get; set; }
public List<ResponseTag> listResponseTag { get; set; }
}
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult submit_Questionaire(VM_Questionaire vm_question)
{
if (ModelState.IsValid)
{
Console.Write(Newtonsoft.Json.JsonConvert.SerializeObject(vm_question));
}
return View("Index");
}
View
<pre>
#model Fonz_Survey.Models.VM_Questionaire
#{
ViewBag.Title = "Questionaire";
}
#using (Html.BeginForm("submit_Questionaire", "Questions", FormMethod.Post))
{
#Html.AntiForgeryToken()
<h2>Questionaire</h2>
<div class="card">
<div class="card-header">
<div class="jumbotron-fluid">
<div class="container">
<div class="row">
<div class="col-lg-3 col-md-6 col-sm-6">
<h5 class="text-muted text-monospace">CODE</h5>
</div>
<div class="col-lg-3 col-md-6 col-sm-6 text-danger text-monospace">
#Html.DisplayFor(model => model.ThequestionBatch.Code, new { #class = "text-danger text-monospace" })
#Html.HiddenFor(model => model.ThequestionBatch.Code)
</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-6 col-sm-6">
<h5 class="text-muted text-monospace">Question Batch</h5>
</div>
<div class="col-lg-3 col-md-6 col-sm-6 text-primary text-monospace">
#Html.DisplayFor(model => model.ThequestionBatch.BatchName, new { #class = "text-primary text-monospace" })
#Html.HiddenFor(model => model.ThequestionBatch.BatchName)
</div>
<div class="col-lg-3 col-md-6 col-sm-6">
<h5 class="text-muted text-monospace">No of Questions</h5>
</div>
<div class="col-lg-3 col-md-6 col-sm-6">
<label class="text-primary text-monospace">#ViewBag.totalQstns</label>
</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-6 col-sm-6">
<h5 class="text-muted text-monospace">Description</h5>
</div>
<div class="col-lg-3 col-md-6 col-sm-6 text-primary text-monospace text-wrap">
#Html.DisplayFor(model => model.ThequestionBatch.Description, new { #class = "text-primary text-monospace text-wrap" })
#Html.HiddenFor(model => model.ThequestionBatch.Description)
</div>
</div>
</div>
</div>
</div>
<div class="card-body">
#{
//int rowIndex = 0;
}
#if (Model != null && Model.listQuestion != null)
{
for(var rowIndex=0; rowIndex< Model.listQuestion.Count; rowIndex++)
//foreach (Question question in Model.listQuestion)
{
// rowIndex++;
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header bg-gray text-light">
<div class="d-inline-block">
<label class="text-lg-left font-weight-bold">#rowIndex.</label>
<label class="text-lg-left font-weight-bold">#Model.listQuestion[rowIndex].QuestionEN</label>
<br />
<label class="text-lg-left font-weight-bold">#Model.listQuestion[rowIndex].QuestionAR</label>
</div>
</div>
<div class="card-body font-weight-bolder">
#switch (#Model.listQuestion[rowIndex].QType)
{
case 1:
// to do Text Boxes
<p class="text-info"><u>Please enter your message below;</u></p>
<div class="form-row">
#*<input type="text" placeholder="#question.QuestionEN" name="Q_#question.Id" id="Q_#question.Id" class="form-control" />*#
#Html.EditorFor(model=> #Model.listQuestion[rowIndex].QuestionEN)
</div>
break;
case 2:
// to do Radio
<p class="text-info"><u>Please select any one of the option below;</u></p>
foreach (ChoiceTag ct in Model.listQuestion[rowIndex].ChoiceTags)
{
<div class="form-check">
<label class="form-check-label" for="C_#ct.Id">
<input type="radio" class="form-check-input" id="C_#ct.Id" name="#Model.listQuestion[rowIndex].Id" value="#ct.AnswerEN">#ct.AnswerEN | #ct.AnswerAR
</label>
</div>
}
break;
case 3:
// to do Radio
<p class="text-info"><u>Please select options below;</u></p>
foreach (ChoiceTag ct in Model.listQuestion[rowIndex].ChoiceTags)
{
<div class="form-check">
<label class="form-check-label" for="C_#ct.Id">
<input type="checkbox" class="form-check-input" id="C_#ct.Id" name="#Model.listQuestion[rowIndex].Id" value="#ct.AnswerEN">#ct.AnswerEN | #ct.AnswerAR
</label>
</div>
}
break;
}
</div>
</div>
</div>
</div>
}
<div class="form-group">
<div class="col-12 text-center">
<input type="submit" value="Submit" class="btn btn-success " />
</div>
</div>
}
</div>
<div class="card-footer">
<label class="text-danger">#ViewBag.Message</label>
</div>
</div>
}
</prev>
First object getting value, but the list getting null.

#Html.DisplayFor() will not post values. You need to use #Html.HiddenFor() along with #Html.DisplayFor(). Refer: Html.DisplayFor not posting values to controller in ASP.NET MVC 3

if you're not passing any type of data then make your data as a hidden field and after that you will received your data at your respective controller.
Thanks.

Related

Bootstrap - present confirmation modal after post back to controller

I am trying to create a Bootstrap modal pop up "Ticket successfully created" once you submit a form which posts data through to IActionResult to add to database. However my modal is like transparent with just text and I'm also getting a runtime error of : Obj ref not set to an instance of object
I have a feeling that modal popup is causing the passing of data back to the controller to not work. What is the way around this?
GetTicket view
#model Project.HelpDeskViewModel
<fieldset>
#using (Html.BeginForm())
{
<div class="container">
<div class="form-group">
<div class="row m-4 text-center">
<div class="col-4">
</div>
<div class="col-4">
<h2 style="text-align:center;font-weight:bold">Get A Ticket</h2>
</div>
</div>
</div>
<div class="form-group">
<div class="row m-3">
<div class="col-4" style="text-align:left">
#Html.LabelFor(m => m.category)
</div>
<div class="col-4">
#Html.DropDownListFor(m => m.category, new SelectList(Model.categoryList, "Value", "Text"), "Select category", new { #class = "form-control" })#Html.ValidationMessageFor(model => model.category,
"", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="row m-3">
<div class="col-4" style="text-align:left">
#Html.LabelFor(m => m.ticketDescription)
</div>
<div class="col-4">
#Html.TextAreaFor(m => m.ticketDescription, new { #class = "form-control" })#Html.ValidationMessageFor(model => model.ticketDescription,
"", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#*Modal for ticket creation*#
<div class="modal" id="MyModal" role="dialog">
<div class="modal-dialog">
<div class="model-content">
<div class="modal-header">
<button class="close" data-dismiss="modal">×</button>
<h4>Ticket Created</h4>
</div>
<div class="modal-body">
<p> Your Helpdesk ticket has been succesfully submitted</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" data-dismiss="modal"> close</button>
</div>
</div>
</div>
</div>
</div>
<div class="row m-3">
<div class="col-4">
</div>
<div class="col-4" style="text-align:left">
<button type="submit" class="btn btn-primary form-control" data-target="#MyModal" data-toggle="modal">Submit</button>
</div>
</div>
</div>
}
</fieldset>
Controller
[HttpPost]
public IActionResult GetTicket(HelpDeskViewModel h)
{
HelpDeskViewModel sess = new HelpDeskViewModel();
try
{
//session variable passing userID
sess.userID = HttpContext.Session.GetString("userID");
if (!ModelState.IsValid) return View(h);
//h.empID = null; //add ticket record without employeeID - ticket hasn't been assigned yet
h.userID = sess.userID; //add userID from session
_db.helpdesk.Add(h);
_db.SaveChanges();
}
catch (Exception ex)
{
global.gLogger.log.Debug("Debug message: ", ex.Message);
global.gLogger.log.Error(new Exception(), ex.Message);
global.gLogger.log.Error(new Exception(), ex.StackTrace);
global.gLogger.log.Fatal("Fatal message: ", ex.Message); ;
}
return View("GetTicket");
}
You can use ViewBag for open bootstrap modal after successfully return from server to client
Client Side View
#if(ViewBag.SuccessfullyTicketCreated != null)
{
<script>
$('#myModal').modal('show'); // open model by use jQuery
</script>
}
Server side Controller
_db.SaveChanges();
ViewBag.SuccessfullyTicketCreated = true; // create ViewBag after savechange success
I hope help you simple way
Only use of ajax call can solve your problem without creating any further issues. if you are not using jQuery, you can also send ajax call using Javascript using fetch() method.
<form id="form" action="/Controller/GetTicket" method="post">
<div class="container">
<div class="form-group">
<div class="row m-4 text-center">
<div class="col-4">
</div>
<div class="col-4">
<h2 style="text-align:center;font-weight:bold">Get A Ticket</h2>
</div>
</div>
</div>
<div class="form-group">
<div class="row m-3">
<div class="col-4" style="text-align:left">
#Html.LabelFor(m => m.category)
</div>
<div class="col-4">
#Html.DropDownListFor(m => m.category, new SelectList(Model.categoryList, "Value", "Text"), "Select category", new { #class = "form-control" })#Html.ValidationMessageFor(model => model.category,
"", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="row m-3">
<div class="col-4" style="text-align:left">
#Html.LabelFor(m => m.ticketDescription)
</div>
<div class="col-4">
#Html.TextAreaFor(m => m.ticketDescription, new { #class = "form-control" })#Html.ValidationMessageFor(model => model.ticketDescription,
"", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#*Modal for ticket creation*#
<div class="modal" id="MyModal" role="dialog">
<div class="modal-dialog">
<div class="model-content">
<div class="modal-header">
<button class="close" data-dismiss="modal">×</button>
<h4>Ticket Created</h4>
</div>
<div class="modal-body">
<p> Your Helpdesk ticket has been succesfully submitted</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" data-dismiss="modal"> close</button>
</div>
</div>
</div>
</div>
</div>
<div class="row m-3">
<div class="col-4">
</div>
<div class="col-4" style="text-align:left">
<button type="submit" class="btn btn-primary form-control" data-target="#MyModal" data-toggle="modal">Submit</button>
</div>
</div>
</div>
</form>
Use Javascript:
<script> function onSubmit(){
$.ajax({
url:'/Controller/GetTicket',
type:'post',
data: $('#form').serialize(),
success: function(){
// code here;}
})
}</script>

Umbraco C# - Display 2 different columns on foreach loop (1-2) (1-2)

I'm trying to display data from the Umbraco in this order 1-2 in foreach loop (bootstarp columns), but my code is displaying in this order of columns 1-1, instead of 1-2 on loop. It does not add the second column to the second row just one column.
E.g. 1 item, then 2 items, then 1 item again with different columns displays.
whats the better approach to make 1-2 on loop of content?
I'm kinda lost on this one. Any help would be good.
<div class="container-fluid" style="padding-left: 117px;">
<div class="row" style="margin-top: 5em;">
<div class="col-lg-9 col-md-9 col-sm-9">
<!-- BLOG START-->
#foreach(var data in Model.Content.Children().Where(x => !x.GetPropertyValue<bool>("umbracoNaviHide"))){
if(data.HasValue("blogNested")){
var items = data.GetPropertyValue<IEnumerable<IPublishedContent>>("blogNested");
int i = 0 ;
foreach(var item in items){
<div class="row">
#if(i % 2 == 0) {
<div class="col-md-4 col-sm-12">
<div class="card">
<img src=" /media/1180/dude.jpg" style="height: 15em;">
</div>
</div>
<div class="col-md-6 col-sm-12">
<span class="card-text qs-blog-direcao">#(item.GetPropertyValue<string>("tipoDeDirecao"))</span><br><br>
<span class="qs-blog-date-1page">#(item.GetPropertyValue<string>("dataDePublicacaoBlog"))</span><br>
<span class="qs-blog-publicado-por"> #(item.GetPropertyValue<string>("publicadoPorBlog")) - OPINIÃO </span><br><br><br>
<span class="qs-blog-titulo-1page">#(item.GetPropertyValue<string>("tituloBlog"))</span>
</div>
<div class="col-md-12 col-sm-12" style="margin-top:2em;">
<span class="qs-blog-resumo d-flex justify-content-start">#(item.GetPropertyValue<string>("resumoBlog"))</span>
<span class="d-flex justify-content-end"><a><img src=" /media/1027/icon_inf_verde.png"></a></span>
</div>
}
else {
<div class="col-md-6 col-sm-12">
<span class="card-text qs-blog-direcao-double">#(item.GetPropertyValue<string>("tipoDeDirecao"))</span><br>
<img src=" /media/1182/tempo.jpg" style="height: 10em;margin-top: 2em;">
<div class="qs-blog-sideByside">
<span class="qs-blog-date-1page-double">#(item.GetPropertyValue<string>("dataDePublicacaoBlog"))</span><br>
<span class="qs-blog-publicado-por-double"> #(item.GetPropertyValue<string>("publicadoPorBlog")) - OPINIÃO </span>
</div>
<div class="qs-blog-titulo-1page-double">#(item.GetPropertyValue<string>("tituloBlog"))</div>
<div class="qs-blog-resumo-blog d-flex justify-content-start">#(item.GetPropertyValue<string>("resumoBlog"))</div>
<span class="d-flex justify-content-end"><a><img src=" /media/1027/icon_inf_verde.png"></a></span>
</div>
}
#{i++;}
</div>
}
}
}
<!-- BLOG START-->
</div>
It could be something like this
var items = data.GetPropertyValue<IEnumerable<IPublishedContent>>("blogNested")
.ToList();
while (items.Any())
{
var oneItem = items.First();
items.Remove(oneItem);
<div class="row">
<div class="col-md-12">
#oneItem.Id
</div>
</div>
var twoItems = items.Take(2).ToList();
if (twoItems.Any())
{
<div class="row">
#foreach (var item in twoItems)
{
items.Remove(item);
<div class="md-6">
#item.Id
</div>
}
</div>
}
}
This will render
<div class="row">
<div class="col-md-12">
<text>{{Id}}</text>
</div>
</div>
<div class="row">
<div class="md-6">
<text>{{Id}}</text>
</div>
<div class="md-6">
<text>{{Id}}</text>
</div>
</div>
<div class="row">
<div class="col-md-12">
<text>{{Id}}</text>
</div>
</div>
...

MVC model with multiple forms

I am passing a list to a view to display in a grid. Underneath the grid I have a form to allow the user to submit new values into the grid. When the controller is called the model always seems to be empty, I am not sure what I am doing wrong or if I should be doing this in a different way entirely.
The relavent parts of the view are as follows
#model IList<PSIApp.Models.PSM_StationTimetableView>
#using (Html.BeginForm())
{
<div class="panel-group">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" href="#collapse3">Hourly Update &#x25BC</a>
</h4>
</div>
<div id="collapse3" class="panel-collapse collapse in" style="width:100%; margin-left:0%; margin-right:50px;">
<div class="mainformCollapse" style="width:100%; margin-left:0%; margin-right:50px;">
<p class="group-header">Hourly Update</p>
<div class="form-group row">
<label for="example-text-input" class="col-xs-3 col-form-label" id="formLabelId">BP Issued</label>
<div class="col-xs-3">
#Html.MyTextBoxFor(p => p[0].PSM_StationBPData.BPIssued, new { #class = "generalformbox" }, false)
</div>
<label for="example-text-input" class="col-xs-3 col-form-label " id="formLabelId">BP Cancelled/Spoilt</label>
<div class="col-xs-3">
#Html.TextBoxFor(p => p[0].PSM_StationBPData.BPSpoilt, new { #class = "generalformbox" })
</div>
</div>
<div class="form-group row">
<label for="example-text-input" class="col-xs-3 col-form-label" id="formLabelId">AV Issued</label>
<div class="col-xs-3">
#Html.TextBoxFor(p => p[0].PSM_StationBPData.PostalReceived, new { #class = "generalformbox" })
</div>
<label for="example-text-input" class="col-xs-3 col-form-label" id="formLabelId">Tendered Issued</label>
<div class="col-xs-3">
#Html.TextBoxFor(p => p[0].PSM_StationBPData.BPTendered, new { #class = "generalformbox" })
</div>
</div>
<input type="submit" value="Submit Hourly Update" class="standardsubmitbt" />
</div>
</div>
</div>
</div>
}
Controller
public ActionResult POControl(Models.PSM_StationBPData model)
{
return RedirectToAction("POControl");
}
You are sending an IList of PSM_StationTimetableView, but you are expecting a PSM_StationBPData on the controller.

Bootstrap column stacks when data is filled in left one

I have bootstrap nested grid.In one of my row I have 3 column. When I fill data in the first column of the row , then 3rd column of the row stacks down.However it stays good when there is no data.
Before filling Data:
<div class="container-fluid">
<div class="row">
<div class="col-xs-6">
<div class="container-fluid">
<div id="tagListDiv">
tags go here
</div>
</div>
</div>
<div class="col-xs-2">
</div>
<div class="col-xs-4">
<img src="#Url.Content(Model.DefaultImagePath)" alt="Image" height="150" width="150"/>
<span class="glyphicon glyphicon-pencil" style="color: #292929; background-color: #E3DAC9; vertical-align:bottom"></span>
<span class="glyphicon glyphicon-plus" style="color: #292929;background-color: #E3DAC9; vertical-align: bottom"></span>
</div>
</div>
</div>
Redered:
After Filling Data:
<div class="container-fluid">
<div class="row">
<div class="col-xs-6">
<div class="container-fluid">
<div id="tagListDiv">
#for (var tagCount = 0; tagCount < #Model.TagList.Count(); tagCount++)
{
<div class="row">
<div class="col-xs-4">
#(Html.CheckBoxFor(x => x.TagList.ToList()[tagCount].IsEnable))
<label>#Model.TagList.ToList()[tagCount].TagName</label>
#if (++tagCount == #Model.TagList.Count())
{
break;
}
</div>
<div class="col-xs-4">
#(Html.CheckBoxFor(x => x.TagList.ToList()[tagCount].IsEnable))
<label>#Model.TagList.ToList()[tagCount].TagName</label>
#if (++tagCount == #Model.TagList.Count())
{
break;
}
</div>
<div class="col-xs-4">
#(Html.CheckBoxFor(x => x.TagList.ToList()[tagCount].IsEnable))
<label>#Model.TagList.ToList()[tagCount].TagName</label>
</div>
</div>
}
</div>
</div>
</div>
</div>
After data filled:

Ajax Request Returning Extra Div Layer

When returning a partial view to the browser, on the first load the partial view renders as I'v laid it out with no issues but when I hit my submit button and call an ajax request, it returns inside itself.
For example - on first run it renders:
<div id="search" class="col-md-4">
...
</div>
But after the postback it renders as
<div id="search" class="col-md-4">
<div id="search" class="col-md-4">
...
</div>
</div>
My View with the Partial View render is:
#model SpecCheck.Portals.Web.UI.ViewModels.Search
#{
ViewBag.Title = "Search";
}
#Html.Action("_GetSearch", "Home");
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-gears"></i> Discontinued Machines</h3>
</div>
<div class="panel-body">
<select class="form-control">
<option>All Tiers</option>
<option>Tier 2 / Tier 3</option>
<option>Interim Tier 4 / Tier 4</option>
</select>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<i class="fa fa-folder-open"></i> Search by Category
</h3>
</div>
<div class="panel-body">
<select class="form-control">
<option>Select a product category</option>
<option>Construction</option>
<option>Technologies</option>
</select>
</div>
</div>
</div>
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-star"></i> Latest Model Data</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
</div>
And my partial View:
#model IEnumerable<SpecCheck.Portals.Web.UI.ViewModels.Search>
<div id="modelSearch" class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-search"></i> Search by Model / Manufacturer</h3>
</div>
<div class="panel-body">
#using (Ajax.BeginForm("_GetSearch", "Home", new AjaxOptions() { UpdateTargetId = "modelSearch" }))
{
#Html.AntiForgeryToken()
<div class="input-group">
#Html.TextBox("search", null, new {id = "name", #class = "form-control", placeholder = "Please enter a manufacturer or model"})
<span class="input-group-btn">
<button id="search" class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
</span>
</div>
if (Model != null)
{
<div id="searchResults" class="fade">
#foreach (var s in Model)
{
<div class="result">
#switch (s.ResultType)
{
case "Man":
#s.Manufacturer
break;
case "Mod":
#s.Manufacturer #s.Model
<img src="~/Images/General/(#s.TierId).png" alt="Tier #s.TierId"/>
break;
}
</div>
}
</div>
}
}
</div>
</div>
</div>
And my Ajax call:
public PartialViewResult _GetSearch(List<Search> model, string search)
{
if (search != null)
{
var results = SearchModels(search).ToList();
model = results;
}
return PartialView("_Search", model);
}
Any idea why this might be happening?
Create a id before the partial view call.
And after the ajax call and append the partial view to that div. Like below
Don't forgot to empty the div before you append.
<div id="yourdivid">
#Html.Action("_GetSearch", "Home");
</div>

Categories