Ubuntu 22.04下VS Code搭建ASP.NET Core MVC CRUD及排障求助
问题解决与CRUD搭建指南
一、现有问题修复
1. MSSQL扩展「配置文件未创建,请重试」错误
- 关闭VS Code,清理扩展缓存:
rm -rf ~/.vscode/extensions/ms-mssql.mssql-* - 以普通用户身份重新打开VS Code,重新安装MSSQL扩展
- 若仍报错,手动创建扩展配置目录并赋权:
mkdir -p ~/.config/Code/User/globalStorage/ms-mssql.mssql chmod -R 755 ~/.config/Code/User/globalStorage/ms-mssql.mssql
2. startup.css缺失错误
- 若项目中
wwwroot/css/startup.css不存在,直接创建空文件即可,多数模板仅引用该文件但无强制内容要求 - 打开
Views/Shared/_Layout.cshtml,检查样式引用路径是否正确;若不需要该文件,可直接删除对应的<link>标签,替换为Bootstrap等其他样式库的引用
二、完整ASP.NET Core MVC CRUD功能搭建(Ubuntu 22.04)
环境准备
- 安装.NET 6+ SDK:
sudo apt-get update && sudo apt-get install dotnet-sdk-6.0 - 数据库选择(二选一):
- MSSQL:用Docker快速部署
docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=YourStrong@Passw0rd" -p 1433:1433 --name mssql -d mcr.microsoft.com/mssql/server:2022-latest - MySQL:确保本地已安装MySQL服务,或用Docker部署
- MSSQL:用Docker快速部署
步骤1:创建MVC项目
dotnet new mvc -n EmployeeCRUD cd EmployeeCRUD code .
步骤2:配置数据库连接
修改appsettings.json,添加对应数据库的连接字符串:
- MSSQL(Docker):
"ConnectionStrings": { "DefaultConnection": "Server=localhost,1433;Database=EmployeeDB;User Id=sa;Password=YourStrong@Passw0rd;TrustServerCertificate=True;" } - MySQL:
"ConnectionStrings": { "DefaultConnection": "server=localhost;database=EmployeeDB;user=root;password=YourMySQLPassword;" }
步骤3:创建模型与DbContext
- 创建
Models/Employee.cs:using System.ComponentModel.DataAnnotations; namespace EmployeeCRUD.Models; public class Employee { [Key] public int Id { get; set; } [Required] [StringLength(50)] public string Name { get; set; } = string.Empty; [Required] [EmailAddress] public string Email { get; set; } = string.Empty; [StringLength(30)] public string Department { get; set; } = string.Empty; public decimal Salary { get; set; } } - 创建
Data/AppDbContext.cs:using Microsoft.EntityFrameworkCore; using EmployeeCRUD.Models; namespace EmployeeCRUD.Data; public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<Employee> Employees { get; set; } } - 注册DbContext到
Program.cs:- MSSQL:
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); - MySQL:先安装Pomelo包
再修改dotnet add package Pomelo.EntityFrameworkCore.MySqlProgram.cs:builder.Services.AddDbContext<AppDbContext>(options => options.UseMySql(builder.Configuration.GetConnectionString("DefaultConnection"), ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("DefaultConnection"))));
- MSSQL:
步骤4:数据库迁移
先安装EF工具(若未安装):
dotnet tool install --global dotnet-ef
执行迁移命令:
dotnet ef migrations add InitialCreate dotnet ef database update
步骤5:生成CRUD控制器与视图
- 创建
Controllers/EmployeesController.cs
using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using EmployeeCRUD.Data; using EmployeeCRUD.Models; namespace EmployeeCRUD.Controllers; public class EmployeesController : Controller { private readonly AppDbContext _context; public EmployeesController(AppDbContext context) { _context = context; } // GET: Employees public async Task<IActionResult> Index() { return _context.Employees != null ? View(await _context.Employees.ToListAsync()) : Problem("Entity set 'AppDbContext.Employees' is null."); } // GET: Employees/Details/5 public async Task<IActionResult> Details(int? id) { if (id == null || _context.Employees == null) { return NotFound(); } var employee = await _context.Employees .FirstOrDefaultAsync(m => m.Id == id); if (employee == null) { return NotFound(); } return View(employee); } // GET: Employees/Create public IActionResult Create() { return View(); } // POST: Employees/Create [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("Id,Name,Email,Department,Salary")] Employee employee) { if (ModelState.IsValid) { _context.Add(employee); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View(employee); } // GET: Employees/Edit/5 public async Task<IActionResult> Edit(int? id) { if (id == null || _context.Employees == null) { return NotFound(); } var employee = await _context.Employees.FindAsync(id); if (employee == null) { return NotFound(); } return View(employee); } // POST: Employees/Edit/5 [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit(int id, [Bind("Id,Name,Email,Department,Salary")] Employee employee) { if (id != employee.Id) { return NotFound(); } if (ModelState.IsValid) { try { _context.Update(employee); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!EmployeeExists(employee.Id)) { return NotFound(); } else { throw; } } return RedirectToAction(nameof(Index)); } return View(employee); } // GET: Employees/Delete/5 public async Task<IActionResult> Delete(int? id) { if (id == null || _context.Employees == null) { return NotFound(); } var employee = await _context.Employees .FirstOrDefaultAsync(m => m.Id == id); if (employee == null) { return NotFound(); } return View(employee); } // POST: Employees/Delete/5 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<IActionResult> DeleteConfirmed(int id) { if (_context.Employees == null) { return Problem("Entity set 'AppDbContext.Employees' is null."); } var employee = await _context.Employees.FindAsync(id); if (employee != null) { _context.Employees.Remove(employee); } await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } private bool EmployeeExists(int id) { return (_context.Employees?.Any(e => e.Id == id)).GetValueOrDefault(); } }
- 创建
Views/Employees目录,添加以下5个视图:
Index.cshtml
@model IEnumerable<EmployeeCRUD.Models.Employee> @{ ViewData["Title"] = "Employees"; } <h1>Employees</h1> <p> <a asp-action="Create">Create New</a> </p> <table class="table"> <thead> <tr> <th> @Html.DisplayNameFor(model => model.Name) </th> <th> @Html.DisplayNameFor(model => model.Email) </th> <th> @Html.DisplayNameFor(model => model.Department) </th> <th> @Html.DisplayNameFor(model => model.Salary) </th> <th></th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(modelItem => item.Email) </td> <td> @Html.DisplayFor(modelItem => item.Department) </td> <td> @Html.DisplayFor(modelItem => item.Salary) </td> <td> <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> | <a asp-action="Details" asp-route-id="@item.Id">Details</a> | <a asp-action="Delete" asp-route-id="@item.Id">Delete</a> </td> </tr> } </tbody> </table>
Create.cshtml
@model EmployeeCRUD.Models.Employee @{ ViewData["Title"] = "Create"; } <h1>Create</h1> <h4>Employee</h4> <hr /> <div class="row"> <div class="col-md-4"> <form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <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="Email" class="control-label"></label> <input asp-for="Email" class="form-control" /> <span asp-validation-for="Email" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Department" class="control-label"></label> <input asp-for="Department" class="form-control" /> <span asp-validation-for="Department" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Salary" class="control-label"></label> <input asp-for="Salary" class="form-control" /> <span asp-validation-for="Salary" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-action="Index">Back to List</a> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
Edit.cshtml
@model EmployeeCRUD.Models.Employee @{ ViewData["Title"] = "Edit"; } <h1>Edit</h1> <h4>Employee</h4> <hr /> <div class="row"> <div class="col-md-4"> <form asp-action="Edit"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <input type="hidden" asp-for="Id" /> <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="Email" class="control-label"></label> <input asp-for="Email" class="form-control" /> <span asp-validation-for="Email" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Department" class="control-label"></label> <input asp-for="Department" class="form-control" /> <span asp-validation-for="Department" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Salary" class="control-label"></label> <input asp-for="Salary" class="form-control" /> <span asp-validation-for="Salary" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="Save" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-action="Index">Back to List</a> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
Details.cshtml
@model EmployeeCRUD.Models.Employee @{ ViewData["Title"] = "Details"; } <h1>Details</h1> <div> <h4>Employee</h4> <hr /> <dl class="row"> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Name) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Name) </dd> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Email) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Email) </dd> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Department) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Department) </dd> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Salary) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Salary) </dd> </dl> </div> <div> <a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> | <a asp-action="Index">Back to List</a> </div>
Delete.cshtml
@model EmployeeCRUD.Models.Employee @{ ViewData["Title"] = "Delete"; } <h1>Delete</h1> <h3>Are you sure you want to delete this?</h3> <div> <h4>Employee</h4> <hr /> <dl class="row"> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Name) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Name) </dd> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Email) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Email) </dd> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Department) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Department) </dd> <dt class="col-sm-2"> @Html.DisplayNameFor(model => model.Salary) </dt> <dd class="col-sm-10"> @Html.DisplayFor(model => model.Salary) </dd> </dl> <form asp-action="Delete"> <input type="hidden" asp-for="Id" /> <input type="submit" value="Delete" class="btn btn-danger" /> | <a
相关产品推荐
相关产品推荐

