当进入另一个操作方法时,MVC 全局变量重置为 null
MVC Global variables reseting to null when entering another action method
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();
}
}
ShowSongs 视图:
@model List<Vidafo.Models.Song>
@Html.ActionLink("Publish", "Publish")
问题
所以我在控制器的顶部声明了 currentUser。然后我在此处用这一行为它分配一个值 currentUser.UserSongs = uploadedSongs;
这工作正常但是当代码进入 Publish()
时 currentUser.UserSongs
为空。
在分配一个值后,我需要在多个操作方法中访问 currentUser.UserSongs,但它似乎在进入另一个操作时重置为 null。
为此,您可以使用 TempData,即将值存储在 TempData 字典中。这里的一个问题是 MVC 不会在回发期间改变变量的值,即在同一控制器的不同操作期间或为此调用另一个控制器,您可以按照建议使用临时变量 TempData。
对象状态不是跨请求维护的,Web 应用程序不是这样工作的。每次向服务器发送请求时,都会创建控制器对象的 新实例 。所以任何实例级值都是新的。
为了跨请求保留信息,您需要将其保留在某处。对于像用户上下文这样的东西,会话状态是一个常见的选择。您 可能 想将它包装在一个通用的提供程序接口中,以便不将您的控制器耦合到 HTTP 上下文,但其在会话中的核心存储很简单:
HttpContext.Current.Session["someKey"] = someValue;
(您甚至可以在每次请求时从数据库中重新获取。它的性能稍差,但非常简单和健壮。)
尽管如此,不要将 ASP.NET 身份系统排除在外。 ASP.NET 非常擅长为您抽象出很多内容。您已经在此处使用它了:
string userName = User.Identity.Name;
然后您使用该值从数据库中获取用户。您 可以 扩展身份系统以存储满足您需要的自定义用户对象。但这是这个问题之外的更大范围的努力。
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();
}
}
ShowSongs 视图:
@model List<Vidafo.Models.Song>
@Html.ActionLink("Publish", "Publish")
问题
所以我在控制器的顶部声明了 currentUser。然后我在此处用这一行为它分配一个值 currentUser.UserSongs = uploadedSongs;
这工作正常但是当代码进入 Publish()
时 currentUser.UserSongs
为空。
在分配一个值后,我需要在多个操作方法中访问 currentUser.UserSongs,但它似乎在进入另一个操作时重置为 null。
为此,您可以使用 TempData,即将值存储在 TempData 字典中。这里的一个问题是 MVC 不会在回发期间改变变量的值,即在同一控制器的不同操作期间或为此调用另一个控制器,您可以按照建议使用临时变量 TempData。
对象状态不是跨请求维护的,Web 应用程序不是这样工作的。每次向服务器发送请求时,都会创建控制器对象的 新实例 。所以任何实例级值都是新的。
为了跨请求保留信息,您需要将其保留在某处。对于像用户上下文这样的东西,会话状态是一个常见的选择。您 可能 想将它包装在一个通用的提供程序接口中,以便不将您的控制器耦合到 HTTP 上下文,但其在会话中的核心存储很简单:
HttpContext.Current.Session["someKey"] = someValue;
(您甚至可以在每次请求时从数据库中重新获取。它的性能稍差,但非常简单和健壮。)
尽管如此,不要将 ASP.NET 身份系统排除在外。 ASP.NET 非常擅长为您抽象出很多内容。您已经在此处使用它了:
string userName = User.Identity.Name;
然后您使用该值从数据库中获取用户。您 可以 扩展身份系统以存储满足您需要的自定义用户对象。但这是这个问题之外的更大范围的努力。