I am building a web app in C# and ASP.Net with an MVC framework. I have the app running on my local desktop (for now). The app has a SQL backend that stores all my data. I am able to pull the data from the SQL db successfully through a number of stored procedures. The data is able to successfully be transferred from the stored procedures all the way up to my view from the controller.
Part of the data being transferred to the view is a byte[] from an image stored in the db (datatype is VARBINARY(MAX)). In short, I am trying to get the data from this byte[] to display as a background image in a div. This div acts as a single image in a Bootstrap carousel.
Initially, I had the following as my controller:
public ActionResult Dashboard()
{
DashboardViewModelHolder holder = new DashboardViewModelHolder();
DiscoveryService discoveryService = new DiscoveryService();
holder.national_Elected_Officials = new List<National_Elected_Officials_Model>();
National_Elected_Officials_Model n = new National_Elected_Officials_Model();
foreach (List<object> official in discoveryService.retrieve_National_Elected_Officials())
{
for(int i = 0; i <= official.Count; i++)
{
int id = int.Parse(official.ElementAt(0).ToString());
string fname = official.ElementAt(1).ToString();
string lname = official.ElementAt(2).ToString();
byte[] pictureByteArray = (byte[])official.ElementAt(3);
string position = official.ElementAt(4).ToString();
string party = official.ElementAt(5).ToString();
string bio = official.ElementAt(6).ToString();
int yearsOfService = int.Parse(official.ElementAt(7).ToString());
int terms = int.Parse(official.ElementAt(8).ToString());
string branch = official.ElementAt(9).ToString();
Image picture = image_Adapter.byteArrayToImage(pictureByteArray);
n.ElectedOfficialID = id;
n.FirstName = fname;
n.LastName = lname;
n.Picture = picture;
n.Position = position;
n.Party = party;
n.Bio = bio;
n.YearsOfService = yearsOfService;
n.Terms = terms;
n.Branch = branch;
}
holder.national_Elected_Officials.Add(n);
}
return View(holder);
}
My thought process was that I would just call n.Picture in my view and it would render the picture. After several tries and tutorials later, I left n.Picture as a byte[] and processed it in its own ActionResult method as seen below:
public FileContentResult Image(byte[] pictureByteArray)
{
return new FileContentResult(pictureByteArray, "image/jpeg");
}
I call this in my view as the following:
<div class="fill" style="background-image:src(@Url.Action("Image", electedOfficial.Picture))"></div>
electedOfficial is a reference to the model being set in the controller (n.Picture).
Is there something that I am missing?
EDIT 1
I forgot to add that the div returns null when I debug and step through the code. This is because the line with the div never gets called on when debugging. If I have it set as Url.Action, the program will actually go to the controller before hitting the line. If I do Html.Action, the program will skip the line and go to the controller after. Both will return null as a result which returns an error on the controller side since nulls arent allowed.
Edit 2 I tried changing the div tag to the following:
<div class="fill" style="background-image:src(@{Html.Action("Image", electedOfficial.Picture);})"></div>
By putting the {} in the debugger actually parses the line as I step through. Now, the problem is that the controller is not receiving the value being passed to it from electedOfficial.Picture. Just to confirm, this variable does hold the correct value in the view.
If you have the full byte[]
in your model, then you can put the data directly into the view:
<div style="background:url( data:image/jpeg;base64,@Convert.ToBase64String(electedOfficial.Picture) )"></div>
This will work without the need for a separate controller that returns a FileContentResult
, but will be a longer initial page load since the user will download all of the images along with the page HTML.
If you want to use a Controller endpoint so the images can be referenced as a URL in the src
attribute and downloaded after the HTML has rendered then you are not too far off. It would work better to have the controller accept ElectedOfficialID
and return the FileContentResult
from that.
public FileContentResult Image(int electedOfficialId)
{
byte[] picture = GetPicture(electedOfficialId);
return new FileContentResult(picture, "image/jpeg");
}
Simples way of doing that would be encoding image as base64 string and add new string property eg PictureAsString
to model instead having Picture
controller
n.PictureAsString = Convert.ToBase64String(pictureByteArray)
view
<div style="background:url(data:image/jpeg;base64,@electedOfficial.PictureAsString )" ></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With