skip to Main Content

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…

5

Answers


  1. Chosen as BEST ANSWER

    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;
            }
    

  2. 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.

    Login or Signup to reply.
  3. 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

    Login or Signup to reply.
  4. 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.

    Login or Signup to reply.
  5. 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>
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search