HttpPost method in controller not coordinating with HttpGet method - asp.net-core-mvc

I tried to insert a breakpoint before each action and I was stuck at a point when ClassId value in HttpGet method takes the actual(correct)Id of the class which needs to be deleted but ClassId value in HttpPost method does not match with the ClassId value of the HttpGet method, infact value of ClassId in HttpPost returns null due to which I run into an exception error that object has null value. It would be really great if any one can acknowledge me that how that error can be removed. Thanks. Below is the code for the controller and the corresponding view respectively.
Controller Code
[HttpGet]
public IActionResult Delete(int ClassId)
{
return View(db.Class.Include(x => x.Student).First(c => c.ClassId == ClassId));
}
[ActionName("Delete")]
[HttpPost]
public IActionResult DeletePost(int ClassId)
{
var r = db.Class.First(a => a.ClassId == ClassId);
var student = r.StudentId.ToString();
db.Remove(r);
db.SaveChanges();
return RedirectToAction("Details", "Student", new { id = student });
}
View Code
#model DemoProject.Models.Class
#{
ViewData["Title"] = "Delete Class";
}
<h3>Are you sure you want to delete this?</h3>
<div>
<hr />
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.ClassName)
</dt>
<dd>
#Html.DisplayFor(model => model.ClassName)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
#Html.DisplayFor(model => model.Title)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Text)
</dt>
<dd>
#Html.DisplayFor(model => model.Text)
</dd>
</dl>
<form asp-action="Delete">
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-danger" />
<div class="row">
<a asp-action="Details" asp-controller="Student" asp-route-id="#Model.Student.StudentId">Back</a>
</div>
</div>
</form>
</div>

You have two options:
As #stephen.vakil said, add a hidden field for the ClassId property to your view within the <form> element.
View with Hidden Field
#model ModelBinding.Models.Class
#{
ViewData["Title"] = "Delete Class";
}
<h3>Are you sure you want to delete this?</h3>
<div>
<hr/>
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.ClassName)
</dt>
<dd>
#Html.DisplayFor(model => model.ClassName)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
#Html.DisplayFor(model => model.Title)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Text)
</dt>
<dd>
#Html.DisplayFor(model => model.Text)
</dd>
</dl>
<form asp-action="Delete">
<div class="form-actions no-color">
#Html.HiddenFor(model => model.ClassId)
<input type="submit" value="Delete" class="btn btn-danger"/>
<div class="row">
<a asp-action="Details" asp-controller="Student" asp-route-id="#Model.Student.StudentId">Back</a>
</div>
</div>
</form>
</div>
Add asp-route-id="#Model.ClassId" to your <form> tag and change the ClassId parameter name of your DeletePost method to id.
View with asp-route-id
#model ModelBinding.Models.Class
#{
ViewData["Title"] = "Delete Class";
}
<h3>Are you sure you want to delete this?</h3>
<div>
<hr/>
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.ClassName)
</dt>
<dd>
#Html.DisplayFor(model => model.ClassName)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
#Html.DisplayFor(model => model.Title)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Text)
</dt>
<dd>
#Html.DisplayFor(model => model.Text)
</dd>
</dl>
<form asp-action="Delete" asp-route-id="#Model.ClassId">
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-danger"/>
<div class="row">
<a asp-action="Details" asp-controller="Student" asp-route-id="#Model.Student.StudentId">Back</a>
</div>
</div>
</form>
</div>
Controller with Renamed Action Parameter
[HttpGet]
public IActionResult Delete(int classId)
{
return View(db.Class.Include(x => x.Student).First(c => c.ClassId == classId));
}
[ActionName("Delete")]
[HttpPost]
public IActionResult DeletePost(int id)
{
var r = db.Class.First(a => a.ClassId == id);
var student = r.StudentId.ToString();
db.Remove(r);
db.SaveChanges();
return RedirectToAction("Details", "Student", new { id = student });
}
Unless you just can't use <hidden> fields for some reason, option 1 is the superior choice.

Related

How to pass the model ID across the pages in Asp.Net

