ASP.NET MVC: loading images from database and displaying their in view - c#

We have some images in our database and want to display their in view. I find two way to do this - the first: we create action method in controller that get an image from database and return FileContentResult:
public ActionResult GetImage( int id )
{
var imageData = ...get bytes from database...
return File( imageData, "image/jpg" );
}
code in view:
<img src='<%= Url.Action( "GetImage", "image", new { id = ViewData["imageID"] } ) %>' />
The second way is to use HttpHandler:
public void ProcessRequest(HttpContext Context)
{
byte [] b = your image...;
Context.Response.ContentType = "image/jpeg";
Context.Response.BinaryWrite(b);
}
and code in view:
<img src="AlbumArt.ashx?imageId=1" />
The first question is what is the most efficient(work more faster) way to implement this functionality (and why it work faster)?
And the second question - is there is a way to put image in our view directly, when we first call action method to return this view? I mean that in action method we get list of images from database and pass their in view as list, and in view use this code:
<%=Html.Image(Model[i])%>
that code must put image into view directly from model.

There won't be much difference in performance between the two methods. Obviously using an http handler will be the fastest you could get because the request doesn't go through the MVC lifecycle (routing, instantiating a controller, model binding, invoking the action) but I think this is a micro optimization and I would personally use the first approach as it is more adapted in an MVC scenario. If you later realize that this is a bottleneck for your application by performing extensive load tests you could always switch to the http handler approach.
As far as your second question is concerned about the helper, the answer is no, you cannot do this easily. The only possibility is to use the data URI scheme but this is not supported by all browsers. This way if your model has the byte array of the image you could write a helper which renders the following:
<img src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAA..." alt="Red dot" />
The image data is base64 encoded directly into the page. Another drawback is that those images will never be cached and your HTML pages could become very large.

Related

Onclick action doesnt go to the method

here is the code from my cshtml file
<button type="button" class="button js-book-class" onclick="#Url.Action("BookTheClass", "MemberArea", new { ClassID = Aclass.ClassID })">Book Now</button>
and here my function inside MemberAreaController.cs
[HttpPost]
public ContentResult BookTheClass(int ClassID)
{
Class selectedClass= _context.classes.Find(ClassID);
selectedClass.spaceUsed++;
_context.SaveChanges();
return Content(ClassID.ToString());//just for testing
}
This is because you have conflict.
Url.Action generates a href link, which in click, will execute a browser navigation, which means GET request.
While your server BookTheClass action is expected to be called when executing a POST.
The easy fix which in this case is also the not so good solution, is to change your method to [HttpGet] (which i believe is the default) and it will be resolved.
The more accurate solution, will be to create a form element and making the button submit the data, this will acquire you a change only in HTML and not server side.
The reason i think you should stick to Post, is because i believe in the notion that GET should be consider as a query like, and that identical requests should have the same response.
Whereas Post should have the role of Actions which result in side-effects. which in Rest, means Creation. But as general rule of changing a state in the server as a result.

asp.net mvc controller method that returns jpeg given parameter

I would like to create a jpeg on the fly given some data from a database. The data is an array containing values which should be translated into a colour.
A asp.net mvc controller method should return a jpeg on the fly given one parameter.
This should be fairly straight forward. Could someone please point me to some existing code?
Thanks.
Here are a couple of possible options that may help you get started:
I think you will porbably need an handler and then call the handler from your controller.
SO POst
Bob Cravens post
Scott Hansleman's post
If you want this in pure mvc you can do this
Extending MVC: Returning an Image from a Controller Action
Another way is to create a HttpHandler that does that for you
HTTP Handlers for Images in ASP.NET
hope this helps
There is a tutorial on msdn on How to: Encode and Decode a JPEG Image.
Doing that in MVC3 is pretty similar, you just need a action in your controller like this:
public class YourController : Controller
{
[HttpGet]
public ImageResult GetImage(int whatever)
{
stream imageStream = yourJpgFactory.GetImage(whatever)
return (imageStream)
}
}
and in your view
<img src="YourController/GetImage?whatever=42" />

Retrieve URL for Action from Controller

I am calling a Controller Action from a view, within that controller I need to invoke another Action which I will invoke to save the view to a network location as either HTML or Image.
How do I retrieve the URL to an Action from within a Controller. Please note I need the actual URL, this means RedirectionToAction or View() wont work.
Why? I need to pass in a URL which will contain a call to a View. This view will be used to generate an image or HTML document using the System.Windows.Forms.WebBrowser.
.NET 3.5; C#; MVC 1;
I could do something like this, but its dirty ... well it leaves me with that dirty feeling.
using(Html.BeginForm("Action", "MyWorkflowController",
new {
MyId = "bla",
URLToGenerateImage = Url.Action("GenerateImage", "MyWorkflowController")
}))
I ended up using the MvcContrib.UI.BlockRenderer to convert to View to Html instead of generating the image. I proceeded to save the html string to a file system location.
Here is a link for further information
http://www.brightmix.com/blog/how-to-renderpartial-to-string-in-asp-net-mvc/
How about ContentResult - Represents a text result, so you could have
/Controller/GetUrl/id
Public ActionResult GetUrl(int id)
{
// builds url to view (Controller/Image/id || Controller/Html/id)
var url = BuildImageUrl(id);
return ContentResult(url);
}
in view you could have:
GenerateImage

