进入另一个操作方法时MVC全局变量重置为null

问题描述 投票:0回答:3
public class MusicController : Controller
{
    User currentUser;

    public PartialViewResult UploadMusic()
    {

        return PartialView("_UploadMusic");
    }

    [HttpPost]
    public ActionResult UploadMusic(List<HttpPostedFileBase> files)
    {
        EntityDBContext db = new EntityDBContext();
        List<Song> uploadedSongs = new List<Song>();

        foreach (var file in files)
        {
            if (file != null)
            {
                string songName = Path.GetFileName(file.FileName);
                byte[] songAsBytes = new byte[file.ContentLength];

                using (BinaryReader br = new BinaryReader(file.InputStream))
                {
                    songAsBytes = br.ReadBytes(file.ContentLength);
                }

                //Save new record in database
                Song song = new Song
                {
                    SongName = songName,
                    SongBytes = songAsBytes
                };

                uploadedSongs.Add(song);
            }
        }

        string userName = User.Identity.Name;
        currentUser = db.Users.Where(x => x.Username == userName).First();
        currentUser.UserSongs = uploadedSongs;

        return ShowSongs(currentUser.UserSongs);
    }

    public ActionResult ShowSongs(List<Song> UserSongs)
    {
        return View("ShowSongs", UserSongs);
    }

    public ActionResult Publish()
    {
        EntityDBContext db = new EntityDBContext();

        foreach (var song in currentUser.UserSongs)
        {
            if (song != null)
            {
                db.Songs.Add(song);
                db.SaveChanges();
            }
        }
        return View();
    }
}

显示歌曲视图:

@model List<Vidafo.Models.Song>

@Html.ActionLink("Publish", "Publish")

问题

所以我在控制器的顶部声明了 currentUser 。然后我在这里用这一行为其分配一个值

currentUser.UserSongs = uploadedSongs;
这工作正常,但是当代码进入
Publish()
currentUser.UserSongs
时为空。

在分配一个值后,我需要在多个操作方法中访问 currentUser.UserSongs ,但当它进入另一个操作时,它似乎会重置为 null 。

c# null global
3个回答
2
投票

对象状态不会跨请求维护,这不是 Web 应用程序的工作方式。每次向服务器发送请求时,都会创建控制器对象的“新实例”。因此任何实例级值都是新的。 为了跨请求保存信息,您需要将其保存在某个地方。对于用户上下文之类的东西,会话状态是常见的选择。您可能希望将其包装在公共提供程序接口中,以便不将控制器耦合到 HTTP 上下文,但其核心存储在会话中很简单:

HttpContext.Current.Session["someKey"] = someValue;

(您甚至可以针对每个请求从数据库中重新获取。它的性能稍差,但非常简单且健壮。)

不过,不要指望 ASP.NET 身份系统。 ASP.NET 非常擅长为您抽象出很多这样的内容。您已经在这里使用它了:

string userName = User.Identity.Name;

然后使用该值从数据库中获取用户。您

可以

扩展身份系统来存储适合您需求的自定义用户对象。但这是这个问题之外更大范围的努力。
    

为此,您可以使用 TempData,即将值存储在 TempData 字典中。这里的一个问题是 MVC 在回发期间不会改变变量的值,即在同一控制器的不同操作期间或为此调用另一个控制器时,您可以按照建议使用临时变量 TempData。


1
投票
简而言之,你可以将变量定义为

static

,但要小心。

0
投票
每次有请求时都会实例化控制器类。但是,如果您在类中放置一个静态字段,那么该静态字段将在所有控制器实例之间共享,因此您将出现非常奇怪的行为,尤其是当该静态字段包含用户名时。这绝对是你应该避免的事情。

static User currentUser;

© www.soinside.com 2019 - 2024. All rights reserved.