ASP.net MVC - Display series of images based on byte[] - asp.net-mvc

I want to display a list of images and a description on a webpage using ASP.net MVC. The images are stored in a SQL Server DB and i'm getting them back as a byte[].
However, I don't understand how I can display a series of images on a page. I want to do something like this:
<% foreach(Product p in Model.Products)
Response.Write(p.Description)
Response.Write(html.Image(p.ImageArray)
%>
But the only code I've saw has been displaying a single image...
Thank you
Ben

Rather than creating a new HttpHandler you can just write a controller action that returns the contents of the image file. Then add images to the page with their src attribute set to the action you created.
EDIT: Note that streaming images as byte[] from a database is inefficient compared to serving static files.

You will need to create a custom IHttpHandler that will serve the images something like this:
public class AlbumArt : IHttpHandler
{
public void ProcessRequest(HttpContext Context)
{
byte [] b = your image...;
Context.Response.ContentType = "image/jpeg";
Context.Response.BinaryWrite(b);
}
}
And then you would need to retrieve each image from there by using image tags in your html, something like
<img src="AlbumArt.ashx?imageId=1" />

Images in HTML are external links, not embedded in the HTML itself. So you do need two requests. However you can optimize this a bit. In the first request, don't retrieve the image data itself, just the meta-data. Then in your HttpHandler, actually retrieve the binary image data.

Each image will have to be sent separately (which means creating an IMG request from the browser for each) or you will have to join them into a single image before sending back. If you run the code above it is likely you will see the first image only.

Related

dynamically create partial view (CSHTML)

Is it possible in ASP.NET MVC 5 to dynamically create a partial view (cshtml) in the /Views/Shared directory? I have a situation where people are going to upload a bunch of HTML as strings and was thinking it would be better for performance to store them on the file system.
Is it as simple as creating a new file, steaming a string and saving?
Yes it is possible
Simply make a view like DynamicView.cshtml
#model DynamicView
#Html.Raw(Model.HTMLString)
Now the method you will use to store both the HTML and the pointer to it is a different story. You can either store the sanitized HTML in a data-base and retrieve it with a call to the Controller like
public ActionResult DynamicView(ind id)
{
DynamicView model = new DynamicView();
DynamicView.HTMLString = dbContext.HTMLViews.Where(v => v.id == id);
return View(model);
}
If you wish to write the submitted HTML to files instead, you can instead do
public ActionResult DynamicView(string filePath)
{
DynamicView model = new DynamicView();
DynamicView.HTMLString = ...code that reads file
return View(model);
}
See this related post Writing/outputting HTML strings unescaped
Quick Answer: No (you cannot/should not modify Views Folder at RunTime.)
ASP.NET MVC Views and Shared Views are meant to be compiled and run. Modifying them or Adding new ones as the Application is running is not at all advisable or practical.
What would make more sense is for you to store the uploaded html blobs in a database, file system, storage blob (cloud). Then code your Shared View or Specific Views to retrieve specific html blobs from the stored location depending upon which user is logged in.
There are a whole lot of Extension Functions in MVC that Enable you to insert partial html in views. take a look at PartialExtensions as an starting point.
I had a requirement to create top menu which will generate from DB. I tried a lot to create it using partial view. But i found most of the cases partial view is use for static content. at last i fond some helpful tutorial please find the following i hope it will help you too.
click here to see how to create Dynamic Partial view

What sort of Image should I use in my model, when the aim is to display this image in a view?

I am in a situation where I am storing images as byte arrays in a SQL database. I am using EF, and so have a byte array automatic property in my model, which is then committed to the database via code first.
I want to put a read only property which is an Image into my model, and convert the byte array to an Image when the get accessor is called. Two questions:
What sort of Image should I use? Should it be a System.Drawing image, or a newer BitmapImage?
Will this cause any problems in regards to code-first and EF?
I can post code if you wish, but I didn't think it was necessary, if anybody wants to see my code, just leave a comment.
1) What sort of Image should I use? Should it be a System.Drawing
image, or a newer BitmapImage?
None of them. You should use a byte array (byte[]).
2) Will this cause any problems in regards to code-first and EF?
I don't think so. I am not an expert with EF but I think it should be possible to map a byte[] property to the corresponding varbinary(max) column in your database.
Now back to your original question about showing an image and having a property on your view model. Even if you do that you cannot display this byte array property as an image inside your view unless you use the data uri scheme which is not widely supported by all browsers. Here's how this might look like if you decide to go that route:
#model MyViewModel
...
<img src="data:image/png;base64,#Html.Raw(Convert.ToBase64String(Model.Image))" alt="some image">
But if you are looking for a solution that will work across all browsers as an alternative you could design a controller action that will fetch your image from the database as a byte array and then stream it to the response. Next from your view you could reference this action inside an <img> tag.
Let's take an example:
public ActionResult Image(int id)
{
byte[] imageData = ... go query your database to retrieve the corresponding
image record using the id
return File(imageData, "image/png");
}
and then inside your main view simply point an <img> tag to this controller action:
#model MyViewModel
...
<img src="#Url.Action("Image", "SomeController", new { id = Model.Id })">

What is the best practice to render an image in MVC from one call to get an aggregate