I want to pass the Model.Game ID from Details page to another view page which is Cart.
The way I do is inserting the #Html.DisplayFor(model => model.Game.ID) in the app-route-id. Is that appropriate to do so?
Details.cshtml
#page "{id:int}"
#model GameSanctuary.Pages.Games.DetailsModel
#{
ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
<h4>Game</h4>
<hr />
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.Game.G_Description)
</dt>
<dd>
#Html.DisplayFor(model => model.Game.G_Description)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Game.G_Genre)
</dt>
<dd>
#Html.DisplayFor(model => model.Game.G_Genre)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Game.G_Price)
</dt>
<dd>
#Html.DisplayFor(model => model.Game.G_Price)
</dd>
</dl>
</div>
<div>
<a asp-page="./Index">Back to List</a>
<a asp-page="./Cart" asp-page-handler="buynow" class="btn" asp-route-id="#Html.DisplayFor(model => model.Game.ID)">Add to Cart</a>
</div>
Cart.cshtml.cs
public async Task<IActionResult> OnGetBuyNow(int id)
{
cart = SessionHelper.GetObjectFromJson<List<Item>>(HttpContext.Session, "cart");
if (cart == null)
{
cart = new List<Item>();
cart.Add(new Item
{
Game = await _context.Game.FirstOrDefaultAsync(m => m.ID == id)
});
SessionHelper.SetObjectAsJson(HttpContext.Session, "cart", cart);
}
return RedirectToPage("Cart");
}
The id value that I retrieved in OnGetBuyNow is 0 but the expected value should be 1 based on the model.Game.ID in Details.cshtml. Is that something missing in between?
no, it's not appropriate.
Html.DisplayFor() renders the display template which matches whatever type you use it on. That's not what you want. What you want is a simple number surely which can be injected directly like this:
asp-route-id="#Model.Game.ID"
I would start there and see if that gives you what you want

Input Multiple Data Codeigniter

Sorry if this question has been asked before. I would like to ask for help to check my script below. Because when I tried to submit my form with multiple input field it only results in one data, whereas, there should be two data entered into the database.
So, which part of my script is wrong?
Controller
public function add() {
// ... some script before 'else' ...
} else {
$post = $this->input->post();
$result = array();
$total_input = count($post['input_acc_code']);
foreach ($post['input_acc_code'] as $key => $value) {
$result[] = array(
'trans_type' => 'journal',
'form_type' => NULL,
'acc_code' => $post['input_acc_code'][$key],
'acc_type_id' => $post['input_acc_type_id'][$key],
'refference' => '',
'customer_ID' => NULL,
'acc_side' => '',
'debet' => $post['input_debet'][$key],
'credit' => $post['input_credit'][$key],
'summary' => $post['input_note'][$key],
'files' => NULL,
'create_at' => date("Y-m-d H:i:s", strtotime("now"))
);
if($this->model_transaction->savedata('fi_acc_journal', $result) == TRUE) {
$this->session->set_flashdata('alert', 'Success');
redirect(base_url().'admin/transaction');
} else {
$this->session->set_flashdata('alert', 'Failed');
redirect(base_url().'admin/transaction');
}
}
}
}
Model
function savedata($table, $data = array()) {
$this->db->insert_batch($table, $data);
if($this->db->affected_rows() > 0) {
return TRUE;
}
return FALSE;
}
View
<?php $attributes = array('class' => 'form-horizontal', 'id' => '');
echo form_open_multipart(base_url().$this->session->userdata('user_status').'/transaction/add', $attributes);?>
<div class="row">
<div class="col-sm-12 col-md-12 panel-form-input">
<div class="form-group form-group-sm">
<label for="input_datetime" class="col-sm-2 control-label">Tanggal Transaksi</label>
<div class="col-sm-10">
<input type="text" class="input-date form-control" name="input_datetime[]" id="input-date">
<?php echo form_error('input_datetime');?>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12 panel-form-input">
<div class="panel panel-default">
<div class="table-responsive">
<table class="table table-unbordered">
<thead>
<th class="col-25">Account</th>
<th class="col-5">Account Type</th>
<th class="col-35">Notes</th>
<th class="col-15">Debet</th>
<th class="col-15">Credit</th>
<th class="col-5"></th>
</thead>
<tbody>
// First Input Field Form Table
<tr>
<td class="col-25">
<div class="form-group form-group-sm">
<div class="col-sm-12">
<select class="select-transaction input-group-sm form-control" name="input_acc_code[]" id="acc_code_1">
<?php if ($account_list != NULL): ?>
<option>— Choose Account Number —</option>
<?php foreach ($account_list as $value): ?>
<option value="<?php echo $value->acc_code;?>"><?php echo $value->acc_name;?></option>
<?php endforeach;?>
<?php else:?>
<option>— No Data —</option>
<?php endif;?>
</select>
<?php echo form_error('input_acc_code[]');?>
</div>
</div>
</td>
<td class="col-5">
<div class="form-group form-group-sm">
<div class="col-sm-12">
<input type="text" class="form-control" name="input_acc_type_id[]" id="acc_type_id_1">
<?php echo form_error('input_acc_type_id[]');?>
</div>
</div>
</td>
<td class="col-35">
<div class="form-group form-group-sm">
<div class="col-sm-12">
<input type="text" class="form-control" name="input_note[]">
<?php echo form_error('input_note[]');?>
</div>
</div>
</td>
<td class="col-15">
<div class="form-group form-group-sm">
<div class="col-sm-12">
<input type="text" class="form-control" name="input_debet[]">
</div>
</div>
</td>
<td class="col-15">
<div class="form-group form-group-sm">
<div class="col-sm-12">
<input type="text" class="form-control" name="input_credit[]">
</div>
</div>
</td>
<td class="col-5"></td>
</tr>
// Second Input Field Form Table
<tr>
<td class="col-25">
<div class="form-group form-group-sm">
<div class="col-sm-12">
<select class="select-transaction input-group-sm form-control" name="input_acc_code[]" id="acc_code_1">
<?php if ($account_list != NULL): ?>
<option>— Choose Account Number —</option>
<?php foreach ($account_list as $value): ?>
<option value="<?php echo $value->acc_code;?>"><?php echo $value->acc_name;?></option>
<?php endforeach;?>
<?php else:?>
<option>— No Data —</option>
<?php endif;?>
</select>
<?php echo form_error('input_acc_code[]');?>
</div>
</div>
</td>
<td class="col-5">
<div class="form-group form-group-sm">
<div class="col-sm-12">
<input type="text" class="form-control" name="input_acc_type_id[]" id="acc_type_id_1">
<?php echo form_error('input_acc_type_id[]');?>
</div>
</div>
</td>
<td class="col-35">
<div class="form-group form-group-sm">
<div class="col-sm-12">
<input type="text" class="form-control" name="input_note[]">
<?php echo form_error('input_note[]');?>
</div>
</div>
</td>
<td class="col-15">
<div class="form-group form-group-sm">
<div class="col-sm-12">
<input type="text" class="form-control" name="input_debet[]">
</div>
</div>
</td>
<td class="col-15">
<div class="form-group form-group-sm">
<div class="col-sm-12">
<input type="text" class="form-control" name="input_credit[]">
</div>
</div>
</td>
<td class="col-5"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12">
<div class="menu-bar">
<button class="btn btn-md btn-primary" type="submit">Save</input>
</div>
</div>
</div>
<?php echo form_close();?>
Thank you for your help....
Try moving the insert_batch related model call out of the foreach, as otherwise you could just run a straight insert there. First you are building the queries to insert, then after the foreach you insert the multidimensional array!
public function add()
{
$post = $this->input->post();
$result = array();
$total_input = count($post['input_acc_code']);
foreach ($post['input_acc_code'] as $key => $value) {
$result[] = array(
'trans_type' => 'journal',
'form_type' => NULL,
'acc_code' => $post['input_acc_code'][$key],
'acc_type_id' => $post['input_acc_type_id'][$key],
'refference' => '',
'customer_ID' => NULL,
'acc_side' => '',
'debet' => $post['input_debet'][$key],
'credit' => $post['input_credit'][$key],
'summary' => $post['input_note'][$key],
'files' => NULL,
'create_at' => date("Y-m-d H:i:s", strtotime("now"))
);
}
if ($this->model_transaction->savedata('fi_acc_journal', $result) == TRUE) {
$this->session->set_flashdata('alert', 'Success');
redirect(base_url() . 'admin/transaction');
} else {
$this->session->set_flashdata('alert', 'Failed');
redirect(base_url() . 'admin/transaction');
}
}

