You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

环境准备

  1. 安装.NET 6+ SDK:
    sudo apt-get update && sudo apt-get install dotnet-sdk-6.0
    
  2. 数据库选择(二选一):
    • 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部署

步骤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

  1. 创建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; }
    }
    
  2. 创建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; }
    }
    
  3. 注册DbContext到Program.cs:
    • MSSQL:
      builder.Services.AddDbContext<AppDbContext>(options =>
          options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
      
    • MySQL:先安装Pomelo包
      dotnet add package Pomelo.EntityFrameworkCore.MySql
      
      再修改Program.cs:
      builder.Services.AddDbContext<AppDbContext>(options =>
          options.UseMySql(builder.Configuration.GetConnectionString("DefaultConnection"), 
              ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("DefaultConnection"))));
      

步骤4:数据库迁移

先安装EF工具(若未安装):

dotnet tool install --global dotnet-ef

执行迁移命令:

dotnet ef migrations add InitialCreate
dotnet ef database update

步骤5:生成CRUD控制器与视图

  1. 创建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();
    }
}
  1. 创建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
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:34:12