Strange NullRefereneceException in Razor helper
Asked Answered
T

6

16

I'm using Razor Helpers in a C# Web Forms application.

The following code compiles and renders A-OK when called:

@helper MemberListItem(string firstname, string lastname, string avatarUrl)
{
    <li>
        @firstname @lastname
        @avatarUrl
    </li>
}

Output (two calls to the helper):

<li>Bryan Arnold ../../Resources/Images/Placeholders/generic-user-image.jpg</li>
<li>Doug Bland ../../Resources/Images/Placeholders/generic-user-image.jpg</li>

But when I change the helper so that avatarUrl is placed in the src attribute of an img tag, I get a NullReferenceException on firstname. Yes, the NullReferenceException is on firstname.

The following code compiles but throws a NRE when called:

@helper MemberListItem(string firstname, string lastname, string avatarUrl)
{
    <li>
        @firstname @lastname
        <img src="@avatarUrl"/>
    </li>
}

Keep in mind that I am not changing a thing besides the placement of @avatarUrl in the helper.

How do I get the image to display?

Update 1: I have also tried wrapping my img code in <text></text> (to no avail):

<li>
    @firstname @lastname
    <text>
        <img src="@avatarUrl"/>
    </text>
</li>

Update 2: Here is the error:

Object reference not set to an instance of an object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error: 

