I have created a basic MVC solution using the entity framework. But when I put dummy data in the create form and click create, nothing happens. No new entries are made into the DB and the page does not return to the controller index. Most code is scaffolded by Visual Studio so I'm not sure what is wrong.
The controller should handle a create action, taking data from the form on the create page, put it in the right database and return to the index of the controller. Instead, the page remains on the create form with my dummy data still in the fields. No entryis ever inputted in the database.
**My create view: **
@model DCServer.Models.Driver
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Driver</h4>
<hr />
<div >
<div >
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" ></div>
<div >
<label asp-for="scooberId" ></label>
<input asp-for="scooberId" />
<span asp-validation-for="scooberId" ></span>
</div>
<div >
<label asp-for="driverName" ></label>
<input asp-for="driverName" />
<span asp-validation-for="driverName" ></span>
</div>
<div >
<label asp-for="driverScore" ></label>
<input asp-for="driverScore" />
<span asp-validation-for="driverScore" ></span>
</div>
<div >
<label asp-for="employedTime" ></label>
<input asp-for="employedTime" />
<span asp-validation-for="employedTime" ></span>
</div>
<div >
<label asp-for="amtApproaches" ></label>
<input asp-for="amtApproaches" />
<span asp-validation-for="amtApproaches" ></span>
</div>
<div >
<label asp-for="amtEvaluated" ></label>
<input asp-for="amtEvaluated" />
<span asp-validation-for="amtEvaluated" ></span>
</div>
<div >
<label asp-for="lastEvaluated" ></label>
<input asp-for="lastEvaluated" />
<span asp-validation-for="lastEvaluated" ></span>
</div>
<div >
<input type="submit" value="Create" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
**My model: **
using MessagePack;
using System;
namespace DCServer.Models
{
public class Driver
{
public int Id { get; set; }
public int scooberId { get; set; }
public string driverName { get; set; }
public string driverScore { get; set; }
public float employedTime { get; set; }
public string amtApproaches { get; set; }
public virtual ICollection<Approach> Approaches { get; set; }
public int amtEvaluated { get; set; }
public float lastEvaluated { get; set; }
public virtual ICollection<Evaluation> Evaluations { get; set; }
public Driver()
{
}
}
}
**My controller **
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using DCServer.Data;
using DCServer.Models;
namespace DCServer.Controllers
{
public class DriversController : Controller
{
private readonly ApplicationDbContext _context;
public DriversController(ApplicationDbContext context)
{
_context = context;
}
// GET: Drivers
public async Task<IActionResult> Index()
{
return View(await _context.Driver.ToListAsync());
}
// GET: Drivers/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null || _context.Driver == null)
{
return NotFound();
}
var driver = await _context.Driver
.FirstOrDefaultAsync(m => m.Id == id);
if (driver == null)
{
return NotFound();
}
return View(driver);
}
// GET: Drivers/Create
public IActionResult Create()
{
return View();
}
// POST: Drivers/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,scooberId,driverName,driverScore,employedTime,amtApproaches,amtEvaluated,lastEvaluated")] Driver driver)
{
try
{
if (ModelState.IsValid)
{
_context.Add(driver);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
}
catch (DataException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
return View(driver);
}
// GET: Drivers/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null || _context.Driver == null)
{
return NotFound();
}
var driver = await _context.Driver.FindAsync(id);
if (driver == null)
{
return NotFound();
}
return View(driver);
}
// POST: Drivers/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,scooberId,driverName,driverScore,employedTime,amtApproaches,amtEvaluated,lastEvaluated")] Driver driver)
{
if (id != driver.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(driver);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!DriverExists(driver.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(driver);
}
// GET: Drivers/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null || _context.Driver == null)
{
return NotFound();
}
var driver = await _context.Driver
.FirstOrDefaultAsync(m => m.Id == id);
if (driver == null)
{
return NotFound();
}
return View(driver);
}
// POST: Drivers/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
if (_context.Driver == null)
{
return Problem("Entity set 'ApplicationDbContext.Driver' is null.");
}
var driver = await _context.Driver.FindAsync(id);
if (driver != null)
{
_context.Driver.Remove(driver);
}
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool DriverExists(int id)
{
return _context.Driver.Any(e => e.Id == id);
}
}
}
CodePudding user response:
It appears that the two ICollection interfaces in the model are returning invalid as they are empty.
I'm afraid you may use .NET 6
/.NET 7
. From .NET 6
the non-nullable property must be required, otherwise the ModelState will be invalid.
To achieve your requirement, the first way is you can remove <Nullable>enable</Nullable>
from your project file(double-click the project name or right-click the project to choose Edit Project File).
The second way, you can initialize the model like below:
public class Driver
{
public int Id { get; set; }
//other properties...
public virtual ICollection<Approach> Approaches { get; set; } = new List<Approach>();
public int amtEvaluated { get; set; }
public float lastEvaluated { get; set; }
public virtual ICollection<Evaluation> Evaluations { get; set; } = new List<Evaluation>();
public Driver()
{
}
}
The third way, you can add ?
to allow nullable:
public class Driver
{
public int Id { get; set; }
//other properties.....
public virtual ICollection<Approach>? Approaches { get; set; }
public int amtEvaluated { get; set; }
public float lastEvaluated { get; set; }
public virtual ICollection<Evaluation>? Evaluations { get; set; }
public Driver()
{
}
}