ASP.NET MVC slow image loading through MVC framework?

On some photobook page i want to show appr 20 thumbnails. These thumbnails are programatically loaded from a database. those thumbnails are already resized. When i show them the images load kinda slow. some take 0.5 seconds to load some wait for 2 secons. The database doesn't matter because when i remove the database layer, the performance issue still exists.When i load the same images directly with html the problem the images do load immediately.
Is loading images/files through the mvc framework slow or am i missing something?
This goes too slow
//in html
<img src='/File/Image.jpg' border='0'>
//in controller
public FileResult File(string ID)
{
//database connection removed, just show a pic
byte[] imageFile = System.IO.File.ReadAllBytes(ID);
return new FileContentResult(imageFile,"image/pjpeg");
}
This goes immediately
<img src='/Content/Images/Image.jpg' border='0'>
I had the same issue. I'm using MVC 3. After pulling my hair out, what I discovered is that once you use Session State in your web app, dynamic image loading seems to get clogged, due to the pounding session requests. To fix this, I decorated my controller with:
[SessionState(System.Web.SessionState.SessionStateBehavior.Disabled)]
This disabled the session state for my Photos controller, and the speed returned. If you are using an earlier version of MVC, you'll need to jump through some hoops and create a Controller/Controller factory to do this. See How can I disable session state in ASP.NET MVC?
Hope this helps!
You are adding processing overhead by exposing the image via MVC. When you directly link to an image, it is handled automatically by IIS, rather than the MVC pipeline, so you skip a lot of overhead.
Also, by loading into a byte array, you're loading the full image from disk into memory and then streaming it out, rather than just streaming directly from disk.
You might get slightly better performance with this:
[OutputCache(Duration=60, VaryByParam="*")]
public FileResult File(string ID)
{
string pathToFile;
// Figure out file path based on ID
return File(pathToFile, "image/jpeg");
}
But it's not going to be quite as fast as skipping MVC altogether for static files.
If the above fixes it for you, you'll probably want to mess around with the caching parameters.

Mvc Release Candidate "File" ActionResult

K... I'm doing something obviously wrong. I have a simple page with a file input control on and a submit button. I'm trying out the new "File" ActionResult that was released with the Mvc RC...
All, I want to happen is when the submit button is clicked the selected file is uploaded to the database. This all works fine...
Then, after the page refreshes I want a image to display the resulting image that was uploaded. The issue, is that the image is not rendering... I get the broken image...
This is the portion that is getting the file and sending it back to the view...
var a = Helper.Service.GetAttachmentById(id, MembershipProvider.SecurityTicket);
if (a == null)
{
return View(new ImagePlaceHolderViewData(new { Id = id }));
}
return View(new ImagePlaceHolderViewData(new { Id = a.Id, Image = a, FileContent = File(a.Data, a.ContentType) }));
Then in the view I have a image tag like so...
<img src="<%=Model.FileContent.FileContents %>" />
I have also tried...
<img src="<%=Model.FileContent%>" />
Thoughts..??
FileResult returns the ASCII or binary contents of the file. When you say do the following:
<img src="<%=Model.FileContent.FileContents %>" />
You are attempting to push the binary image data into the src attribute. That will never work, because the src must a URL or a path to an image.
There are several ways of doing what you want, and the most correct solution in this case, would be to create a new controller that returns the binary data like you are attempting, and then you set the src attribute to be the path to correct action on your new controller. E.g:
<img src="/image/result/12345" />
This points to the following (really simple and incomplete) example controller:
public class ImageController : Controller
{
public ActionResult Result(int resultID)
{
// Do stuff here...
return File(..);
}
}
Note that the name I chose for the action is most likely not any good, but it serves its purpose as an example. Hope this was helpful.
I think it's pretty simple: the src attribute of your img tag requires an URL. What you're doing here is just putting the FileStream object in there (which implicitly calls the ToString method on that object). Your resulting html is probably something like this:
<img src="FileStream#1" />
Did you check your html source?
What you probably should do is provide a method which returns the data, and pass the route to that to your view. Your resulting html 'should' then look something like this:
<img src="/Images/View/1" />
So, steps you have to do are:
Create a method on your controller that returns a FileContentResult
Pass your image ID to your view
Use Url.RouteUrl to generate an url which you can put in your img tag, which points to the method returning your image data.
There's also another solution:
<img src="data:image/gif;base64,<%=Convert.ToBase64(Model.FileContent)%>"/>
which works in some browsers, and doesn't in some browsers(IE! of course). But the stable solution is what Thomas J mentioned.

Categories