Delete Action does not activate/trigger ASP.NET Core MVC - asp.net-mvc

HttpPost on delete action does not trigger, however HttpGet seems working fine as i get the content displayed. However I have little confusion in the following route address generated when I click on HttpGet on delete action:-
https://localhost:44394/9
shouldn't it generates link like this: https://localhost:44394/Post/DeletePost/9
Controller:-
[HttpPost, ActionName("DeletePost")]
public async Task<IActionResult> ConfirmDelete(int id)
{
await _repository.DeletePostAsync(id);
return RedirectToAction(nameof(GetAllPosts));
}
[HttpGet("{id}")]
public async Task<IActionResult> DeletePost(int id)
{
var post = await _repository.GetPostById(id);
if(post == null)
{
return NotFound();
}
return View(post);
}
Razor View for HttpGet:-
<div class="btn btn-outline-danger delete">
<a href="#Url.Action("DeletePost", "Post", new { id = p.Id })">Delete
</a>
</div>
Razor Page HttpPost:-
<div class="container">
<div class="row">
<div class="col-9">
<p>
#Model.Topic
</p>
<p class="timeStampValue" data-value="#Model.Published">
#Model.Published
</p>
<p>
#Model.Author
</p>
<section>
<markdown markdown="#Model.Content" />
</section>
</div>
</div>
<form asp-action="DeletePostAsync">
<input type="hidden" asp-for="Id" />
<button type="submit" class="btn btn-outline-danger">Delete</button>
</form>
Cancel
</div>
Routing:-
app.UseMvc(routes =>
{ routes.MapRoute(
name: "KtsPost",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Post", action = "Index" },
constraints: new { id = "[0-9]+" });
});

Your action name is wrong in the form. Your code should be instead:
<form asp-action="DeletePost">
<input type="hidden" asp-for="Id" />
<button type="submit" class="btn btn-outline-danger">Delete</button>
</form>

The default method of an HTML form is GET not POST. You need to tell your form to POST. Also, the action name should be ConfirmDelete:
<form asp-action="ConfirmDelete" method="post">
<input type="hidden" asp-for="Id" />
<button type="submit" class="btn btn-outline-danger">Delete</button>
</form>

Related

Edit action has not been hitting while I push the submit button

