skip to Main Content

I’m currently learning RazorPages in codeacademy.com.
I did everything that was shown in the video Tutorial, and unfortunately is doesn’t work:

The task for the project:
"Data Delete
The current project has a button on the Index page list that deletes the current Continent or Country. The button will be modified to call a discrete Delete.cshtml page. This page will display the current record for review and provide a Delete button. Once the deletion occurs, the user is redirected back to the list so they get visual feedback of a successful task.

The code and markup are easily copied from the existing Detail.cshtml page. After copying that page, we add a delete button and copy the necessary statements from the OnPostAsync() method in the Index.cshtml.cs page."
The Delete page was created. The problem is:
When I press button Delete on the Delete page I have redirection to this link in browser:

https://localhost/Continents/Delete/SA?Continent.ID=SA

Actually no Delete happends
No redirection

What mistakes maybe here?

The code Delete.cshtml:

@page "{id}"
@model DeleteModel
@{
  ViewData["Title"] = "Continent Delete";
}

<div class="jumbotron p-3">
  <div class="d-flex align-items-center">
    <h1 class="display-4 flex-grow-1">
      Continent Delete
    </h1>
    <a class="btn btn-primary btn-sm" asp-page="./Index">
      Back to List
    </a>
  </div>
</div>
[enter image description here](https://i.stack.imgur.com/tFnrX.jpg)
<div class="d-flex">
  <div class="p-2 bg-primary text-white text-right" style="flex:0 0 15%">
    @Html.DisplayNameFor(model => model.Continent.ID)
  </div>
  <div class="p-2 border-top border-right border-bottom border-primary" style="flex:1 0 auto">
    @Html.DisplayFor(model => model.Continent.ID)
  </div>
</div>
<div class="d-flex">
  <div class="p-2 bg-primary text-white text-right" style="flex:0 0 15%">
    @Html.DisplayNameFor(model => model.Continent.Name)
  </div>
  <div class="p-2 border-right border-bottom border-primary" style="flex:1 0 auto">
    @Html.DisplayFor(model => model.Continent.Name)
  </div>
</div>

<form metod="post" class="d-flex flex-row-reverse mt-3">
  <input type="hidden" asp-for="Continent.ID"/>
  <input type="submit" value="Delete" class="btn btn-danger btn-sm"/>
</form>

Delete.cshtml.cs:

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorCountry.Models;
using RazorCountry.Data;

namespace RazorCountry.Pages.Continents
{
  public class DeleteModel : PageModel
  {
    private readonly CountryContext _context;

    public DeleteModel(CountryContext context)
    {
      _context = context;
    }

    public Continent Continent { get; set; }

    public async Task<IActionResult> OnGetAsync(string id)
    {
      Continent = await _context.Continents
        .Include(c => c.Countries)
        .AsNoTracking()
        .FirstOrDefaultAsync(m => m.ID == id);

      if (Continent == null)
      {
        return NotFound();
      }

      return Page();
    }
    public async Task<IActionResult> OnPostAsync(string id)
    {
      if (id == null)
      {
        return NotFound();
      }
      // Find the continent
      Continent Continent = await _context.Continents.FindAsync(id);
      //Delete the continent
      if (Continent != null)
      {
        _context.Continents.Remove(Continent);
      }
      //Persist Changes
      await _context.SaveChangesAsync();
      //Redirect to the user
      return RedirectToPage("./Index");
    }
  }
}

Model Continent.cs:

using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;

namespace RazorCountry.Models
 {
public class Continent
  {
[Required, StringLength(2, MinimumLength = 2), Display(Name = "Code")]
[RegularExpression(@"[A-Z]+", ErrorMessage = "Only upper case characters are allowed.")]
public string ID { get; set; }

[Required]
public string Name { get; set; }

public ICollection<Country> Countries { get; set; }
  }
 }

Try to understand how RazorPages functional works, try to fix mistake in a correct way

2

Answers


  1. Chosen as BEST ANSWER

    Thanks to @MikeBrind finally, I changed the code

    <form method="post" class="d-flex flex-row-reverse mt-3">
      <input type="hidden" name="id" value="@Model.Continent.ID"/>
      <input type="submit" value="Delete" class="btn btn-danger btn-sm"/>
    </form>
    

    And it works!


  2. The reason that no error occurs is because your OnPostAsync method is not being hit. You have mis-spelled the method attribute in your form (you have metod) so submitting it generates the default GET request and your OnGetAsync handler is executed instead.

    Once you have corrected that error, you still have an unresolved issue.

    Your OnPostAsync handler expects a parameter named id. The hidden field tag helper in your form generates a parameter with a name of Continent.ID. Consequently the value will not be bound to the id parameter. The simplest solution is to do away with the tag helper in the form a the bottom of your Delete page and replace it with a plain HTML input with a name attribute:

    <form method="post" class="d-flex flex-row-reverse mt-3">
      <input type="hidden" name="id" value="@Continent.ID"/>
      <input type="submit" value="Delete" class="btn btn-danger btn-sm"/>
    </form>
    

    You can read more about model binding in general here: https://www.learnrazorpages.com/razor-pages/model-binding

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search