I have tried following examples that look fairly simple for getting the id of a primary key after inserting a new record for use in other tables that need to use it as a foreign key, but despite following these examples to the letter I am still getting a null reference exception for the id.
The example I followed was at https://www.entityframeworktutorial.net/faq/how-to-get-id-of-saved-entity-in-entity-framework.aspx except I am trying to use it in an async task in the code behind of a Razor Page in ASP.NET Core 3.1 as follows:
private readonly ApplicationDbContext _context;
public IndexModel(ApplicationDbContext context)
{
_context = context;
}
[BindProperty]
public Posts Posts { get; set; }
public async Task<IActionResult> OnPostAsync()
{
_context.Posts.Add(Posts);
await _context.SaveChangesAsync();
int postid = Posts.Postid;
string targeturl = linkgenerator.postlink(postid, Posts.Title);
return RedirectToPage(targeturl);
}
That results in a new post being generated with an error:
NullReferenceException: Object reference not set to an instance of an object
Why am I not able to get the Postid as easily as the example says I should be able to?
The relevant part of the Posts model is as follows:
[Key]
public int Postid { get; set; }
All the input values for the new record come from a form on the Razor Page. I need to get the Postid after the submit button is clicked.
UPDATE: Feedback indicates that I should share the Razor Page code. That code is basically this:
<form id="newpost" method="post">
This page has countless controls the reproduction of which would not be efficient for the purpose of this question. Here is one example control
<div class="form-group row">
<label class="col-sm-2 col-form-label" asp-for="Posts.Title"></label>
<div class="col-sm-7">
<input class="form-control" asp-for="Posts.Title" />
</div>
<span class="text-danger col-sm-3 col-form-label" asp-validation-for="Posts.Title"></span>
</div>
<button type="submit" value="Create" class="btn btn-primary">Submit Post</button>
</form>
Another thing to add. This is my first .Net Core website and all my prior work was with ASP.Net WebForms. As such I have had a lot of difficulty at times binding the code behind page to controls on the main page because they don’t work like WebForms controls worked. On WebForms if I wanted to get a value of a form control during an insert event I could just get the value by writing something like string title = TextBox1.Text.ToString() and there is something that works similar to that using HttpContext and id numbers of form controls, but that still requires that the form control have a value. There will never be a value for the primary key of a record that has not yet been created in a form control.
On a WebForm I would use a SqlDataSource control and get the scoped identity value of the primary key after creating the new record. According to evey tutorial I have seen including the one I already linked to EF generates the scoped identity automatically so all I need to do is save my changes to the database and access it the way I have been trying to access it.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
It turns out that you need to create a new object and assign each value manually. If you do it that way then the scope identity becomes available after it is saved, but for some reason you can’t get that simply by relying on the default method for binding basic forms on Razor Pages to models.
This is an example of what works
var newPost = new Posts();
newPost.Title = Posts.Title;
await _context.Posts.AddAsync(newPost);
await _context.SaveChangesAsync();
int postid = newPost.Postid;
This is required even if you have a bound input on a form in a razor page for Posts.Title because you can’t get the scope identity of the Posts object without creating a new Posts object. I asked Microsoft why but none of their staff members would explain why this is.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0