I have an edit button in each row of my Datatable. I have two actions for editing. One for Getting data in a Datatable and the other one for posting my information. The code behind my Edit button in the my Home Index is:
{
"data": "Id",
"render": function (data, type, full, meta) {
return `<div class="text-center"> <a class="btn btn-info"
href="/Home/EditGet/` + data + `" >Edit</a> </div> `;
}
and my home controller methods are:
/// Get Edit
[HttpGet]
[Route("{Id}")]
public IActionResult EditGet(int? id)
{
if (id == null || id == 0)
{
return NotFound();
}
var obj = _sv.OpenRecord(id);
if (obj == null)
{
return NotFound();
}
return View("EditGet", obj);
}
/// Post Edit
[HttpPost]
public IActionResult EditPost(SalesVeiwModel sales)
{
if (ModelState.IsValid)
{
var res= _sv.Update(sales.Comment);
if (res==null )
{
return Json(data: "Not found");
}
return RedirectToAction("EditGet");
}
return Json(data: "Is not valid");
}
And finally my EditGet view is like bellow:
<form id="contact-form" method="post" asp-controller="Home" asp-
action="EditPost" role="form" >
<input asp-for="Id" hidden />
<div class="form-group">
<label>Invoice Nomber</label>
<input id="form_IBNo" type="text" class="form-control" disabled asp-for="IBNo">
</div>
.
.
.
<div class="col-md-12">
<input type="submit" class="btn btn-success btn-send" value="Confirm" asp-
controller="Home" asp-action="EditGet">
</form>
You should have two buttons,one call EditGet,one call EditPost,here is a demo:
<form id="contact-form" method="post" asp-controller="Home" asp-
action="EditPost" role="form" >
<input asp-for="Id" hidden />
<div class="form-group">
<label>Invoice Nomber</label>
<input id="form_IBNo" type="text" class="form-control" disabled asp-for="IBNo">
</div>
.
.
.
<div class="col-md-12">
<input type="submit" class="btn btn-success btn-send" value="Confirm">
<a class="btn btn-success btn-send" value="Confirm" asp-controller="Home" asp-action="EditGet" asp-route-id="1">EditGet</a>
</div>
</form>

Multiple forms in one view page

I'm working on an application that handles employee's profile.
I have 3 forms (all in the same controller) in a single view page, but it only saves the 1st form. And when i save the 2nd form, it clears the values of the 1st and 3rd form.
Here is my code:
Views/EMPs/Index:
#using (Html.BeginForm("Edit", "EMPs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="personalsubmit" class="btn btn-success" />
</div>
</div>
}
#{ Html.RenderAction("Index", "EMP_REFERENCE", new { id = Model.eMP.lineno });}
#using (Html.BeginForm("Edit", "EMPs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="jobsubmit" class="btn btn-success" />
</div>
</div>
}
#{ Html.RenderAction("Index", "EMP_BENEFITS", new { id = Model.eMP.lineno });}
#using (Html.BeginForm("Edit", "EMPs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="otherssubmit" class="btn btn-success" />
</div>
</div>
}
EMPsController
public ActionResult Edit([Bind(Include = "lineno,EMPNO,IDNO..")] EMP eMP)
{
if (ModelState.IsValid)
{
if (Request.Form["personalsubmit"] != null)
{
db.Entry(eMP).State = EntityState.Modified;
db.SaveChanges();
}
if (Request.Form["jobsubmit"] != null)
{
db.Entry(eMP).State = EntityState.Modified;
db.SaveChanges();
}
if (Request.Form["otherssubmit"] != null)
{
db.Entry(eMP).State = EntityState.Modified;
db.SaveChanges();
}
return Redirect(Request.UrlReferrer.PathAndQuery);
}
return View(eMP);
}
I couldn't put them all in one form, because i used an ajax beginForm between them for another crud method. Since I've read that nested forms are not recommended.
Is there a way to save one form without it clearing the values of the other forms?
Is there a way to save one form without it clearing the values of the other forms?
You could simply use ajax.beginform for each of those forms;
How to use Simple Ajax Beginform in Asp.net MVC 4?
Or you could make your own ajax implementation
https://www.c-sharpcorner.com/blogs/using-ajax-in-asp-net-mvc
Or you could just go ahead and bind everything on your model;
// don't need to specify which properties to bind, all of the available properties in your view will be bound to the model on POST
public ActionResult Edit(EMP eMP)
{
if(eMP.FirstName!=null ...){
// ... do some checking depending on what values are submitted
}
// save profile here
// when you return the view
return View(eMP);
}
but for this method you need to only have 1 form for Personal,Job, and Others.
#{ Html.RenderAction("Index", "EMP_REFERENCE", new { id = Model.eMP.lineno });}
#{ Html.RenderAction("Index", "EMP_BENEFITS", new { id = Model.eMP.lineno });}
#using (Html.BeginForm("Edit", "EMPs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<!--put all your employee input fields here-->
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="submit" class="btn btn-success" />
</div>
</div>
<!--put all your job input fields here-->
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="submit" class="btn btn-success" />
</div>
</div>
<!--put all your others input fields here-->
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="submit" class="btn btn-success" />
</div>
</div>
}

Bad Request MVC HttpPost

