1
votes

I'm trying to execute this tutorial: https://www.tutorialspoint.com/asp.net_core/asp.net_core_razor_edit_form.htm

I have a NET Core Webapp and a small list with employees (id, name). I created a Index.cshtml, Details.cshtml and Edit.cshtml. The database connection is working. When I try to click the edit or details link behind the employee name the routing seems not to be working. I just get empty sites.

Index.cshtml

@using MyApp.Controllers
@model HomePageViewModel

@{
    ViewBag.Title = "Home";
}
<h1>Welcome!</h1>

<table>
    @foreach (var employee in Model.Employees)
    {
        <tr>
            <td>@employee.name</td>
            <td>
                <a asp-controller="Employee" asp-action="Details"
                   asp-routeid="@employee.id">Details</a>
                <a asp-controller="Employee" asp-action="Edit"
                   asp-routeid="@employee.id">Edit</a>
            </td>
        </tr>
    }
</table>

Edit.cshtml

@model MyApp.Models.Employees
@{
    ViewBag.Title = $"Edit {Model.name}";
}
<h1>Edit @Model.name</h1>

<form asp-action="Edit" method="post">
    <div>
        <label asp-for="name"></label>
        <input asp-for="name" />
        <span asp-validation-for="name"></span>
    </div>

    <div>
        <input type="submit" value="Save" />
    </div>
</form>

complete controller

using Microsoft.AspNetCore.Mvc;
using MyApp.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace MyApp.Controllers
{
    public class EmployeeController : Controller
    {
        public ViewResult Index()
        {
            var model = new HomePageViewModel();
            using (var context = new FirstAppDemoDbContext())
            {
                SQLEmployeeData sqlData = new SQLEmployeeData(context);
                model.Employees = sqlData.GetAll();
            }
            return View(model);
        }
        public IActionResult Details(int id)
        {
            var context = new FirstAppDemoDbContext();
            SQLEmployeeData sqlData = new SQLEmployeeData(context);
            var model = sqlData.Get(id);


         if (model == null)
            {
                return RedirectToAction("Index");
            }
            return View(model);
        }
        [HttpGet]
        public IActionResult Edit(int id)
        {
            var context = new FirstAppDemoDbContext();
            SQLEmployeeData sqlData = new SQLEmployeeData(context);
            var model = sqlData.Get(id);

            if (model == null)
            {
                return RedirectToAction("Index");
            }
            return View(model);
        }
        [HttpPost]
        public IActionResult Edit(int id, EmployeeEditViewModel input)
        {
            var context = new FirstAppDemoDbContext();
            SQLEmployeeData sqlData = new SQLEmployeeData(context);
            var employee = sqlData.Get(id);

            if (employee != null && ModelState.IsValid)
            {
                employee.name = input.Name;
                context.SaveChanges();
                return RedirectToAction("Details", new { id = employee.id });
            }
            return View(employee);
        }
    }
    public class SQLEmployeeData
    {
        private FirstAppDemoDbContext _context { get; set; }
        public SQLEmployeeData(FirstAppDemoDbContext context)
        {
            _context = context;
        }
        public void Add(Employees emp)
        {
            _context.Add(emp);
            _context.SaveChanges();
        }
        public Employees Get(int ID)
        {
            return _context.Employees.FirstOrDefault(e => e.id == ID);
        }
        public IEnumerable<Employees> GetAll()
        {
            return _context.Employees.ToList<Employees>();
        }
    }
    public class HomePageViewModel
    {
        public IEnumerable<Employees> Employees { get; set; }
    }
    public class EmployeeEditViewModel
    {
        [Required, MaxLength(80)]
        public string Name { get; set; }
    }
}

The application asks for localhost:xxxx/Employee/Edit with argument <0> (instead of id 1 or 2...) and is redirecting to my index list at localhost:xxxx/Employee. I expected localhost:xxxx/Employee/Edit/1 but the id argument seems to be missing.

I am using @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers in the _ViewImports.cshtml

What can I try? If you need more information, let me know!

2
Put a break point inside public IActionResult Edit(int id), run in debug, see whether it runs into this method? - Jacky
Since you change the Controller to Employee, it may cause some issue in routing, post the whole EmployeeController.cs would be easier - Jacky

2 Answers

1
votes

I expect your problem is in the Index.cshtml file, where you specify that @employee.id is to be used in the route:

asp-routeid="@employee.id"

Change both of these to:

asp-route-id="@employee.id"

The difference is the - between route and id. See the documentation for more information on how the Form Tag Helper works with route parameters:

Provides the asp-route-<Parameter Name> attribute, where <Parameter Name> is added to the route values.

1
votes

There are so many scenario that we need to go through, so i rather write here , instead of multiple comment:

  1. Put a break point, run debug every single line . See whether it went wrong.

    For this scenario , I suspect it went wrong here:

    if (model == null)
    {
        return RedirectToAction("Index");
    }
    

    Your model might be null, thus it redirect back to main index.

  2. Due to using controller name as "Employee", instead of "Home", compare to tutorialpoint, your routing might broken somewhere. Check your routing file, by default, it should be like this:

    routes.MapRoute(
        name: "default_route",
        template: "{controller}/{action}/{id?}",
        defaults: new { controller = "Home", action = "Index" });
    

    Did you make any change inside here?