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

ASP.NET Core结合PostgreSQL实现文件上传表单级联下拉的问题咨询

插入Genre数据报错基本都是外键约束冲突导致:PostgreSQL要求你插入的Genre表FileTypeID字段的值,必须已经在FileType表的主键字段中存在。操作顺序应该是先向FileType表插入所有需要的类型数据,再向Genre表插入对应FileTypeID的分类数据即可解决报错。

级联下拉功能实现步骤

步骤1:调整FileUploadViewModel

public class FileUploadViewModel
{
    // 原有属性保持不变
    public int FileTypeId { get; set; } // 新增:选中的文件类型ID
    public int Genre { get; set; } // 原有枚举类型改为int,对应数据库Genre表主键
    // 其他属性:Name、Author、Description、PublishedOn、Files 保持不变
}

步骤2:调整Controller逻辑

首先修改首页加载动作,预加载FileType下拉选项:

public IActionResult Index()
{
    // 从PostgreSQL查询所有文件类型,转为下拉选项
    ViewBag.FileTypeList = new SelectList(_dbContext.FileTypes.ToList(), "Id", "Name");
    return View();
}

新增获取分类列表的接口,用于前端动态加载:

[HttpGet]
public IActionResult GetGenresByFileTypeId(int fileTypeId)
{
    var genres = _dbContext.Genres
        .Where(g => g.FileTypeId == fileTypeId)
        .Select(g => new { id = g.Id, name = g.Name })
        .ToList();
    return Json(genres);
}

步骤3:修改Razor视图表单

在原有Genre下拉框前面新增FileType下拉框,替换原有Genre下拉的枚举绑定:

@model FileUploadViewModel
@{    ViewData["Title"] = "Index";}

<h4>Start Uploading Files Here</h4>
<hr />
@if (ViewBag.Message != null)
{
    <div class="alert alert-success alert-dismissible" style="margin-top:20px">
        @ViewBag.Message
    </div>
}
<form enctype="multipart/form-data" asp-controller="files" asp-action="UploadToFileSystem" method="post">
    <div class="form-group row">
        <label asp-for="Name" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <input asp-for="Name" class="form-control" placeholder="name" />
            <span asp-validation-for="Name" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group row">
        <label asp-for="Author" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <input asp-for="Author" class="form-control" placeholder="Author" />
            <span asp-validation-for="Author" class="text-danger"></span>
        </div>
    </div>
    <!-- 新增FileType下拉框 -->
    <div class="form-group row">
        <label asp-for="FileTypeId" class="col-sm-2 col-form-label"> 文件类型 </label>
        <div class="col-sm-10">
            <select asp-for="FileTypeId" class="custom-select mr-sm-2" asp-items="ViewBag.FileTypeList" id="fileTypeSelect">
                <option value="">请选择文件类型</option>
            </select>
        </div>
    </div>
    <!-- 修改原有Genre下拉框,移除枚举绑定 -->
    <div class="form-group row">
        <label asp-for="Genre" class="col-sm-2 col-form-label"> 分类 </label>
        <div class="col-sm-10">
            <select asp-for="Genre" class="custom-select mr-sm-2" id="genreSelect">
                <option value="">请先选择文件类型</option>
            </select>
            <span asp-validation-for="Genre" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group row">
        <label asp-for="Description" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <input asp-for="Description" class="form-control" placeholder="Description" />
            <span asp-validation-for="Description" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group row " >
        <label asp-for="PublishedOn" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <input type="date" asp-for="PublishedOn" class="form-control" placeholder="Publishing Date" />
            <span asp-validation-for="PublishedOn" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group row">
        <label asp-for="Files" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <div class="custom-file">
                <input asp-for="Files" multiple type="file" class="form-control custom-file-input" placeholder="file" />
                <label class="custom-file-label">Chose File...</label>
                <span asp-validation-for="Files" class="text-danger"></span>
            </div>
        </div>
    </div>
    <button class="btn btn-success" type="submit" asp-action="UploadToFileSystem" asp-controller="Files">Upload</button>
</form>

步骤4:新增级联交互脚本

在原有Scripts块中添加FileType下拉的监听逻辑:

@section Scripts{ 
<script>
    $(document).ready(function () {
        // 原有文件选择展示逻辑保持不变
        $('.custom-file-input').on("change", function () {
            var fileLabel = $(this).next('.custom-file-label');
            var files = $(this)[0].files;
            if (files.length > 1) {
                fileLabel.html(files.length + 'files selected');
            }
            else if (files.length == 1) {
                fileLabel.html(files[0].name);
            }
        });

        // 新增级联下拉逻辑
        $('#fileTypeSelect').on('change', function () {
            const fileTypeId = $(this).val();
            const genreSelect = $('#genreSelect');
            // 清空原有选项
            genreSelect.empty();
            
            if (!fileTypeId) {
                genreSelect.append('<option value="">请先选择文件类型</option>');
                return;
            }

            // 请求后端获取对应分类
            $.get('/Files/GetGenresByFileTypeId?fileTypeId=' + fileTypeId, function (data) {
                genreSelect.append('<option value="">请选择分类</option>');
                // 渲染返回的分类选项
                data.forEach(genre => {
                    genreSelect.append(`<option value="${genre.id}">${genre.name}</option>`);
                });
            });
        });
    });
</script>
}
备选方案(适合数据量小的场景)

如果FileType和Genre总数据量很小,可以直接在页面渲染时把所有Genre数据按FileTypeID分组序列化到前端,选择时直接本地过滤,无需发AJAX请求,性能更好:

  1. 在Controller的Index动作中添加:
ViewBag.AllGenres = System.Text.Json.JsonSerializer.Serialize(_dbContext.Genres.ToList());
  1. 前端直接读取ViewBag.AllGenres做本地过滤即可,无需调用后端接口。

内容的提问来源于stack exchange,提问作者DevGary

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:39:04