I have an issue that I would like some opinions on. I totally understand that I CANNOT render an image (byte[]) directly from my viewmodel. I understand that I need to have an id that represents my image in my view model.
Once I bind my viewmodel to my view I can then do something like the following:
<img src="#Url.Action("GetPhoto", new { photoId = Model.PhotoId })" />
And then this:
public ActionResult GetPhoto(int photoId)
{
byte[] photo = GetPhotoFromDb(photoId);
return File(photo, "image/jpeg");
}
However, I have a call to a 3rd party web service (I do not control this) that I call to get an aggregate that populated my viewmodel. Some thing like this:
-Vehicle
-VehicleId
-VehicleName
-VehicleImage byte[] <=======
-VehicleServiceHistory
-ServiceHistoryId
-SericeType
-ServiceTitle
So in theory I could call up the 3rd party web service people and say, I know you are already giving my the VehicleImage in the aggregate (above) but can I please have a separate call to a new service method called GetImageById(int imageId).
So lets assume they say no. So all I have is an aggregate of data that already has my image but I know I have to load the image to the view separately like I stated above:
<img src="#Url.Action("GetPhoto", new { photoId = Model.PhotoId })" />
I could do something nasty like add the image to session when the aggregate comes down from the web service and interrogate session to get the image back with the photoId but there is no way I want to do this.
Can anyone give me any ideas on how I can utilize the, already available, image in the aggregate without having to do another call.
Note: I am totally ok with calling a separate action:
public ActionResult GetPhoto(int photoId)
{
byte[] photo = GetPhotoFromDb(photoId);
return File(photo, "image/jpeg");
}
But I want to use the image that was already supplied in the aggregate in this action and not have to call the service again.
Looking forward to hearing your suggestions.
thanks
RuSs
Note: This post has been up here for a couple of weeks, surely someone has an opinion!! :(
I totally understand that I CANNOT render an image (byte[]) directly from my viewmodel
Well actually you can if the browser supports the data URI scheme:
<img src="data:image/jpeg;base64,#Html.Raw(Convert.ToBase64String(Model.VehicleImage))" />
Other than that there are not much choices left. You will have to persist the image somewhere on the server between the 2 HTTP calls. I congratulate you for the fact that you do not wish to use the Session for that. It's not the right storage for that. One possibility would be to persist the image on some folder on your server (shared folder if you are running on a webfarm) and then only reference the image by id. So basically you will be caching the remote images on your infrastructure. You could have some scheduled scripts that are deleting files older than some date that you could define.
The answer to this is that you have to populate the view model that would contain an id of the image you want to render.
Once the viewmodel has rendered you must call another controller action like this:
public ActionResult GetPhoto(int photoId()
{
byte[] photo = GetPhotoFromDb(photoId);
return File(photo, "image/jpeg");
}
After much investigation it seem this is just the way it is unless all browsers support data URI scheme.
<img src="data:image/jpeg;base64,#Html.Raw(Convert.ToBase64String(Model.VehicleImage))" />
Hope this helps.

How do you get the full URL of a file uploaded using an Upload object in Java Play?

I'm writing an image uploader in Java Play! in the style of
https://gist.github.com/1256286#file-picture-java-L3
This is great. The image is rendered using this function in the Controller object (here, Picture is a Model implementation that has metadata about an image file:
public static void show(Long id) {
Logger.info("loading id=%s", id);
Picture picture = Picture.findByKey(id);
response.setContentTypeIfNotSet(picture.contentType);
renderBinary(new ByteArrayInputStream(picture.file), picture.file.length);
}
I want to add a url member to Picture that contains the absolute URL to this function for a given picture. How can I populate this member in a way that works irrespective of where the Java Play! application is hosted?
Although I didn't try it in version 1.x I suggest to check the Router API, there are some methods which indicates, that they can optionally create an absolute route (I'm Play 2 user and have no experience with them).
There are also methods like ie. getBaseUrl() or getFullUrl(String action, Map<String,Object> args) so I just guess that they probably will help you to resolve the problem.

Display image from IMAGE object in MVC

I have an object of type IMAGE which holds image.
I wanted to display the image in MVC view along with other controls.
The way i can think of is to temporary store image on disk and set src of img control.
I am sure there would be better way of doing this.
The easiest way to do this in my opinion would be to return a FileStreamResult from your controller.
public FileResult GetImage()
{
string path = "c:\images\image.jpg";
return new FileStreamResult(new FileStream(path, FileMode.Open), "image/jpeg");
}
This is a simple implementation, but gives you a starting point for what you are attempting to do.
If you are interested in implementing #Giovanni's answer, then I have some code that may be helpful from a past answer I gave located here. The ImageHandler class is an example of what you would want to implement in Giovanni's case.
You can write a handler to stream images out and then reference the streamer in your image tag.
For instance, you have http://myapp/media.ashx?imageId=10 stream out the image. In your page you reference like so:
<img src="http://myapp/media.ashx?imageId=10"/>.
This way you don't have to temporarily write to disk.
You can serve your image as the response content of a controller action. this response will have the image type as content type.
You can convert the image to Base64 string and assign it to the src attribute of the img tag.
<img alt="Embedded Image" width="168" height="32"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKgA..." />
http://www.greywyvern.com/code/php/binary2base64

Resources