Reputation: 202
I'm developing an server-side Blazor-application, which uses EntityFramework-Core to create the Database (code-first). I want to use one of the models in an EditForm-component, but it throws an NullReferenceException on the _Host.cshtml, whenever I open the page, containing the EditForm-component. Other pages are working completely fine! Error in Rider Screenshot This is the error given on the page:
An unhandled exception occurred while processing the request.
NullReferenceException: Object reference not set to an instance of an object.
WebApplication.Pages.Components.Customer.EditCustomer.<BuildRenderTree>b__0_4(RenderTreeBuilder __builder3)
Stack Query Cookies Headers Routing
NullReferenceException: Object reference not set to an instance of an object.
WebApplication.Pages.Components.Customer.EditCustomer.<BuildRenderTree>b__0_4(RenderTreeBuilder __builder3)
Microsoft.AspNetCore.Components.CascadingValue<TValue>.Render(RenderTreeBuilder builder)
Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)
Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry)
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessPendingRender()
Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(int componentId, RenderFragment renderFragment)
Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()
Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()
Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)
Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasks(Task task)
Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)
Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(int componentId, ParameterView initialParameters)
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.CreateInitialRenderAsync(Type componentType, ParameterView initialParameters)
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.RenderComponentAsync(Type componentType, ParameterView initialParameters)
Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext+<>c__11<TResult>+<<InvokeAsync>b__11_0>d.MoveNext()
Microsoft.AspNetCore.Mvc.ViewFeatures.StaticComponentRenderer.PrerenderComponentAsync(ParameterView parameters, HttpContext httpContext, Type componentType)
Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.PrerenderedServerComponentAsync(HttpContext context, ServerComponentInvocationSequence invocationId, Type type, ParameterView parametersCollection)
Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.RenderComponentAsync(ViewContext viewContext, Type componentType, RenderMode renderMode, object parameters)
Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.<RunAsync>g__Awaited|0_0(Task task, TagHelperExecutionContext executionContext, int i, int count)
WebApplication.Pages.Pages__Host.<ExecuteAsync>b__14_1() in _Host.cshtml
<component type="typeof(App)" render-mode="ServerPrerendered"/>
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync()
WebApplication.Pages.Pages__Host.ExecuteAsync() in _Host.cshtml
Layout = null;
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Show raw exception details
This is my EditCustomer-Razorcomponent:
@page "/customers/edit/"
@page "/customers/edit/{CustomerId:int}"
@using DataModels.Invoice
@inject IToastService _toastService
<AuthorizeView Context="authContext">
<Authorized>
<h3>Edit Customer</h3>
<EditForm OnValidSubmit="@OnValid_Submit" Context="formContext" Model="@CurrentModel">
<DataAnnotationsValidator/>
<ValidationSummary/>
<div class="form-group">
<label for="CompanyName">Company Name:</label>
<input id="CompanyName" class="form-control" type="text"/>
</div>
<div class="form-row">
<div class="form-group col-md-1">
<label for="FormOfAddress">Form:</label>
<select id="FormOfAddress" class="form-control">
<option value="1">Herr</option>
<option value="2">Frau</option>
<option value="3">Divers</option>
</select>
</div>
<div class="form-group col-md-3">
<label for="PreName">Prename:</label>
<input id="PreName" class="form-control" type="text"/>
</div>
<div class="form-group col-md-3">
<label for="SurName">Surname:</label>
<input id="SurName" class="form-control" type="text"/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-3">
<label for="Email">Email:</label>
<input id="Email" class="form-control" type="email"/>
</div>
<div class="form-group col-md-3">
<label for="Telephone">Telephone:</label>
<input id="Telephone" class="form-control" type="tel"/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="Address">Address:</label>
<input id="Address"
@bind="CurrentModel.Address.StreetName"
class="form-control"
type="text"/>
</div>
<div class="form-group col-md-1">
<label for="HouseNumber">Nr:</label>
<input id="HouseNumber"
@bind="CurrentModel.Address.HouseNumber"
class="form-control"
type="text"/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-2">
<label for="ZipCode">Zip-Code:</label>
<input id="ZipCode"
@bind="CurrentModel.Address.City.ZipCode"
class="form-control"
type="text"/>
</div>
<div class="form-group col-md-3">
<label for="City">City:</label>
<input id="City"
@bind="CurrentModel.Address.City.Name"
class="form-control"
type="text"/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-3">
<label for="UstId">Ust.Id.:</label>
<input id="UstId" class="form-control" type="text"/>
</div>
<div class="form-group col-md-3">
<label for="CommercialRegisterNr">Commercial Register Nr.:</label>
<input id="CommercialRegisterNr" class="form-control" type="text"/>
</div>
</div>
<div class="form-group">
<h4>Fields</h4>
<table class="table">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
<th>Action</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<button type="submit" class="btn btn-primary">Save Changes</button>
</EditForm>
</Authorized>
<NotAuthorized>
<NotPermitted/>
</NotAuthorized>
</AuthorizeView>
C# code:
@code {
[Parameter]
public int? CustomerId { get; set; }
private Customer CurrentModel { get; set; } = new();
private List<Tuple<string, string>> Fields { get; set; }
private string TupleKey { get; set; }
private string TupleValue { get; set; }
protected override void OnInitialized()
{
Fields = new List<Tuple<string, string>>();
if (CustomerId is not null)
{
//Load from DbContext
return;
}
CurrentModel = new Customer();
}
private void OnValid_Submit(EditContext context)
{
Console.WriteLine("works.");
}
}
This is my customer-model:
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace DataModels.Invoice
{
public class Customer
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string CompanyName { get; set; }
public ContactPerson ContactPerson { get; set; }
public Address Address { get; set; }
public string UstId { get; set; }
public string CommercialRegisterNr { get; set; }
public IEnumerable<CustomerInfoField>? AdditionalFields { get; set; }
public IEnumerable<Invoice>? Invoices { get; set; }
}
}
The page works when throwing in a "dummy"-class with only one or two properties in it with @bind. Would really appreciate your help since it's driving me crazy...
Upvotes: 14
Views: 12951
Reputation: 645
What was causing this error for me was letting the HTML portion of the page run ahead without using something like @if (MyObject != null) {}
to prevent it from running. I believe the HTML side of the system was "getting ahead" of the server side of the system.
Upvotes: 1
Reputation: 1541
For me I had forgot to add the @ before bind-Value
Raised error described:
<InputText type="text" placeholder="+46702692086" bind-Value="Model.FromNumber" class="form-control" id="senderNumber"></InputText>
No error:
<InputText type="text" placeholder="+46702692086" @bind-Value="Model.FromNumber" class="form-control" id="senderNumber"></InputText>
Upvotes: 0
Reputation: 81
For me it was having Button with Href="someNullableField!"
. Making it Href="someNullableField?"
fixed the issue.
Upvotes: 0
Reputation: 31
Another potential cause -- having both a @page directive and a [Route] attribute on the same page. I switched to Routes and forgot to comment out the @page.
Upvotes: 0
Reputation: 1240
If it helps, I received this error when I was missing an "@" in front of an if-then block. The pre-compilier did not catch it for some reason.
@if(x == y)
{
<div>display text</div>
}
Upvotes: 0
Reputation: 301
Similarly to what balintn mentioned, this can be caused by a malformed @page
directive - in my case though, it wasn't type restrictions causing it, it was that I had two parameters in the URL and I forgot to add a slash between them.
Before:
@page "/my/page/{param1}{param2}"
After:
@page "/my/page/{param1}/{param2}"
Alternatively, you can decorate your parameters with the [SupplyParameterFromQuery]
attribute, and the URL's can look like the standard HTML query parameters without error.
Seems like something that could be checked for in the render engine. Pretty vague error otherwise.
Upvotes: 0
Reputation: 1463
Found another issue with the @page directive that causes a NullReferenceException:
Mine looked like this:
@page "/mypage/{id:string}"
or
@page "/mypage/{id:string?}"
Changing to
@page "/mypage/{id}"
fixed the issue
Upvotes: 9
Reputation: 1470
Found out you get this error if you have two .razor files with the same @page directive.
It would be great if the exception had told me about this mistake.
In my case I copied a razor page and forgot to change the first line of the file that had:
@page "/databaseoracle"
So I had two @page commands with the same name.
once I changed my duplicate file to be
@page "/databaseteradata"
The error went away.
That is 4 hours of my life that I am not getting back. Hopefully someone will find this useful.
My loss is your gain.
Upvotes: 32
Reputation: 202
i kinda found the reason for this behavior. The objects contained in the Customer-class i.e. contact person seems to be null when bind empty. When using the DbContext to get a existing object using .Include-Calls the page works. This is my workaround for now:
protected override async Task OnInitializedAsync()
{
Fields = new List<Tuple<string, string>>();
if (CustomerId is not null)
{
await using var context = new ApplicationDbContext();
CurrentModel = await context.Customers
.Include(x => x.ContactPerson)
.Include(x => x.Address)
.Include(x => x.AdditionalFields)
.FirstOrDefaultAsync(c => c.Id == CustomerId);
return;
}
CurrentModel = Customer.CreateEmpty();
}
And the static method for new objects:
public static Customer CreateEmpty()
{
var customer = new Customer
{
ContactPerson = new ContactPerson()
};
var address = new Address
{
City = new City()
};
customer.Address = address;
customer.AdditionalFields = new List<CustomerInfoField>();
return customer;
}
Upvotes: 3