MVC Model is empty when postback - c#

I have this model, Customer . When i get the information with an id, it works just fine.
Like ;
/Customer/Entity/5
#model ProgSpace.Models.Customer
#{
ViewBag.Title = Model.Name;
Layout = "~/Views/Shared/_MainLayout.cshtml";
}
#section bodypane
{
#using (Html.BeginForm("Entity", "Customer", FormMethod.Post, new { #enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="col-md-12">
<div class="col-md-1">
<label>Customer No:</label>
<h4># #(Model.ID) </h4>
</div>
<div class="clearfix"></div><br />
<div class="col-md-2">
<div class="col-md-12">
<div class="col-md-12 fileupload fileupload-exists" data-provides="fileupload">
<div class="fileupload-preview fileupload-exists thumbnail" style="width: 200px; height: 150px;">
<img src="#Model.Picture.Path" />
</div>
<div>
<span class="btn btn-default btn-file">
<span class="fileupload-new">Add Pic </span>
<span class="fileupload-exists">Change</span><input name="file" id="file" type="file">
</span>
Remove
</div>
</div>
</div>
</div>
<div class="col-md-10">
<div class="col-md-3">
<label>Name *</label>
#Html.TextBoxFor(model => model.Name, new { #class = "form-control"})
</div>
<div class="col-md-3">
<label>Company</label>
#Html.TextBoxFor(model => model.Contact.Company, new { #class = "form-control"})
</div>
<div class="col-md-3">
<label>Phone </label>
#Html.TextBoxFor(model => model.Contact.Phone, new { #class = "form-control" })
</div>
</div>
<div class="clearfix"><br /></div>
<p> </p>
<div class="col-md-12">
<div class="btn-group">
<button class="btn btn-danger btn-lg">Cancel</button>
<button type="submit" class="btn btn-success btn-lg">Send</button>
</div>
</div>
</div>
}
}
And in the controller i have these actions.
public ActionResult Entity(int id)
{
Customer cust= sis.Customers.Where(t => t.ID == id).FirstOrDefault();
return View(cust);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Entity(Customer cust, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
/* Do something */
}
else
{
}
return View(cust);
}
When the verb is GET , it's fine. But when i post this form and when the second action (HttpPost action) kicks in , view throws an error..
Object reference not set to an instance of an object
which marks the Model.ID is null in the view.
<div class="col-md-1">
<label>Customer No:</label>
<h4># #(Model.ID) </h4> ---> THIS HERE THROWS NULL EXCEPTION
</div>
I've tried to add a HiddenFor for the Model.ID like
#Html.HiddenFor(t => t.ID)
but it didn't change anything.
How do i get back to the same view with the same context again ?

Related

ViewModel returning null into form, how do I fix this