Line 11: {
Line 12:     <li>
Line 13:         @firstname @lastname
Line 14:         <img src="@avatarUrl"/>
Line 15:     </li>

Source File: RazorHelpers\Family.cshtml    Line: 13 

Update 3: I forgot to mention that I am defining the @helper in a separate file. Then, I am calling that helper from an aspx template like this:

<%= @HelperFile.Helper(parameters).ToString() %>

Also, I think @Luaan might be on to something. I have tried fiddling with ~ for relative pathing to my image files, thinking that Razor might be throwing a NRE because it cannot locate the file. It would appear that no setup with ~ works in my project.

With a static file path:

This works:

<img src="/Resources/Images/Placeholders/generic-user-image.jpg"/>

This doesn't (NullReferenceException):

<img src="~/Resources/Images/Placeholders/generic-user-image.jpg"/>

With a dynamic file path:

This doesn't work (NullReferenceException):

<img src="@avatarUrl"/>

Neither does this (NullReferenceException):

<img src="~@avatarUrl"/>

Note: The Resources directory is in the root of my website.

Update 4:

I have deserted my original helper (the one mentioned at the beginning of this question) and gone with a pure ASPX template due to time constraints with my project. However, I am trying to use a Razor helper for a different feature in this application and I am having the same problem I have described prior.

Here is a similar helper (source and compiled code). The helper is supposed to display a list of links that allow the user to sign-up/sign-in for my application using various identity providers (google, facebook, twitter, yahoo). The story is the same here; the helper executes without an error when I just print the img src but it throws a NullReferenceException when I put the img src into an actual <img/> tag.

Source:

@helper ListGroupGrid(IEnumerable<ExternalIdentityProvider> providers) {
    <div>
        @foreach(var provider in providers){
            @provider.Name
            <img src="@provider.IconUrl"/>
        }
    </div>
}

Compiled code (from Temporary ASP.NET Files in c:\Windows):

#pragma checksum "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "46B0FEE2042706017F4AE53D4EA612F3E73EDF8B"
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.18052
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace ASP.RazorHelpers {
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Web;
    using System.Web.Helpers;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.WebPages;
    using System.Web.WebPages.Html;

    #line 1 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"
    using Aqha.DatabaseHelpers;

    #line default
    #line hidden

    #line 2 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"
    using Aqha.RazorExtensions;

    #line default
    #line hidden

    #line 3 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"
    using DevExpress.Utils.Drawing.Helpers;

    #line default
    #line hidden


    public class IdentityProvider : System.Web.WebPages.HelperPage {

#line hidden

#line 5 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"
public static System.Web.WebPages.HelperResult ListGroupGrid(IEnumerable<IdentityProviderData.ExternalIdentityProvider> providers) {
#line default
#line hidden
return new System.Web.WebPages.HelperResult(__razor_helper_writer => {

#line 5 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"



#line default
#line hidden
BeginContext(__razor_helper_writer, "~/App_Code/RazorHelpers/IdentityProvider.cshtml", 202, 11, true);

WriteLiteralTo(__razor_helper_writer, "    <div>\r\n");

EndContext(__razor_helper_writer, "~/App_Code/RazorHelpers/IdentityProvider.cshtml", 202, 11, true);


#line 7 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"


#line default
#line hidden

#line 7 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"
         foreach(var provider in providers){


#line default
#line hidden
BeginContext(__razor_helper_writer, "~/App_Code/RazorHelpers/IdentityProvider.cshtml", 272, 13, false);


#line 8 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"
WriteTo(__razor_helper_writer, provider.Name);


#line default
#line hidden
EndContext(__razor_helper_writer, "~/App_Code/RazorHelpers/IdentityProvider.cshtml", 272, 13, false);


#line 8 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"



#line default
#line hidden
BeginContext(__razor_helper_writer, "~/App_Code/RazorHelpers/IdentityProvider.cshtml", 287, 16, true);

WriteLiteralTo(__razor_helper_writer, "            <img");

EndContext(__razor_helper_writer, "~/App_Code/RazorHelpers/IdentityProvider.cshtml", 287, 16, true);

WriteAttributeTo(__razor_helper_writer, "src", Tuple.Create(" src=\"", 303), Tuple.Create("\"", 326)

#line 9 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"
, Tuple.Create(Tuple.Create("", 309), Tuple.Create<System.Object, System.Int32>(provider.IconUrl

#line default
#line hidden
, 309), false)
);

BeginContext(__razor_helper_writer, "~/App_Code/RazorHelpers/IdentityProvider.cshtml", 327, 4, true);

WriteLiteralTo(__razor_helper_writer, "/>\r\n");

EndContext(__razor_helper_writer, "~/App_Code/RazorHelpers/IdentityProvider.cshtml", 327, 4, true);


#line 10 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"
        }


#line default
#line hidden
BeginContext(__razor_helper_writer, "~/App_Code/RazorHelpers/IdentityProvider.cshtml", 342, 12, true);

WriteLiteralTo(__razor_helper_writer, "    </div>\r\n");

EndContext(__razor_helper_writer, "~/App_Code/RazorHelpers/IdentityProvider.cshtml", 342, 12, true);


#line 12 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"


#line default
#line hidden
});

#line 12 "C:\Users\Public\Documents\VisualStudioProjects\OnlineStable\Aqha\App_Code\RazorHelpers\IdentityProvider.cshtml"
}
#line default
#line hidden


        public IdentityProvider() {
        }

        protected static ASP.global_asax ApplicationInstance {
            get {
                return ((ASP.global_asax)(Context.ApplicationInstance));
            }
        }
    }
}

Update 5: I did some more testing. To illustrate the issue as clearly as possible, I eliminated all input parameters and extra markup.

Consider the following three helpers:

@helper BaseCase() {
    <img src="/Resources/Images/Placeholders/generic-user-image.jpg"/>
}

@helper VariableBaseCase() {
    var src = "/Resources/Images/Placeholders/generic-user-image.jpg";
    <img src="/Resources/Images/Placeholders/generic-user-image.jpg"/>
    <text>the source is @src</text>
}

@helper Variable() {
    var src = "/Resources/Images/Placeholders/generic-user-image.jpg";
    <img src="@src"/>
    <text>the source is @src</text>
}

When I call the first two helpers from an ASPX, they display output (and the images appear normally) without exception:

<%= RazorHelpers.ImageTest.BaseCase().ToString() %>
<%= RazorHelpers.ImageTest.VariableBaseCase().ToString() %>

When I call the last helper, I get the same error I have been getting.

<%= RazorHelpers.ImageTest.Variable().ToString() %>

I hope now I am correct in believing that this is somehow a relative path issue. How do I get Razor to display images with dynamic src properties in my Web Forms application?

Tartar answered 12/11, 2013 at 17:26 Comment(10)
Are you absolutely sure it's not null or that there's nothing else going on? Using your exact method, and passing the two sets of data to it, I'm getting the correct output. I should mention that's within an MVC application.Distortion
I am positive that it's not null. My base case shows that.Tartar
Well, there is certainly a null somewhere. I just know it isn't my data. Also, I'm using Web Forms.Tartar
Is there a way to see generated C# file? You might find it in ASP.NET temp files. Or you can download and see output of RazorGenerator.Seamanship
I am confused. I'm using VS 2012 + update 3. I created a new Empty Web Form Application. I added Razor 3 and WebPages 3 nuget packages to my project. I added a CSHTML file in my project. I typed your codes there. I ran application without any error and result was correct and well formed HTML. Did I do something different?Psychosurgery
Maybe you did. I am not sure. I have had plenty of run-ins with NullReferenceException just like this. It's probably something I am doing un-knowingly :(Tartar
I ran your codes on Razor 2 and WebPages 2 (this time version 2 not 3). There were no errors too. This error is not related to Razor engine. Something(s) was(were) happened before view's rendering phase.Psychosurgery
could you please try adding #error directive somewhere close to your function and try to compile. It will give an error and will show you generated code for your page. I need to see that to understand this situationParmenter
@edokan. I did what you said with #error but I didn't see any special output. I updated my question with the compiled code for an example helper.Tartar
See the issue github.com/RazorGenerator/RazorGenerator/issues/57Tillietillinger
D
2

I just had a simular problem (mvc.net 4). I bypassed it this way:

error code:

<input name="ItemUID" type="hidden" value="@ItemUID" />

working code:

<input name="ItemUID" type="hidden" @("value=")"@ItemUID" />
Dempsey answered 21/10, 2015 at 10:49 Comment(1)
very interesting.. I'll have to check this out furtherTartar
A
1

Razor parser will not parse your HTML correctly because it looks for sections at a time. In this case it assumes the whole block () is HTML

Try surrounding your HTML with < text> HTML here < / text> Makes it a lot easier to read and interpret by the parser

Annalist answered 12/11, 2013 at 17:44 Comment(4)
Thanks, I just tried that but it didn't help. The NRE is still occurring.Tartar
Try wrapping the <img src="AND "/> separately. I'm thinking that your @avatarUrl is not being rendered correctlyAnnalist
That doesn't help either. :(Tartar
Could you tell me the error you get? because I just tried your original code on my MVC 4 razor project and it worked fineAnnalist
A
1

I believe that Razor tries to make sure the URL you're passing to img src is valid. Are you sure the files actually exist in the correct relative directory? Maybe you could try passing the URL in root-relative format (ie. "~/Resources/Images/Placeholders/generic-user-image.jpg"). If that doesn't help, you could try rendering the image using @Html.Image or @Html.Raw. And if that doesn't help, try @Url.Content(avatarUrl), but that's really trying hard :)

