I want to create an image handler, but i am torn between using Web API 2
or just a normal Generic Handler (ashx)
I have implemented both in the past, but which one is the most correct one. I found an old SO post LINK but is it still really relevant?
WebApi is fully capable and I prefer it. The other answer is right that JSON and XML are default, but you can add your own MediaFormatter and serve any content type for any model. This allows you to perform content negotiation and provide different content based on the Accept header or file extension. Let's pretend our model is a "User". Imagine asking for a "User" as json, xml, jpg, pdf. With WebApi, we can use file extensions or the Accept header and ask for /Users/1 or Users/1.json for JSON, Users/1.jpg for jpg, Users/1.xml for xml, /Users/1.pdf for pdf, etc. All of these could also just be /Users/1 with different Accept headers with quality so your clients could ask for Users/1 with an Accept header asking for jpg first, but fall back to png.
Here is an example of how to create a formatter for .jpg.
public class JpegFormatter : MediaTypeFormatter
{
public JpegFormatter()
{
//this allows a route with extensions like /Users/1.jpg
this.AddUriPathExtensionMapping(".jpg", "image/jpeg");
//this allows a normal route like /Users/1 and an Accept header of image/jpeg
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/jpeg"));
}
public override bool CanReadType(Type type)
{
//Can this formatter read binary jpg data?
//answer true or false here
return false;
}
public override bool CanWriteType(Type type)
{
//Can this formatter write jpg binary if for the given type?
//Check the type and answer. You could use the same formatter for many different types.
return type == typeof(User);
}
public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content,
TransportContext transportContext)
{
//value will be whatever model was returned from your controller
//you may need to check data here to know what jpg to get
var user = value as User;
if (null == user)
{
throw new NotFoundException();
}
var stream = SomeMethodToGetYourStream(user);
await stream.CopyToAsync(writeStream);
}
}
Now we need to register our formatter (typically App_Start/WebApiConfig.cs)
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
//typical route configs to allow file extensions
config.Routes.MapHttpRoute("ext", "{controller}/{id}.{ext}");
config.Routes.MapHttpRoute("default", "{controller}/{id}", new { id = RouteParameter.Optional });
//remove any default formatters such as xml
config.Formatters.Clear();
//order of formatters matter!
//let's put JSON in as the default first
config.Formatters.Add(new JsonMediaTypeFormatter());
//now we add our custom formatter
config.Formatters.Add(new JpegFormatter());
}
}
And finally, our controller
public class UsersController : ApiController
{
public IHttpActionResult Get(int id)
{
var user = SomeMethodToGetUsersById(id);
return this.Ok(user);
}
}
Your controller will not have to change as you add different formatters. It simply returns your model and then formatters kick in later in the pipeline. I love formatters as it provides such a rich api. You can read more about formatters on the WebApi website.
The correct one is ashx the reason is the content type. If you use Web Api the content type a.k.a media formatter(format) of your response is the one defined for all your services meaning JSON, XML or oData.
//Global Asax, Web Api register methods is used to defined WebApi formatters
config.Formatters.Insert(0, new System.Net.Http.Formatting.JsonMediaTypeFormatter());
However an image is a binary therefore you need to send the image in its original format and not as JSON or XML
response.AddHeader("content-type", "image/png");
response.BinaryWrite(imageContent);
response.Flush();
That is why the ashx is the right tool for that job.
One additional advantage is that you have more control over your output without the need to code a new "formatter"(the way to make WebApi to resolve this issue) for each image type that you want to return by doing something like in Ashx file:
var png = Image.FromFile("some.png");
png.Save("a.gif", var png = Image.FromFile("some.png");
png.Save("a.gif", ImageFormat.Gif); //Note you can save the new image into a MemoryStream to return it later in the same method.
And you have wide variety of types to play with:
https://msdn.microsoft.com/en-us/library/system.drawing.imaging.imageformat(v=vs.110).aspx
Important: It is clear for all of us that both WebApi and Ashx can return images. I am not saying in any way that you can't achieve this with WebApi all I am saying is why I believe Ashx is the right choice.
I am a big fan of flexibility and customization. I personally would go for httpHandler. So to answer your question, it really depends on your requirements.
First thing WebAPI is the result of evolution all the way from http (GET/POST) calls to web services and the need of being able to transfer data in less cost as opposed to web services. HttpHandlers utilized same concept long time before web apis. Basically web apis are nothing but a http page without its user interface (if you want to).
Few things need to know before choosing HttpHandler or Web Api
There might more comparison (As a manager I think from management side as well and not completely technical perspective) so you may have to weigh your options and decide what to do. Since handler file is anyway foundation of web API, I would say it gives more power to developer than web api does. just like a http socket would do more than httphandler.
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