D-W
D-W

Reputation: 5341

ASP.net MVC 4 display image

Im displaying an image on my page like so

 <img src="data:image;base64,@System.Convert.ToBase64String(Model.PhotoDisplay)" />

my model

 public byte[] PhotoDisplay { get; set; }

However PhotoDisplay may not have an image so may returns null so im getting an error

An exception of type 'System.ArgumentNullException' occurred in mscorlib.dll but was not handled in user code

Additional information: Value cannot be null."

How what the best way to handle this, example would be great.

Upvotes: 2

Views: 1079

Answers (4)

Brian Ball
Brian Ball

Reputation: 12606

If you are looking to keep your markup as simple as possible, you can do this:

<img src="data:image;base64,@System.Convert.ToBase64String(Model.PhotoDisplay ?? new byte[0])" onerror="this.src='';" />

What this essentially does is if your Mode.PhotoDisplay proeprty is null, it passes in an empty byte array to the System.Convert.ToBase64String method. The method will then return an empty string.

At this point, the browser will display some sort of "broken image" icon since the src attribute will no longer be valid. Because it is no longer valid, the onerror handler will be invoked. I am simply setting the src attribute to an empty string. You can handle it differently if you'd like (e.g. set the src to a URL, hide the tag completely, etc.).

Upvotes: 0

AlexC
AlexC

Reputation: 10756

You could use shared templates to do this.

You could annotate your byte array with something like

[UIHint("BytePhoto")]
public byte[] PhotoDisplay { get; set; }

and create a new file called BytePhoto.cstml in /Views/Shared/DisplayTemplates/

That file contents should look something like this

@model byte[]
@if (Model != null)
{
   <img src="data:image;base64,@System.Convert.ToBase64String(Model)" />
} else {
   <b>No image to display</b>
}

Then you could call this display template using @Html.DisplayFor(model => model.PhotoDisplay) in your Razor files rather than <img src="data:image; base64, @System.Convert.ToBase64String(Model.PhotoDisplay)" />.

If this is something you might do a lot you could go one step further and create a class that would encapsulate the byte array called something like BytePhoto. Then you would not need the UIHint at all and the Razor markup would just work using the Display Templates.

Upvotes: 1

whoah
whoah

Reputation: 4443

Thanks, any better way to handle it controller side?

There is only one option, if you're passing from controller byte[] PhotoDisplay, you have to validate that field on front side - as Stephen Muecke wrote in comment:

@if(Model.PhotoDisplay != null) 
{ 
    <img src="data:image;base64,@System.Convert.ToBase64String(Model.PhotoDisplay)" />
}
else
{
    // some message
}

Otherwise, you can also do something like this at controller side:

private byte[] _photoDisplay
public byte[] PhotoDisplay { 
   get{ 
       return _photoDisplay!=null?_photoDisplay:new byte[1]; 
   } 
   set
   {
      _photoDisplay = value; 
   } 
}

Upvotes: 0

Neel
Neel

Reputation: 11741

I guess putting nullable might help you as shown below :-

public byte[]? PhotoDisplay { get; set; }

or you can even code as below :-

[Column(TypeName = "image")]
public byte[] PhotoDisplay { get; set; }

Upvotes: 0

Related Questions