ASP.NET MVC 用户 ID 与其他表的链接

Posted

技术标签:

【中文标题】ASP.NET MVC 用户 ID 与其他表的链接【英文标题】:ASP.NET MVC User ID Link with other Tables 【发布时间】:2022-01-16 05:54:28 【问题描述】:

我正在开发用于存储用户财务数据的数据输入系统。每个用户将在表格中分别输入他的收入和费用。 表格设计如下:

主键:Rev/Exp ID 外键:组织 ID

这是我的模型的示例:

public class Revenue

    [Key]
    public int RevenueId  get; set; 
    public int Year  get; set; 
    public double Source1  get; set;  = 0;
    public double Source2  get; set;  = 0;
    public double Source3  get; set;  = 0;
    public double Source4  get; set;  = 0;

    // Foreign Key Relationship
    public string OrganizationId get; set; 
    public virtual Organization Organization get; set; 


public class Organization

    public virtual ICollection<Revenue> Revenues  get; set; 
    public virtual ICollection<Expense> Expenses  get; set; 

这是 DBContext:

public class AppDbContext : IdentityDbContext

    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    
    

    // Create tables in DB
    public DbSet<Organization > Organization  get; set; 
    public DbSet<Revenue> Revenue  get; set; 
    public DbSet<Expense> Expense  get; set; 

这是控制器中的创建操作:

    // GET: Revenue/Create
    public IActionResult Create()
    
        return View();
    

    // POST: Revenue/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("RevenueId,Year,Source1,Source2,...,OrganizationId")] Revenue revenue)
    
        if (ModelState.IsValid)
        
            _context.Add(revenue);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        
        ViewData["OrganizationId"] = new SelectList(_context.OrganizationId, "Id", "Id", revenue.OrganizationId);
        return View(revenue);
    

最后,创建视图:

@using Microsoft.AspNetCore.Identity

@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
    @
        ViewData["Title"] = "Create";
    
    
    <h1>Create</h1>
    
    <h4>Revenue</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="Year" class="control-label"></label>
                    <input asp-for="Year" class="form-control" />
                    <span asp-validation-for="Year" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Source1" class="control-label"></label>
                    <input asp-for="Source1" class="form-control" />
                    <span asp-validation-for="Source1" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Source2" class="control-label"></label>
                    <input asp-for="Source2" class="form-control" />
                    <span asp-validation-for="Source2" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Source3" class="control-label"></label>
                    <input asp-for="Source3" class="form-control" />
                    <span asp-validation-for="Source3" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Source4" class="control-label"></label>
                    <input asp-for="Source4" class="form-control" />
                    <span asp-validation-for="Source4" class="text-danger"></span>
                </div>
            <div class="form-group">
                <label asp-for="OrganizationId" class="control-label"></label>
                <input asp-for="OrganizationId" class="form-control" value="@UserManager.GetUserId(User)"/>
                <span asp-validation-for="OrganizationId" class="text-danger"></span>
            </div>
                </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");
    

因此,经过大量搜索后,我能够使用 UserManager 捕获用户 ID 并将其分配给隐藏字段,然后将其与表单一起发送。但是,这不起作用,表单没有提交,也没有显示任何错误消息。

这是将用户 ID 捕获为外键的正确方法以及如何修复 Create Action 吗?

【问题讨论】:

【参考方案1】:

您并没有真正指定任何有关您的身份验证的内容。如果您使用的是典型的 ASP.Net 身份验证,您可能可以使用 User.Identity.Name,如下所示:

        if (ModelState.IsValid)
        
            revenue.UserId = User.Identity.Name
            _context.Add(revenue);
            ...

【讨论】:

我正在使用 ASP.NET 标识。但是如何将用户与其转速和费用联系起来。因为这样一旦我输入了一条收入记录,即使我已经登录,用户ID列也是NULL,所以我假设我需要在Create Action中进行修改。 此代码在创建操作中。就在将您的收入对象变量添加到上下文之前 - 我刚刚意识到可能需要:_context.Revenue.Add(revenue) - 您将收入实例的 UserId 属性设置为 User.Identity.Value。 我在问题中做了一点修改。我通过仅添加其 ID 将是 FK 的组织对象更改了收入模型,这很好并反映在 SQL Server 上。但是,创建操作似乎有问题,因为表单没有提交并且您提到的方式不起作用,因为模型内部没有 ID 定义。【参考方案2】:

从 .NET 6 开始,为了将模型中的属性分配为 Nullable ?应加在属性名后,否则为必填项。

问题是传递了 UserId 但 User 对象为空(这应该是因为它只是一个引用)。

所以模型应该是:

public class Revenue

    [Key]
    public int RevenueId  get; set; 
    public int Year  get; set; 
    public double Source1  get; set;  = 0;
    public double Source2  get; set;  = 0;
    public double Source3  get; set;  = 0;
    public double Source4  get; set;  = 0;

    // Foreign Key Relationship
    public string OrganizationId get; set; 
    public Organization? Organization get; set; 

通过在我们从 UserManager 获得的隐藏字段中传递用户 ID,视图将保持原样。

【讨论】:

以上是关于ASP.NET MVC 用户 ID 与其他表的链接的主要内容,如果未能解决你的问题,请参考以下文章

如何将 ID 属性添加到 asp.net MVC 链接元素

使用多个数据库表的 ASP.NET MVC 模型

ASP.net MVC 自定义声明

ASP.NET MVC & C#:将视图模型传递给控制器

ASP.NET MVC,每次用户单击链接时都会增加模型数据中的值

从返回多个实际表的复杂存储过程中检索 asp.net MVC 中的数据