I have the following cshtml file.
#model Models.AuthorizeUser
#{
ViewBag.Title = "Authorize";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container">
<div class="card card-container">
<img class="profile-img-card" src="~/Content/images/rblogo_reverse-pms348_000.gif" />
<p> </p>
<form method="POST">
<p>Hello, #Model.Name</p>
<p>A third party application want to do the following on your behalf:</p>
<ul>
#foreach (var scope in Model.Scopes)
{
<li>#scope.ScopeDescription</li>
}
</ul>
<div class ="row">
<div class="col-md-4">
<button class="btn btn-block btn-primary btn-signin" name="submit" type="submit" value="authorize">Grant</button>
</div>
<div class="col-md-8">
<button class="btn btn-block btn-primary btn-signin btn-small-text" name="submit" type="submit" value="logout">Sign in as different user</button>
</div>
</div>
</form>
</div>
</div>
I have my controller file as follows:
public class OAuthController : Controller
{
[HttpGet]
public ActionResult Authorize()
{
logger.Trace("Authorize method entered");
AuthorizeUser authorizeUser;
......
return View(authorizeUser);
}
[HttpPost]
public ActionResult Authorize(AuthorizeUser authorizeUser, string submit)
{
logger.Trace("Authorize with object");
if (Response.StatusCode != 200)
{
logger.Trace("status code " + Response.StatusCode);
logger.Trace("status description " + Response.StatusDescription);
return View("AuthorizeError");
}
..............
}
When the form is displayed, the info is displayed correctly. After I click Grant button, I got Response.StatusCode == 400. Both authorizeUser and submit are null. I am expecting StatuCode == 200 with values of authrizeUser and submit.
Have you tried using Html.BeginForm()?
Instead of using <form method="POST"> you could use Html.BeginForm("Action", "Controller")

How do I redirect from an MVC Post Action back to the bootstrap popup modal partial view where the post came from?

How do I redirect from an MVC Post Action back to the bootstrap popup modal partial view where the post came from?
Here is the PartialView sitting in the Bootstrap modal popup on the page.
It has a div with a validation taghelper waiting for any model errors.
#model CreateRoleViewModel
<div class="panel panel-primary partialModalFormDivs">
#Html.Partial("_ModalHeader",
new ModalHeader
{
Heading = "ADD ROLE",
glyphiconClass = "glyphicon glyphicon-random"
}
)
<div class="panel-body">
<div asp-validation-summary="All" class="text-danger"></div>
<form asp-action="CreateRole" method="post">
<div class="form-group">
<label asp-for="RoleName"></label>
<input asp-for="RoleName" class="form form-control" />
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Create</button>
<a asp-action="Index" class="btn btn-default">Cancel</a>
</div>
</form>
</div>
</div>
It posts to this action:
[HttpPost]
public async Task<IActionResult> CreateRole(CreateRoleViewModel createRoleViewModel)
{
if (ModelState.IsValid)
{
IdentityRole role = new IdentityRole(createRoleViewModel.RoleName);
IdentityResult result
= await _roleManager.CreateAsync(role);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
foreach (IdentityError error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
}
}
return View(createRoleViewModel);
}
I can return a PartialView like this at the end:
return View("_CreateRole", createRoleViewModel);
But then the whole page is cleared and this partial is returned with no layout file.
How can I return the results back to the modal popup window.
I understand the problem and the current behavior. But has anyone else solved this?
I think what you want to do is an ajax post and then just return a partial view and replace the form. The form should be inside a container div with an id that is used to replace its contents with the ajax post result. To do this you need to include the jquery unobtrusive ajax script which will auto wire the ajax based on the data-* attributes on the form as shown below
<div class="panel-body">
<div asp-validation-summary="All" class="text-danger"></div>
<div id="resultcontainer">
<form asp-action="CreateRole" method="post"
data-ajax="true"
data-ajax-method="POST"
data-ajax-mode="replace"
data-ajax-update="#resultcontainer"
>
<div class="form-group">
<label asp-for="RoleName"></label>
<input asp-for="RoleName" class="form form-control" />
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Create</button>
<a asp-action="Index" class="btn btn-default">Cancel</a>
</div>
</form>
</div>
</div>
and don't forget to return a partial view
return PartialView(createRoleViewModel);

MVC - Action passing to wrong controller

I have a form that submits a SearchByUserViewModel (containing only string ID) to asp-controller="Home" asp-action="SubmitUserSearch". The form is a single textbox and a submit button. SubmitUserSearch retrieves the ID from the model and returns RedirectToAction("EventListByArtist", m.ID).
EventListByArtist, in the Home controller, is as follows:
public IActionResult EventListByArtist(string ID)
{
var events = context.Events.ToList();
ViewBag.genres = context.Genres.ToList();
ViewBag.artists = context.Artists.ToList();
ViewBag.ID = ID;
return View("EventList", events);
}
SubmitUserSearch redirects to EventListByArtist:
public IActionResult SubmitUserSearch(SearchByUserViewModel m)
{
return RedirectToAction("EventListByArtist", m.ID);
}
The SearchByUserViewModel contains only the ID field.
However, something in the middle breaks, and instead of being directed to (for example input "Bob") Home/EventListByArtist/Bob, I am directed to Bob/EventListByArtist, which does not exist. What is causing this redirect? The form has been pasted below.
<form asp-controller="Home" asp-action="SubmitUserSearch" asp-route-returnurl="#ViewData["ReturnUrl"]" class="form-horizontal">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="ID" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="ID" class="form-control" id="artistInput" />
<span asp-validation-for="ID" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Search" />
</div>
</div>
</form>
The project routes declaration (in Startup.cs) is as follows:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
In your SubmitUserSearch() POST method the value of m.ID is a string ("Bob") so you RedirectToAction() translates to
return RedirectToAction("EventListByArtist", "Bob");
which is using this overload where the 2nd parameter is the name of the controller, hence it generates /Bob/EventListByArtist.
You need to use this overload where the 2nd parameter is object
return RedirectToAction("EventListByArtist", new { id = m.ID });

Resources