我正在开发一个 ASP.NET MVC 应用程序,我在其中创建了一个包含所有必要的 MVC 组件(模型、视图、控制器)的产品页面。但是,当用户填写产品页面上的表单并提交时,应用程序不会将新产品保存到数据库中。相反,它会重定向到一个不存在的页面。
我想要实现的目标
在产品页面,用户可以填写表单来创建新产品。目标是在提交表单时将产品详细信息保存到数据库中。
实际发生了什么
应用程序不会将新产品保存到数据库,而是在提交表单后重定向到不存在的页面。
预期行为
提交表单后,新产品应保存到数据库中,并且用户应重定向到确认页面或产品列表。
我尝试过的:
模型类:
namespace My_Name_Space.Models
{
public class Product
{
[Required]
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
[Range(0, double.MaxValue, ErrorMessage = "Price must be a positive number.")]
public string Price { get; set; }
[Required]
public string ImageUrl { get; set; }
[Required]
[Range(0, int.MaxValue, ErrorMessage = "Stock must be a non-negative integer.")]
public int Stock { get; set; }
}
}
控制器:
public async Task<IActionResult> ManageProducts()
{
var products = await _context.Products.ToListAsync();
return View(products);
}
/* Manage Product Create GET*/
public IActionResult CreateProducts()
{
return View();
}
/* add actions to create, edit, and delete products*/
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateProducts(Product product)
{
if (ModelState.IsValid)
{
_context.Add(product);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(ManageProducts));
}
else
{
// Inspect the ModelState to understand why it's not valid //
var errors = ModelState.Values.SelectMany(v => v.Errors);
}
return View(product);
}
查看:
<form asp-action="CreateProduct" asp-controller="Admin" method="post">
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<textarea asp-for="Description" class="form-control"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Stock" class="control-label"></label>
<input asp-for="Stock" class="form-control" />
<span asp-validation-for="Stock" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ImageUrl" class="control-label"></label>
<input asp-for="ImageUrl" class="form-control" />
<span asp-validation-for="ImageUrl" class="text-danger"></span>
</div>
<div class="form-group">
<button type="submit" value="Create" class="btn btn-primary">Create</button>
</div>
</form>
<script>
<script src="~/js/create-product.js"></script>
</script>
site.js
脚本:
document.addEventListener("DOMContentLoaded", function () {
// Image URL preview functionality
const imageUrlInput = document.querySelector('input[name="ImageUrl"]');
const imagePreview = document.createElement('img');
imagePreview.id = 'imagePreview';
imageUrlInput.parentNode.appendChild(imagePreview);
imageUrlInput.addEventListener("input", function () {
const url = imageUrlInput.value;
if (url) {
imagePreview.src = url;
imagePreview.style.display = 'block';
} else {
imagePreview.style.display = 'none';
}
});
});
在
Program.cs
中映射控制器:
//other essential services
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapControllerRoute(
name:"admin",
pattern: "{controller=Admin}/{action=ManageProducts}/{id?}");
app.MapControllerRoute(
name: "login",
pattern: "Login",
defaults: new { controller = "Login", action = "Index" });
文件结构:
ProjectName/
│
├── Controllers/
│ └── ProductController.cs
│
├── Models/
│ └── Product.cs
│
├── Views/
│ └── Admin/
│ ├── CreateProduct.cshtml
│ └── Index.cshtml
│
├── wwwroot/
| ├── css/
| | └── site.css
│ └── js/
| └── create-product.js
│
│
├── appsettings.json
└── program.cs
深深感谢每一个帮助,请原谅我的菜鸟代码,如果我做错了什么,请告诉我!
根据您提供的代码和相关项目结构,您的预期行为可以通过
Admincontroller
实现。
应用程序不会将新产品保存到数据库中。 相反,它会重定向到一个不存在的页面。
问题的原因是,在你的表单中,提交的对应方法是
Admincontroller/CreateProduct
,但是在你的项目结构中,你的Controllers中定义的控制器名称是Productcontroller
,所以表单提交后无法正确匹配方法已提交。您可以将 Productcontroller
更改为 Admincontroller
。
其次,在控制器方法中,View方法的默认行为
return View();
是返回一个与调用它的action方法同名的视图,因此方法名称需要与视图名称相对应.
例如:如果控制器中的方法名称是
CreateProducts
,那么对应的视图名称也应该是CreateProducts
,而不是CreateProduct
。并且表单提交对应的方法应该是Admincontroller/CreateProducts
而不是Admincontroller/CreateProduct
。否则,路由将无法正确匹配方法。
并且在你的路由配置中,只为控制器配置了默认的操作方法,即 ManageProducts。如果您有更多自定义路由配置,可以参考此文档进行配置:https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-8.0.
用户应该被重定向到确认页面或列表 产品。
如果您想重定向到像
ManageProducts
这样的单独页面,那么您需要在Views/Admin
文件夹中创建相应的页面ManageProducts。这是一个完整的示例供您参考:
控制器:
public class AdminController : Controller
{
private readonly ApplicationDbContext _dbContext;
public AdminController(ILogger<HomeController> logger, ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public IActionResult Index()
{
return View();
}
public async Task<IActionResult> ManageProducts()
{
var products = await _dbContext.Products.ToListAsync();
return View(products);
}
/* Manage Product Create GET*/
public IActionResult CreateProducts()
{
return View();
}
/* add actions to create, edit, and delete products*/
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateProducts(Product product)
{
if (ModelState.IsValid)
{
_dbContext.Products.Add(product);
await _dbContext.SaveChangesAsync();
return RedirectToAction("ManageProducts");
}
return View(product);
}
}
视图/管理/创建产品:
@model Product
<form asp-action="CreateProducts" asp-controller="Admin" method="post">
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<textarea asp-for="Description" class="form-control"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Stock" class="control-label"></label>
<input asp-for="Stock" class="form-control" />
<span asp-validation-for="Stock" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ImageUrl" class="control-label"></label>
<input asp-for="ImageUrl" class="form-control" />
<span asp-validation-for="ImageUrl" class="text-danger"></span>
</div>
<div class="form-group">
<button type="submit" value="Create" class="btn btn-primary">Create</button>
</div>
</form>
查看/管理/管理产品:
@model IEnumerable<Product>
@{
ViewData["Title"] = "Manage Products";
}
<h2>Manage Products</h2>
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Price</th>
<th>Stock</th>
<th>Image</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach (var product in Model)
{
<tr>
<td>@product.Name</td>
<td>@product.Description</td>
<td>@product.Price</td>
<td>@product.Stock</td>
<td>
<img src="@product.ImageUrl" alt="@product.Name" style="width: 100px; height: auto;" />
</td>
<td>
<a asp-action="EditProduct" asp-route-id="@product.Id" class="btn btn-warning">Edit</a>
<a asp-action="DeleteProduct" asp-route-id="@product.Id" class="btn btn-danger">Delete</a>
</td>
</tr>
}
</tbody>
</table>