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

ASP.NET MVC中SQL数据编辑删除的QueryString与请求问题

我来帮你一步步搞定这两个问题,先从编辑功能的参数传递问题说起,再解决删除操作的POST请求需求:


问题1:修复EditUser的参数传递与视图数据填充

你遇到的Request.QueryString["Username"]报错,本质是在ASP.NET MVC中不需要这么复杂的写法——框架已经帮我们实现了自动参数绑定,直接在控制器方法里声明参数即可接收QueryString的值。

步骤1:修改HttpGet的EditUser方法,获取用户名并填充模型

把HomeController里的HttpGet EditUser改成这样,让它自动接收URL里的Username参数,同时从数据库获取用户当前角色,填充到模型中传给视图:

[HttpGet]
public IActionResult EditUser(string username)
{
    // 先从数据库获取用户当前的角色,用来在视图中默认选中
    UsersDAL ud = new UsersDAL();
    var existingUser = ud.GetUserByUsername(username);
    
    if (existingUser == null)
    {
        return NotFound(); // 如果用户不存在,返回404页面
    }
    return View(existingUser);
}

步骤2:在UsersDAL中新增查询用户的方法

需要添加一个方法来获取指定用户名的用户信息(主要是当前角色):

public Users GetUserByUsername(string username)
{
    string connectionstring = "MY_CONNECTION_STRING";
    // 使用SQL Server系统视图查询用户所属角色
    string sql = @"SELECT dp.name AS Username, rp.name AS Role
                   FROM sys.database_principals dp
                   JOIN sys.database_role_members drm ON dp.principal_id = drm.member_principal_id
                   JOIN sys.database_principals rp ON drm.role_principal_id = rp.principal_id
                   WHERE dp.name = @Username";
    
    using (SqlConnection conn = new SqlConnection(connectionstring))
    {
        SqlCommand cmd = new SqlCommand(sql, conn);
        cmd.Parameters.AddWithValue("@Username", username);
        conn.Open();
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            if (reader.Read())
            {
                return new Users
                {
                    Username = reader["Username"].ToString(),
                    Role = reader["Role"].ToString()
                };
            }
            return null;
        }
    }
}

步骤3:修复EditUser视图的用户名输入框

你当前的用户名输入框手动设置了value="",而且disabled属性不影响模型绑定,直接用asp-for就能自动填充值:

<input asp-for="Username" type="text" class="form-control" id="username" name="Username" required disabled />

步骤4:修正Edit方法的逻辑(原逻辑无效)

你之前的Edit方法是先从同一个角色移除再添加,完全没有作用。正确逻辑是先从旧角色移除用户,再添加到新角色:

public void Edit(Users u, string oldRole)
{
    string connectionstring = "MY_CONNECTION_STRING";
    string sqlRemove = "ALTER ROLE @OldRole DROP MEMBER @Username";
    string sqlAdd = "ALTER ROLE @NewRole ADD MEMBER @Username";
    
    using (SqlConnection conn = new SqlConnection(connectionstring))
    {
        conn.Open();
        using (var transaction = conn.BeginTransaction())
        {
            try
            {
                // 移除旧角色
                SqlCommand cmdRemove = new SqlCommand(sqlRemove, conn, transaction);
                cmdRemove.Parameters.AddWithValue("@OldRole", oldRole);
                cmdRemove.Parameters.AddWithValue("@Username", u.Username);
                cmdRemove.ExecuteNonQuery();
                
                // 添加新角色
                SqlCommand cmdAdd = new SqlCommand(sqlAdd, conn, transaction);
                cmdAdd.Parameters.AddWithValue("@NewRole", u.Role);
                cmdAdd.Parameters.AddWithValue("@Username", u.Username);
                cmdAdd.ExecuteNonQuery();
                
                transaction.Commit();
            }
            catch
            {
                transaction.Rollback();
                throw; // 抛出异常让控制器处理
            }
        }
    }
}

然后修改HttpPost EditUser方法,传递旧角色参数:

[HttpPost]
public IActionResult EditUser(Users u)
{
    if (!ModelState.IsValid)
    {
        // 验证失败时恢复用户原角色
        UsersDAL ud = new UsersDAL();
        var existingUser = ud.GetUserByUsername(u.Username);
        u.Role = existingUser.Role;
        return View(u);
    }
    UsersDAL ud = new UsersDAL();
    var existingUser = ud.GetUserByUsername(u.Username);
    ud.Edit(u, existingUser.Role);
    return RedirectToAction("ShowUsers");
}

问题2:实现DeleteUser的POST请求(不跳转视图)

你当前用@Html.ActionLink生成的是GET请求,不符合REST规范(删除操作应该用POST/DELETE),这里提供两种实现方式:

方式1:表单同步提交(删除后跳转回列表)

把ShowUsers视图中的Delete链接改成表单,提交POST请求:

<td class="actions">
    <form asp-controller="Home" asp-action="DeleteUser" method="post" onsubmit="return confirm('确定要删除该用户吗?');">
        <input type="hidden" name="Username" value="@item.Username" />
        <button type="submit" class="btn btn-link p-0">Delete</button>
    </form>
</td>

然后修改控制器的DeleteUser方法,直接接收用户名参数:

[HttpPost]
public IActionResult DeleteUser(string username)
{
    if (string.IsNullOrEmpty(username))
    {
        return BadRequest();
    }
    UsersDAL ud = new UsersDAL();
    ud.Delete(new Users { Username = username });
    return RedirectToAction("ShowUsers");
}

方式2:AJAX异步删除(无页面跳转,实时移除行)

如果想要完全不跳转页面,用AJAX实现异步删除:
先修改ShowUsers视图中的Delete按钮:

<td class="actions">
    <button class="btn btn-link p-0 delete-btn" data-username="@item.Username">Delete</button>
</td>

然后在页面底部添加AJAX脚本(记得在视图顶部加@Html.AntiForgeryToken()来防CSRF):

@Html.AntiForgeryToken()
<script>
document.querySelectorAll('.delete-btn').forEach(btn => {
    btn.addEventListener('click', async function() {
        if (!confirm('确定要删除该用户吗?')) return;
        
        const username = this.dataset.username;
        const token = document.querySelector('input[name="__RequestVerificationToken"]').value;
        
        const response = await fetch('/Home/DeleteUser', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'RequestVerificationToken': token
            },
            body: `Username=${encodeURIComponent(username)}`
        });
        
        if (response.ok) {
            // 删除成功后移除当前行
            this.closest('tr').remove();
        } else {
            alert('删除失败,请重试');
        }
    });
});
</script>

最后修改控制器的DeleteUser方法返回JSON:

[HttpPost]
public IActionResult DeleteUser(string username)
{
    if (string.IsNullOrEmpty(username))
    {
        return Json(new { success = false, message = "用户名不能为空" });
    }
    try
    {
        UsersDAL ud = new UsersDAL();
        ud.Delete(new Users { Username = username });
        return Json(new { success = true });
    }
    catch (Exception ex)
    {
        return Json(new { success = false, message = ex.Message });
    }
}

额外注意事项

  • 不要用String.Format拼接SQL,这会导致SQL注入风险,全部改用参数化查询(就像上面的示例代码那样)。
  • 数据库连接字符串建议放在配置文件中(appsettings.json或Web.config),不要硬编码。
  • 操作数据库时尽量用using语句,自动释放连接资源。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:53:24