Reputation: 605
I'm building a web application using ASP.NET Core 3.0. I have a model called Article
. I am having problems in two parts of my application where neither editing nor deleting an article are calling the correct POST
method handlers.
My Article
class is defined as follows in the namespace Models
:
Models/Articles.cs
public class Article
{
public int Id { get; set; }
[Required]
[StringLength(32)]
public string Title { get; set; }
[StringLength(512)]
public string Description { get; set; }
public string Content { get; set; }
}
Editing
I have a shared partial view called _Editor.cshtml
. It is defined as follows:
Pages/Articles/_Editor.cshtml
@model Models.Article
<div class="form-group">
<label asp-for="Title" class="control-label col-xs-4 col-md-2"></label>
<input asp-for="Title" class="form-control col-xs-8 col-md-10" />
<span asp-validation-for="Title" class="text-danger col"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label col-xs-4 col-md-2"></label>
<textarea asp-for="Description" class="form-control col-xs-8 col-md-10" style="height:4em"></textarea>
<span asp-validation-for="Description" class="text-danger col"></span>
</div>
<hr />
<div class="form-group">
<label asp-for="Content" class="control-label col-xs-4 col-md-2"></label>
<textarea asp-for="Content" class="form-control col-xs-8 col-md-10" style="height:16em"></textarea>
<span asp-validation-for="Content" class="text-danger col"></span>
</div>
I use this partial view from inside both the Edit.cshtml
and Create.cshtml
files as follows:
Pages/Articles/Edit.cshtml
@page
@model Pages.Articles.EditModel
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Article.Id" />
<partial name="_Editor" model="Model.Article" />
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</div>
</form>
Pages/Articles/Create.cshtml
@page
@model Pages.Articles.CreateModel
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<partial name="_Editor" model="Model.Article" />
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
Both of these Razor pages have standard scaffolded code-behind (.cshtml.cs) files. The create page works successfully but the edit page does not actually save the edits.
Deleting
On my View.cshtml
Razor Page, I want to have an article delete dialog that can be used in other pages throughout the project. I use the Delete.cshtml
partial view for this. It's code is as follows:
Pages/Articles/Delete.cshtml
@model Models.Article
<div class="modal" tabindex="-1" role="dialog" id="deletionModal">
<form id="deletionModalForm" asp-page="Articles/Delete" method="post">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete Article</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete the article "@Model.Title"?</p>
<input type="hidden" asp-for="@Model.Id" />
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-danger">Delete</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</form>
</div>
It is referenced in the View.cshtml
Razor page as follows:
Pages/Articles/View.cshtml
@page
@model Comprehension.Pages.Articles.ViewModel
<partial name="Delete" model="Model.Article" />
<div class="row mb-4">
<h2 class="col">@Model.Article.Title</h2>
<p class="col-auto">
<a asp-page="./Edit" asp-route-id="@Model.Article.Id" class="text-primary">Edit</a>
</p>
<p class="col-auto">
<a class="text-danger" data-toggle="modal" data-target="#deletionModal">Delete</a>
</p>
</div>
These two pages have code-behind (.cshtml.cs) files that were scaffolded in the usual way. Whenever the submit button is pressed in Delete.cshtml
, the OnPost
method in View.cshtml.cs
is called rather than the OnPost
method in Delete.cshtml.cs
.
I've tried adding @page
to the Delete.cshtml
to no avail. I've also tried everything as suggested by @Xing Zou.
It seems to me that these two issues originate from the same mistake but I'm not sure what that mistake is. Any help would be greatly appreciated.
For context, here is a screenshot of my project structure.
Upvotes: 0
Views: 1911
Reputation: 20116
My understanding is that , you click a button (named Delete) firstly, then a shared dialog pop up, you could see Title
in the dialog to confirm .Finally, click the Delete
button in the dialog to call the actual post handler to delete the article.
Below is my simple demo:
1._Delete.cshtml
Add id
for the model and add <form>
tag to submit to your delete handler
@model Models.Article
<div class="modal" tabindex="-1" role="dialog" id="myModal">
<form id="myForm" method="post">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete Article</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete the article "@Model.Title"?</p>
@*Pass current article ID*@
<input type="hidden" asp-for="@Model.Id" />
</div>
<div class="modal-footer">
<button type="submit" asp-page="Articles/Delete" class="btn btn-danger">Delete</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</form>
</div>
2.Index.cshtml:
<partial name="_Delete" model="@Model.Article" />
<button type="button" class="btn btn-primary myButton" data-toggle="modal" data-target="#myModal">
Delete
</button>
3.Pages/Articles/Delete.cshtml(Delete.cshtml.cs) Razor Page
public async Task<IActionResult> OnPostAsync(int? id)
{
//your delete logic
}
Edit 12/24/2019
Do not put partial view as razor pages, you just need to submit to a post hanlder behind one razor page.
Besides,asp-page
should use correct path, if you put your partial view in the same Articles folder,then it will change to asp-page="Delete"
Demo:
1.Create a partial view as Pages/Articles/MyDeletePartilaView.cshtml
:
@model Models.Article
<div class="modal" tabindex="-1" role="dialog" id="deletionModal">
<form id="deletionModalForm" asp-page="Delete" method="post">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete Article</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete the article "@Model.Title"?</p>
<input type="hidden" asp-for="@Model.Id" />
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-danger">Delete</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</form>
</div>
2.Pages/Articles/View.cshtml
<partial name="MyDeletePartilaView.cshtml" model="Model.Article" />
3.Pages/Articles/Delete.cshtml
@page
@model RazorpagesCore.Pages.Movies.DeleteModel
4.Pages/Articles/Delete.cshtml.cs
public class DeleteModel : PageModel
{
public async Task<IActionResult> OnPostAsync(int? id)
{
//your delete logic
}
}
Upvotes: 1