How to reload part of main view after submit using ajax

I'm new to MVC. How can I refresh part of my main view after submit action in one of my partial views. I'm trying to make adding comments. I didn't use ajax until now so any help is good. I want after I create new comment in PartialView "Create" that it appers in PartialView GetCommentsByTicket...I hope that this is enough explanation...
#model HelpDeskApp.Models.Ticket
#{
ViewBag.Title = "Details";
}
#*<h2>Details</h2>*#
<div class="panel panel-green">
<div class="panel-heading">
Ticket
</div>
<div class="panel-body">
<div>
#*<h4>ticket</h4>
<hr />*#
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.TicketId)
</dt>
<dd>
#Html.DisplayFor(model => model.TicketId)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Subject)
</dt>
<dd>
#Html.DisplayFor(model => model.Subject)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Description)
</dt>
<dd>
#Html.DisplayFor(model => model.Description)
</dd>
<dt>
#Html.DisplayNameFor(model => model.AddedDate)
</dt>
<dd>
#Html.DisplayFor(model => model.AddedDate)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Category1.Name)
</dt>
<dd>
#Html.DisplayFor(model => model.Category1.Name)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Priority1.Name)
</dt>
<dd>
#Html.DisplayFor(model => model.Priority1.Name)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Status1.Name)
</dt>
<dd>
#Html.DisplayFor(model => model.Status1.Name)
</dd>
<dt>
#Html.DisplayNameFor(model => model.User.FirstName)
</dt>
<dd>
#Html.DisplayFor(model => model.User.FirstName)
</dd>
</dl>
</div>
<p>
#*#Html.ActionLink("Edit", "Edit", new { id = Model.TicketId }) |*#
#Html.ActionLink("Back to List", "Index")
</p>
<div id="postcomments">
<hr />
<h4>Komentari</h4>
#{ Html.RenderAction("CommentsByTicket", "Comments", new { ticketId = Model.TicketId });}
</div>
<div id="create comments">
#{ Html.RenderAction("Create", "Comments", new { Ticket = Model.TicketId });}
</div>
</div>
</div>
<div class="panel-footer">
Panel Footer
</div>
</div>

