📜 ⬆️ ⬇️

Displaying pictures in ASP .NET MVC

Technologies: .NET Framework 3.5, ASP .NET MVC
Languages: Visual Basic .NET, C #

Quite often, when developing web applications, it is required to give the user data in a format other than html. For example, display a reduced copy of the image (ThumbImage), or issue protected data from the database. In ASP .NET WebForms, you can use Handlers (handlers) or regular ASPX pages for this purpose. In ASP .NET MVC, the situation has changed a bit. Although of course, as before, nothing is forbidden to use handlers. Unless, you may need a rule for Routing , such as: routes.IgnoreRoute ("{resource} .ashx") .
In this review, we will consider an example of displaying images using ASP .NET MVC, however, the described approach can be used to output data of absolutely any format.


ActionResult


')
As it is known (I hope that it is known), the result of the execution of any action (action) of the controller (controller) is an ActionResult. ActionResult is a base class from which all classes inherit, ultimately forming content to be rendered to the client. For example: ViewResult, JsonResult, ContentResult, RedirectResult, etc. By itself, the ActionResult class cannot be used, it can only be inherited from it, and due to this, the list of results of controller actions is limited only by the imagination of developers.
The formation of data for output occurs in the ExecuteResult method.

ImageResult



Actually, in order for the controller to provide the client with an image, you need to write your class inherited from ActionResult. Logically, its name should be ImageResult, but this is up to you.

VB .NET:
Public Class ImageResult
Inherits ActionResult
End Class


C #:
public class ImageResult: ActionResult
{ }


As I said, the content is formed in the ExecuteResult method, however, before you do this, you need to get the source material. In other words, transfer to the class the information on the basis of which the final data will be formed. In the case of images, it will most universally transmit to the class Stream. You will also need to transmit information about the type of content (Content-Type), so that search engines do not get scared, and browsers do not guess the coffee grounds and, as a result, do not hurt the user's psyche. To do this, you will have to write a couple of relevant properties, and to complete the picture, prescribe a constructor.

VB .NET:
Private _ImageStream As Stream
Private _ContentType As String = ""

Public Property ImageStream() As Stream
Get
Return _ImageStream
End Get
Set ( ByVal value As Stream)
_ImageStream = value
End Set
End Property

Public Property ContentType() As String
Get
Return _ContentType
End Get
Set ( ByVal value As String )
_ContentType = value
End Set
End Property

Public Sub New( ByVal imageStream As Stream, ByVal contentType As String )
If imageStream Is Nothing Then Throw New ArgumentNullException("imageStream")
If String .IsNullOrEmpty(contentType) Then Throw New ArgumentNullException("contentType")
_ImageStream = imageStream
_ContentType = contentType
End Sub


C #:
private static Stream _ImageStream;
private static string _ContentType = "";

public static Stream ImageStream
{
get { return _ImageStream; }
set { _ImageStream = value; }
}

public static string ContentType
{
get { return _ContentType; }
set { _ContentType = value; }
}

public ImageResult(Stream imageStream, string contentType)
{
if (imageStream == null) throw new ArgumentNullException("imageStream");
if ( String .IsNullOrEmpty(contentType)) throw new ArgumentNullException("contentType");
_ImageStream = imageStream;
_ContentType = contentType;
}


To complete this, you need to write code for the ExecuteResult method, which will display an image based on the data received.

VB .NET:
Public Overrides Sub ExecuteResult( ByVal context As System.Web.Mvc.ControllerContext)
If context Is Nothing Then Throw New ArgumentNullException("context")
Dim Response As HttpResponseBase = context.HttpContext.Response
Response.ContentType = _ContentType
Dim buffer(1024) As Byte
Do
Dim read As Integer = _ImageStream.Read(buffer, 0, buffer.Length)
If read = 0 Then Exit Do
Response.OutputStream.Write(buffer, 0, read)
Loop
Response.End()
End Sub


C #:
public static override void ExecuteResult(System.Web.Mvc.ControllerContext context)
{
if (context == null) throw new ArgumentNullException("context");
HttpResponseBase Response = context.HttpContext().Response;
Response.ContentType = _ContentType;
byte [] buffer = new byte [1024];
do
{
int read = _ImageStream.Read(buffer, 0, buffer.Length);
if (read == 0) { break ; }
Response.OutputStream.Write(buffer, 0, read);
} while ( true );
Response.End();
}


Now the result of the action of any controller can be ImageResult.

VB .NET:
Return New ImageResult(System.IO.File.OpenRead("C:\kbyte.ru.gif"), "image/gif")

C #:
return new ImageResult(System.IO.File.OpenRead("C:\\kbyte.ru.gif"), "image/gif");

Extension



For complete happiness, you can write an extension for System.Web.Mvc.Controller. For this, you can create a regular module, and a static class with a name, for example, ControllerExtensions , and write some convenient functions in it that will return ImageResult.

Note. Remember to import the System.Runtime.CompilerServices namespace .

VB .NET:
Public Module ControllerExtensions

<Extension()> _
Public Function Image( ByVal controller As System.Web.Mvc.Controller, ByVal imageStream As Stream, ByVal contentType As String ) As ImageResult
Return New ImageResult(imageStream, contentType)
End Function

<Extension()> _
Public Function Image( ByVal controller As System.Web.Mvc.Controller, ByVal imageBytes() As Byte , ByVal contentType As String ) As ImageResult
Return New ImageResult( New MemoryStream(imageBytes), contentType)
End Function

<Extension()> _
Public Function Image( ByVal controller As System.Web.Mvc.Controller, ByVal fileName As String , ByVal contentType As String ) As ImageResult
Return New ImageResult(System.IO.File.OpenRead("C:\kbyte.ru.gif"), contentType)
End Function

End Module


C #:
public static class ControllerExtensions
{

[Extension()]
public static ImageResult Image(System.Web.Mvc.Controller controller, Stream imageStream, string contentType)
{
return new ImageResult(imageStream, contentType);
}

[Extension()]
public static ImageResult Image(System.Web.Mvc.Controller controller, byte [] imageBytes, string contentType)
{
return new ImageResult( new MemoryStream(imageBytes), contentType);
}

[Extension()]
public static ImageResult Image(System.Web.Mvc.Controller controller, string fileName, string contentType)
{
return new ImageResult(System.IO.File.OpenRead("C:\\kbyte.ru.gif"), contentType);
}

}


Now in the controllers you can use the prescribed functions, for example:

VB .NET:
Return Image(System.IO.File.OpenRead("C:\kbyte.ru.gif"), "image/gif")

C #:
return Image(System.IO.File.OpenRead("C:\\kbyte.ru.gif"), "image/gif");

Afterword



Inheriting from the ActionResult class, you can display data of absolutely any format. What code functionality will be registered in the ExecuteResult method depends entirely on your imagination. As for images, if you will display images from files, I would recommend pre-reading them (making a copy, for example, into an array of bytes), so as not to accidentally lock files if you later need to perform any manipulations on them (above files) (move, delete).

-
Nemiro Alexey,
06/29/2009

Source: https://habr.com/ru/post/63149/


All Articles