0
votes

I have a Model that has a property Publisher of type ApplicationUser. When I try to create the Model, it gives me a nullreference exception.

In the Model:

[Display(Name = "Publisher")]
[ForeignKey("PublisherId")]
public ApplicationUser Publisher { get; set; }

In ApplicationUser:

public ICollection<Model> PublishedModels { get; set; }

The many-to-one relation in the DB context:

b.HasMany(u => u.PublishedModels)
     .WithOne(v => v.Publisher)
     .IsRequired()
     .OnDelete(DeleteBehavior.Restrict);

In the Create method of the controller (get the current user):

var user = await _userManager.GetUserAsync(HttpContext.User);

The I get a nullreference on this line:

model.Publisher = user;

I'm confused, I verified that user is not null. Model is not null and ModelState is valid. Then why can't I assign that value to model.Publisher? The strange thing is that if I don't modify model and just save it to the DB, it works. But I need to add the publisher too. If I only set the date, it's also fine.

This works, but when removing the comments it complains about a nullreference when setting the date.

public async Task<IActionResult> Create([Bind(include:"...")] Model model)
{
    ApplicationUser user = await _userManager.GetUserAsync(HttpContext.User);
    try
    {
        if (ModelState.IsValid)
        {
            model.PublicationDate = DateTime.Now;

            //user.PublishedModels.Add(model);

            _context.Add(model);
            //_context.Update(model.Publisher);

            await _context.SaveChangesAsync();

            return RedirectToAction(nameof(Index));
        }
    }
    catch (DataException /*dex*/)
    {
        ModelState.AddModelError("", "...");
    }
    return View(model);
}

In the following stack trace, it crashes on the first line in the method ...

NullReferenceException: Object reference not set to an instance of an object.
WebApp.Controllers.Admin.ModelController.Create(Model model) in 
ModelController.cs
-
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind(include:"...")] Model model)
{
    var user = await _userManager.GetUserAsync(HttpContext.User);
    user.PublishedModels.Add(model);
    model.PublicationDate = DateTime.Now;
    model.Publisher = user;
    try
    { 
Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)

System.Threading.Tasks.ValueTask.get_Result() Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync() Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync() Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

1
The only thing that could possibly throw this exception on that line is if model is null. Either model is null, the exception is being thrown from a different place, or you've got something else weird going on like custom getters/setters that are throwing the exception. Post your stack trace.Chris Pratt
No custom getters. It's like I HAVE to save the model to the database in that method, doesn't seem to accept me modifying the posted model. Maybe it has to do with antiforgery?fonZ
That doesn't appear to be the full stack trace. It looks like you've modified it. It particular it's not calling out any particular line.Chris Pratt
I modified the name of the model. The thing is that there is no nullreference. When I add the code to get the user, it gets it correctly, I can see the value. Then the next line fails, no matter what line it is. If I remove the user related code, it just works. I do this with an authenticated user.fonZ

1 Answers

1
votes

Fail to reproduce your issue, check the difference between your code and below:

  1. You defined PublishedModels in ApplicationUser, but you referenced PublishedModel.
  2. DbContext, for code below, if you did not set the value for Publisher or PublisherId when creating Model, you will get error for you did not set the value for PublisherId, but you did not, check whether you keep the model and database same.

            builder.Entity<ApplicationUser>()
                    .HasMany(u => u.PublishedModels)
                    .WithOne(vv => vv.Publisher)
                    .IsRequired()
                    .OnDelete(DeleteBehavior.Restrict);
    
  3. Method to create model with applicationuser

            public async Task<IActionResult> Create([Bind("Id,Name")] Model model)
            {
                    ApplicationUser user = await _userManager.GetUserAsync(HttpContext.User);
                    if (ModelState.IsValid)
                    {
                            model.Publisher = user;
                            _context.Add(model);
                            await _context.SaveChangesAsync();
                            return RedirectToAction(nameof(Index));
                    }
                    return View(model);
            }