Abridge answered 25/11, 2013 at 16:47 Comment(6)
Related to that, are you defining the @helper in an actual page, or some sort of helper "library"? It might be throwing null on some kind of page reference when trying to resolve the URL. Just as a test, try moving the @helper to the page where you're actually using it.Abridge
Did some testing with hard-coded values. This works: <img src="/Resources/Images/Placeholders/generic-user-image.jpg"/>. This throws a NRE: <img src="~/Resources/Images/Placeholders/generic-user-image.jpg"/>Tartar
Also, this doesn't work (from my question) <img src="@avatarUrl"/>. This doesn't work either (added ~): <img src="~@avatarUrl"/>. For the latter, the value for src would be ~/Resources/Images/Placeholders/generic-user-image.jpgTartar
It would appear that ~ does not work at all for me. Is that a construct of Razor or of MVC? (I'm using Web Forms)Tartar
Also, I am defining the @helper in a separate file. Then, I am calling that helper from an aspx template like this: <%= @HelperFile.Helper(parameters).ToString() %>Tartar
Now that I've seen your example code, I'm thinking the issue might really be with using Razor helpers in WebForms code. Razor tries to resolve the Url using WebPageContext/WebPage, which are null (WebForms uses HttpContext/Page instead). As for fixing it, you could try calling (HttpContext.Current.CurrentHandler as Page).ResolveUrl(avatarUrl) when creating the image src. If that works, you can make that into a helper to make it simpler to use (or pass Page instance to your helper). If it doesn't work, you're probably stuck with having to write the HTML manually using @Html.Raw or such.Abridge
P
1

It seems you are not the only one with the problem. You MVC version (MVC2 I assume) has a bug that raises and exception when it calls WriteAttributeTo. This problem is mentioned in following stackoverflow question "Null reference exception in WriteAttributeTo method".

Only reasonable solution is to use a newer version. probably MVC3 (with update1). Your .NET version is 4.0+ so it will not be a problem.

Parmenter answered 26/11, 2013 at 9:31 Comment(1)
Sorry, my bad. I meant razor runtime. Update your razor runtime.Parmenter
A
1

This rings a bell somewhere. Try the below with the parentheses around the variables, it seems to help the Razor engine out a bit:

@helper MemberListItem(string firstname, string lastname, string avatarUrl)
{
    <li>
        @(firstname) @(lastname)
        <img src="@(avatarUrl)" />
    </li>
}
Alius answered 26/11, 2013 at 9:38 Comment(1)
This fixed a problem I was having. I wasn't using img tags in my helper but was writing attributes using @. Thanks!Electroacoustics
B
0

A bit late but I had the same problem and took me several hours to solve. What fixed the issue for me was the following:

string attributeValue= "some value";

string attributeExpression= "attributeName=" + attributeValue;

<div class="" id="" @attributeExpression></div>
Blooded answered 29/4, 2020 at 11:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.