You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

无法保存视图返回变量:ASP.NET MVC用户信息跨视图传递失败

我来帮你分析下问题所在,然后给你几个可行的解决方案:

问题根源

你遇到的核心问题是ASP.NET Core控制器是瞬时(Transient)对象——每次HTTP请求都会创建一个全新的PersonalAreaController实例。当你在Login的POST方法里给私有字段User赋值后,执行RedirectToAction会触发一个全新的GET请求到Info方法,这时候新的控制器实例里的User字段是默认的null,自然无法传递数据。


解决方案1:使用TempData传递临时数据

TempData专门用于在请求之间临时存储数据,默认情况下数据会在被读取一次后自动删除,非常适合这种跳转场景。

修改你的控制器代码:

public class PersonalAreaController : Controller {
    private readonly CompanyContext _context;

    public PersonalAreaController(CompanyContext context) {
        _context = context;
    }

    public IActionResult Login() {
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login([Bind("PersonalAccount")] Users user) {
        if (ModelState.IsValid) {
            var foundUser = await _context.Users.FirstOrDefaultAsync(c => c.PersonalAccount == user.PersonalAccount);
            if (foundUser != null) {
                // 将用户对象序列化后存入TempData
                TempData["CurrentUser"] = JsonSerializer.Serialize(foundUser);
            }
            return RedirectToAction(nameof(Info));
        }
        return View();
    }

    public IActionResult Info() {
        if (TempData["CurrentUser"] is string userJson) {
            var user = JsonSerializer.Deserialize<Users>(userJson);
            return View(user);
        }
        // 如果没有用户数据,跳回登录页
        return RedirectToAction(nameof(Login));
    }
}

注意:确保Users类的属性是公共的,这样才能正常被JSON序列化。


解决方案2:使用Session存储用户数据

如果需要在多个请求之间长期保留用户数据(比如用户在个人中心的多个页面跳转),可以使用Session。首先要在项目中配置Session服务:

Program.cs中添加以下配置:

// 注册Session服务
builder.Services.AddSession(options => {
    options.IdleTimeout = TimeSpan.FromMinutes(30); // 设置Session超时时间
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

// 在路由配置后启用Session
app.UseRouting();
app.UseSession(); // 必须放在UseRouting之后,UseAuthorization之前

然后修改控制器代码:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login([Bind("PersonalAccount")] Users user) {
    if (ModelState.IsValid) {
        var foundUser = await _context.Users.FirstOrDefaultAsync(c => c.PersonalAccount == user.PersonalAccount);
        if (foundUser != null) {
            HttpContext.Session.SetString("CurrentUser", JsonSerializer.Serialize(foundUser));
        }
        return RedirectToAction(nameof(Info));
    }
    return View();
}

public IActionResult Info() {
    var userJson = HttpContext.Session.GetString("CurrentUser");
    if (!string.IsNullOrEmpty(userJson)) {
        var user = JsonSerializer.Deserialize<Users>(userJson);
        return View(user);
    }
    return RedirectToAction(nameof(Login));
}

解决方案3:通过路由参数传递用户ID(推荐)

上面两种方法依赖客户端存储(TempData本质基于Cookie),如果用户禁用Cookie会失效。更可靠的方式是跳转时传递用户ID,在Info方法中重新从数据库查询:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login([Bind("PersonalAccount")] Users user) {
    if (ModelState.IsValid) {
        var foundUser = await _context.Users.FirstOrDefaultAsync(c => c.PersonalAccount == user.PersonalAccount);
        if (foundUser != null) {
            // 传递用户ID到Info方法
            return RedirectToAction(nameof(Info), new { id = foundUser.Id });
        }
        // 没找到用户时添加错误提示
        ModelState.AddModelError("", "账号不存在");
    }
    return View();
}

// 修改Info方法接收ID参数并重新查询用户
public async Task<IActionResult> Info(int id) {
    var user = await _context.Users.FindAsync(id);
    if (user == null) {
        return NotFound(); // 或者跳回登录页
    }
    return View(user);
}

这种方式符合RESTful设计原则,不依赖客户端存储,安全性和可靠性更高。

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

火山引擎 最新活动