英文:
Database context dependency injection is not working for a page's model
问题
I read somewhere in the ASP.NET Core documentation that I don't need to worry about how an instance of my database context will be passed to other controller and model classes as dependency injection will automatically do that for me. I declared a Database Context property in the Page's model class and then required an instance of the Database Context in the constructor of the model.
However, when I try to access the Database Context object from the Razor page associated with the model then I get an error that my Database Context is not set to an instance of an object.
The controllers do not throw this error however despite implementing the same declared database context object as property and requiring it in the constructor.
Why is my database context null when I try to access it from the Model property of the Razor page and why is it not null when I access it from the controller?
// This property is accessed from the route
var id = Model.Id;
// Use the id to get all the information about this question
var title = Model.dbctx.Posts.FirstOrDefault(x => x.Id == id).Title;
// The dbctx reference above is returning null
The code above is at the top of the Razor page.
Here is how the model for that Razor page looks like:
public class QuestionViewModel:PageModel
{
// Get the id from the route
[FromRoute]
public int Id { get; set; }
// The database context property
public Dbctx dbctx { get; set; }
// Require an object in the constructor
public QuestionViewModel(Dbctx ctx)
{
dbctx = ctx;
}
}
I use the same logic as the above in my controllers. The only difference is that I use private fields on my controllers and then pass the Dbctx
reference to them via the constructors of the respective controllers.
How can I resolve this?
Update:
I do not know if it's the query that is returning null, but I redirect to this page after a new post object has been posted to the database. I then call databaseContext.SaveChanges() to make sure that the insert query was a success. I then grab the id of the last question that was inserted into the database and then redirect to the QuestionView page as per the logic in this controller.
public IActionResult HandleNewPost(string Title, string Body, string Tags) {
// Split the tags based on the space
var tags = Tags.Split(' ');
var tagList = new List<Tag>();
tags.ToList().ForEach(tag => tagList.Add(new Tag(tag)));
// Get the time the post was authored
var creationTime = DateTime.Now;
var postedBy = HttpContext.Session.GetString("email");
var post = new Post {
Title = Title,
Body = Body,
PostedBy = postedBy,
Tags = tagList,
Upvotes = 0,
Downvotes = 0
};
// Post the object to the database
_dbctx.Posts.Add(post);
_dbctx.SaveChanges();
// Get the id of the last post and redirect to the QuestionView page
if(_dbctx.Posts.OrderBy(x=>x.Id).LastOrDefault() != null) {
var id = _dbctx.Posts.OrderBy(x => x.Id).LastOrDefault().Id;
return RedirectToPage("/QuestionView", new []{id});
}
else {
// Some custom code
}
}
It is really weird that the error message starts with a different solution name. The name of my current solution is InputHandling, and there is another solution though in the repositories called ASPLearner. The QuestionView page is in the Page folder of my current solution, but the error stack begins with this line.
ASPLearner.Pages.Pages_QuestionView.ExecuteAsync() in QuestionView.cshtml
7.var title = Model.dbctx.Posts.FirstOrDefault(x => x.Id == id).Title
Is Visual Studio confused and could this be the source of the error?
英文:
I read somewhere in the ASP.NET Core documentation that I don't need to worry about how an instance of my database context will be passed to other controller and model classes as dependency injection will automatically do that for me. I declared a Database Context property in the Page's model class and then required an instance of the Database Context in the constructor of the model.
However, when I try to access the Database Context object from the Razor page associated with the model then I get an error that my Database Context is not set to an instance of an object.
The controllers do not throw this error however despite implementing the same declare database context object as property and require it in the constructor.
Why is my database context null when I try to access it from the Model property of the Razor page and why is it not null when I access it from the controller?
// This property is accessed from the route
var id = Model.Id;
// Use the id to get all the information about this question
var title = Model.dbctx.Posts.FirstOrDefault(x => x.Id == id).Title;
// The dbctx reference above is returning null
The code above is at the top of the Razor page.
Here is how the model for that Razor page looks like:
public class QuestionViewModel:PageModel
{
// Get the id from the route
[FromRoute]
public int Id { get; set; }
// The database context property
public Dbctx dbctx { get; set; }
// Require an object in the constructor
public QuestionViewModel(Dbctx ctx)
{
dbctx = ctx;
}
}
I use the same logic as the above in my controllers. The only difference is that I use private fields on my controllers and then pass the Dbctx
reference to them via the constructors of the respective controllers.
How can I resolve this?
Update:
I do not know if it's the query that is returning null, but I redirect to this page after a new post object has been posted to the database. I then call databaseContext.SaveChanges() to make sure that the insert query was a success. I then grab the id of the last question that was inserted into database and then redirect to the QuestionView page as per the logic in this controller.
public IActionResult HandleNewPost(string Title, string Body, string Tags) {
// Split the tags based on the space
var tags = Tags.Split(' ');
var tagList = new List<Tag>();
tags.ToList().ForEach(tag => tagList.Add(new Tag(tag)));
// Get the time the post was authored
var creationTime = DateTime.Now;
var postedBy = HttpContext.Session.GetString("email");
var post = new Post {
Title = Title,
Body = Body,
PostedBy = postedBy,
Tags = tagList,
Upvotes = 0,
Downvotes = 0
};
// Post the object to database
_dbctx.Posts.Add(post);
_dbctx.SaveChanges();
// Get the id of the last post and redirect to QuestionView page
if(_dbctx.Posts.OrderBy(x=>x.Id).LastOrDefualt() != null) {
var id = _dbctx.Posts.OrderBy(x => x.Id).LastOrDefault().Id;
return RedirectToPage("/QuestionView", new []{id});
}
else {
// Some custom code
}
}
It is really weird that the error message starts with a different solution name. The name of my current solution is InputHandling, and there is another solution though in the repositories called ASPLearner. The QuestionView page is in the Page folder of my current solution, but the error stack begins with this line.
>ASPLearner.Pages.Pages_QuestionView.ExecuteAsync() in QuestionView.cshtml
7.var title = Model.dbctx.Posts.FirstOrDefault(x => x.Id == id).Title
Is Visual Studio confused and could this be the source of the error?
答案1
得分: 1
This method may help you:
通过 AddDbContext 配置 DBContext
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BloggingContext>(options => options.UseSqlite("Data Source=blog.db"));
}
向您的 DBContext 类中添加新的构造函数
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
:base(options)
{ }
public DbSet<Blog> Blogs { get; set; }
}
将上下文注入到您的控制器中
public class MyController
{
private readonly BloggingContext _context;
public MyController(BloggingContext context)
{
_context = context;
}
// ...
}
英文:
This method may help you:
Configure DBContext via AddDbContext
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BloggingContext>(options => options.UseSqlite("Data Source=blog.db"));
}
Add new constructor to your DBContext class
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
:base(options)
{ }
public DbSet<Blog> Blogs { get; set; }
}
Inject context to your controllers
public class MyController
{
private readonly BloggingContext _context;
public MyController(BloggingContext context)
{
_context = context;
}
...
}
答案2
得分: -1
I fell victim to a bad answer by ChatGPT again. The whole capturing the value returned by the route using an integer Model Property decorated with the [FromForm] attribute was ChatGPT's idea. That attribute was always zero as all integer properties and variables that are declared, but unassigned. Since I declared the id as a primary key on my Posts table then no record will ever be found with an id of 0 and that explains why the LINQ queries were returning null.
I just used the same logic I used in the controller to fetch the details of the question at the top of the file and it worked.
英文:
I fell victim to a bad answer by ChatGPT again. The whole capturing the value returned by the route using an integer Model Property decorated with the [FromForm] attribute was ChatGPT's idea. That attribute was always zero as all integer properties and variables that are declared, but unassigned. Since I declared the id as a primary key on my Posts table then no record will ever be found with an id of 0 and that explains why the LINQ queries were returning null.
I just used the same logic I used in the controller to fetch the details of the question at the top of the file and it worked.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论