Delete page not showing selected record

This is homework, an ASP.NET MVC and Web forms Web application using a repository (with data hard coded and no database) to rate doctors. The user should be able to edit and delete records, but when the application is run, and the "Delete" link is pressed for one of the records, the Delete page does not show the details of that record. Why not?
Here are the Delete methods:
public ActionResult Delete(string DoctorPicture)
{
repo.Remove(DoctorPicture);
return View("Delete");
}
[HttpPost]
public ActionResult Delete(string DoctorPicture, FormCollection collection)
{
try
{
// TODO: Add delete logic here
repo.Remove(DoctorPicture);
return View("Delete");
}
catch
{
return View();
}
}
From repo.Remove(DoctorPicture); it goes here in TestDoctorRepository, and doctor is null. Is it supposed to be?
public void Remove(string DoctorPicture)
{
var doctor = from d in doctors where d.DoctorPicture == DoctorPicture select d;
doctors.Remove(doctor.FirstOrDefault());
}
This is what my list of doctors looks like. Is my path for the images posing a problem?
public TestDoctorRepository()
{
doctors = new List<Doctor> {
new Doctor { DoctorPicture = "Images/0cropped.jpg", DoctorName = "Michael Shores", DoctorSpecialty = "Opthamology", times = 0, rating = 0, rated = true, avg=0, fave = true },
//more doctors
};
}
public Doctor GetDoctorByDoctorPicture(string DoctorPicture)
{
var selectedDoctor = from d in doctors
where d.DoctorPicture == DoctorPicture
select d;
return selectedDoctor.FirstOrDefault();
}
Delete View:
#model MidtermApplication.Models.Doctor
#{
ViewBag.Title = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<fieldset>
<legend>Doctor</legend>
<div class="display-label">
#Html.DisplayNameFor(model => model.DoctorPicture)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.DoctorPicture)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.DoctorName)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.DoctorName)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.DoctorSpecialty)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.DoctorSpecialty)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.rating)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.rating)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.times)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.times)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.fave)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.fave)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.rated)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.rated)
</div>
</fieldset>
#using (Html.BeginForm()) {
<p>
<input type="submit" value="Delete" /> |
#Html.ActionLink("Back to List", "Index")
</p>
}

2 validation groups

I have 2 validation forms on page.
<div id='LogOn' style="background-color: White;">
#using (Ajax.BeginForm("LogOnAjax", "Home", new AjaxOptions { UpdateTargetId = "LogOn", OnSuccess = "logInComplete" }))
{
//ITW2012Mobile.ViewModels.LogOnModel m = Model;
#Html.HiddenFor(model => model.IsLoggedIn)
#Html.HiddenFor(model => model.ReturnUrl)
<div>
#Html.ValidationSummary()
</div>
<div>
#Html.LabelFor(model => model.UserName)
#Html.EditorFor(model => model.UserName)
</div>
<div>
#Html.LabelFor(model => model.Password)
#Html.EditorFor(model => model.Password)
</div>
<div>
<input type="submit" value="Login" />
</div>
}
</div>
and
<fieldset>
#using (Html.BeginForm(Model.ActionMethod, Model.Controller))
{
#Html.ValidationSummary()
.....
<div class="display-label"> E-mail Address * </div>
<div class="display-field">
#Html.EditorFor(model => model.Username)
#Html.ValidationMessageFor(model => model.Username)
</div>
<div class="display-label"> Create Password * </div>
<div class="display-field">
#Html.PasswordFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
</div>
<p>
<input type="submit" value="Create" />
</p>
}
</fieldset>
How can I mark that ModelState.AddModelError is for first of form, because I see the same error in the both places of validation summary?
How can I mark that ModelState.AddModelError is for first of form
You can't.
What you can do is having ValidationMessageFor for each form properties instead of the ValidationSummary

Resources