I can't seem to get the values I entered from the form into my action createEmployee method in the controller I think the issue is the ViewModel I may be wrong but how do I fix this. The only thing I able to recieve back when I run the project the random number I generated, and null variables, also how do I add the inputted Employee back to list side note my Employee list is hard coded
View.cs
#using (Html.BeginForm("CreateEmployee", "/Employee", FormMethod.Post))
{
<div class="row">
<div class="col-lg-2">First Name</div>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.Employee.Name, new { #class = "form-control" })
</div>
</div>
<br />
<div class="row">
<div class="col-lg-2">Last Name</div>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.Employee.Surname, new { #class = "form-control" })
</div>
</div>
<br />
<div class="row">
<div class="col-lg-2">Date of Birth</div>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.Employee.DateOfBirth, new { #class = "form-control" })
</div>
</div>
<br />
<div class="row">
<div class="col-lg-2">Department</div>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.Employee.Department, new { #class = "form-control" })
</div>
</div>
<br />
<div class="modal-footer">
<button type="submit" class="btn btn-primary center-block">Complete</button>
</div>
}
EmployeeViewModel
public List<Fundi.HR.Web.Models.Employee> Employees { get; set; }
public Employee Employee { get; set; }
public EmployeeViewModel(List<Employee> found)
{
this.Employees = found;
}
Action EmployeeController
public ActionResult CreateEmployee(Employee emp)
{
if (ModelState.IsValid)
{
Random random = new Random();
int num = random.Next();
Employee empObj = new Employee();
List<Employee> employees = new List<Employee>();
empObj.EmployeeId = num;
empObj.Name = emp.Name;
empObj.Surname = emp.Surname;
empObj.DateOfBirth = emp.DateOfBirth;
empObj.Department = emp.Department;
employees.Add(empObj);
EmployeeViewModel em = new EmployeeViewModel(employees);
return View("Index", em);
}
else
{
return RedirectToAction("Index");
}
For a simple test, I used part of your code so that the value can be accepted, you can refer to the following:
View:
#model WebApplication38.Models.Employee
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("CreateEmployee", "Test", FormMethod.Post))
{
<div class="row">
<div class="col-lg-2">First Name</div>
<div class="col-lg-10">
#Html.TextBoxFor(m=>m.name, new { #class = "form-control" })
</div>
</div>
<br />
<div class="row">
<div class="col-lg-2">Last Name</div>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.Surname, new { #class = "form-control" })
</div>
</div>
<br />
<div class="row">
<div class="col-lg-2">Date of Birth</div>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.DateOfBirth, new { #class = "form-control" })
</div>
</div>
<br />
<div class="row">
<div class="col-lg-2">Department</div>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.Department, new { #class = "form-control" })
</div>
</div>
<br />
<div class="modal-footer">
<button type="submit" class="btn btn-primary center-block">Complete</button>
</div>
}
Controller and result:

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>

MVC partial view controller not running on load

Im trying to load a MVC partial view in to a modal popup. The popup contains a drop down list which I am trying to populate on the ActionResult that loads when the view is loaded. The problem is the controller code isn't getting ran.
My code is as follows -
View:
<div id="modal_form_horizontal_addnote" class="modal fade">
<div class="modal-dialog modal-md">
<div class="modal-content">
<div class="modal-header bg-primary">
<button type="button" class="close" data-dismiss="modal">×</button>
<h5 class="modal-title">Add Note</h5>
</div>
#Html.Partial("AddNote", new IHD.Core.Models.CreateTicketNoteModel { TicketHeaderId = Model.Id })
</div>
</div>
The partial view:
#model IHD.Core.Models.CreateTicketNoteModel
#using (Html.BeginForm("AddNote", "Ticket", FormMethod.Post))
{
#Html.HiddenFor(model => model.TicketHeaderId)
#Html.AntiForgeryToken()
<div class="row">
<div class="col-md-12">
<div class="tab-content">
<div class="tab-pane active" id="highlighted-justified-tab1">
<div class="form-group">
#Html.LabelFor(model => model.WorkType, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-12">
#Html.DropDownListFor(model => model.WorkType, new SelectList(Model.WorkTypeOptions, "Key", "Value", Model.WorkType), new { #name = "select", #class = "form-control" })
#Html.ValidationMessageFor(model => model.WorkType, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</div>
</div>
}
The controller:
public ActionResult AddNotePhase(int id = 0, int taskId = 0)
{
CreateTicketPhaseNoteModel note = new CreateTicketPhaseNoteModel();
note.TicketHeaderId = id;
// Populate the work type dropdown list
note.WorkTypeOptions.Add("", "-- Select a Work Type --");
note.WorkTypes = _workTypeService.GetAll().ToList();
foreach (var c in note.WorkTypes)
{
note.WorkTypeOptions.Add(c.Id.ToString(), c.Description);
}
//note.PhaseTask = taskId;
return PartialView(note);
}
You controller code isn't being hit because you are passing a model to the partial view and not calling the action. You need to use #{Html.RenderAction();} instead to call your action with the appropriate values.

MVC Razor form button not calling controller specified

So within my view, I have:
<div id="createProductModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Create Product</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
#using (Html.BeginForm("Create", "Product", FormMethod.Post, new { id = "createProductForm", #class = "form-horizontal"}))
{
<div class="form-group">
<div class="col-md-4">
#Html.LabelFor(m => Model.Product.Name, new { #class = "control-label" })
</div>
<div class="col-sm-8">
#Html.TextBoxFor(m => Model.Product.Name, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-4">
#Html.LabelFor(m => Model.Product.IsActive, new { #class = "control-label" })
</div>
<div class="col-sm-8">
#Html.CheckBoxFor(m => Model.Product.IsActive, new { #class = "form-control" })
</div>
</div>
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal" onclick="$('#createProductForm').submit();">Add product</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
And then in my ProductsController I have added an action like so:
[HttpPost]
public ActionResult Create(Product product)
{
return View();
}
But for some reason when clicking submit it redirects me to this URL:
http://localhost/Product/Create
And throws a 404 error like so:
The resource cannot be found.
I've not defined a route within the route configs surely this shouldn't matter?
Does anyone understand what i seem to be doing wrong?
Second parameter of Html.BeginForm is the controller name. Given that you have a ProductsController, instead of
Html.BeginForm("Create", "Product", ...
Try
Html.BeginForm("Create", "Products"
Check FormExtensions.BeginForm

how to do a create partial view inside a edit view?

I can add a create partial view within a modal bootstrap so that it can add value in the table with a edit view of the field value ?
My create partial view
#model MVCLayout.Models.Table2
<p>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="form-group">
#Html.Label("Cargo: ", new { style = "width:160px" })
#Html.TextBoxFor(model => model.ID, new { style = "width:200px" })
</div>
<br/>
<div class="form-group">
#Html.Label("Percentual: ", new { style = "width:160px" })
#Html.TextBoxFor(model => model.Name, new { style = "width:200px" })
</div>
<br/>
<div class="form-group">
#Html.Label("Serviço: ", new { style = "width:160px" })
#Html.TextBoxFor(model => model.Work, new { style = "width:200px" })
</div>
<br/>
<p>
<input type="submit" value="Save" />
</p>
}
</p>
My Edit View
<html>
<body>
#model MVCLayout.Models.Table1
#{
ViewBag.Title = "Edit";
}
<div id="signup">
<div class="rontainer">
<div class="header">
<div id="dock">
<br>
#using (Html.BeginForm("Edit", "AdmServicos", FormMethod.Post, new { #class = "form-inline" }))
{
#Html.AntiForgeryToken()
<fieldset>
<legend>Editar Servios</legend>
<br>
<div class="form-group">
#Html.Label("Código:", new { style = "width:160px" })
#Html.TextBoxFor(model => model.ID, new { style = "width:55px", #readonly = "readonly" })
<div class="form-group">
#Html.Label("Descrição: ", new { style = "width:160px" })
#Html.TextBoxFor(model => model.Descricao, new { style = "width:550px", #readonly = "readonly" })
</div>
</div>
<br />
<br /><br />
<p>
<input type="submit" value="Salvar" />
</p>
</fieldset>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
#{
Html.RenderPartial("CreateTable2", Model.ID);
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
</body>
</html>
Can I do this with a partial view or the best way to do this?
create a property of Table2 type in your Table1 Model like below :
public class Table1
{
public Table2 table2 {get; set;}
//other properties of Table1 Model
}
Now in your Edit View:
<div class="modal-body">
#{
Html.RenderPartial("CreateTable2", Model.table2);
}
</div>
Now in your Action of the Controller :
public ActionResult Edit(Table1 model)
{
var editPartialViewData = model.table2;
// Do whatever you want to do with this data
}

Categories