Web Api – Media Type Formatter – Notlar
Merhabalar ,
Media Type Formatter verimizi kullanıcılara hangi formatta sunacağımızı belirleyeceğimiz sanal bir sınıftır , yani bütün media typpe formatırlar bu sanal sınıftan miras alarak türemiştir
- JsonMediaTypeFormatter
- XmlMediaTypeFormatter
- FormUrlEncodeMediaTypeFormatter
Default olarak Asp.Net Web Api de gelmektedir , istersek kendimizde yeni bir Media Type Formatter tanımlayabiliriz.
Örneğin Api mizde xml desteğini kaldırmak istesek App_Start kalsöründe bulunan WebApiConfig.cs dosyamızda aşşağıdaki kod satısını eklemeliyiz.
using : using System.Net.Http.Formatting;
code : config.Formatters.Remove(config.Formatters.XmlFormatter);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Net.Http.Formatting;
namespace WebApiApp
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Remove(config.Formatters.XmlFormatter);
}
}
}
Web apimize text/html tipinde bir accept istek olduğunda json formatında response dönmesi için config ayarı ekleme.
config satırımız : config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue(“text/html”));
json formatımızın desteklediği media type header değerlerine text/html eklemiş olduk
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Net.Http.Formatting;
namespace WebApiApp
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));
}
}
}
fakat bu şekilde bir kullanımda text/html olarak gelen bir accept te response olarak json döncektir ama header bilgisinin content-type kısmı application/json olması gerekirken text/html yazacaktır.

Bunun önüne geçmek için kendi MediaTypeFormatter ımız yazıp config ayarlarırında tanımlayacağız.
Öncelikle projemize MyJsonFormatter adında bir class ekledim :
kodlar:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Web;
namespace WebApiApp
{
public class MyJsonFormatter : JsonMediaTypeFormatter
{
public MyJsonFormatter()
{
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
}
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.ContentType = new MediaTypeHeaderValue("application/json");
}
}
}

oluşturduğumuz class a JsonMediaTypeFormatter sınıfını implement ettik , sonrasında constructor ımızda bi önceki örneğimizde yaptığımız gibi text/html content-type ına destek verdiğimizi tanımladık.
sonrasında JsonMediaTypeFormatter a ait olan SetDefaultContentHeaders methodunu override ederek header content-type ını her zaman application/json olarak dönmesini sağladık.
bu işlemlerden sonra oluşturduğumuz MediaTypeFormat sınıfımız WebApiConfig.cs dosyamıza tanımlamamız kaldı.
config.Formatters.Add(new MyJsonFormatter());
şeklinde kodumuzu eklememiz yeterli olacaktır .
WebApiConfig.cs :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Net.Http.Formatting;
namespace WebApiApp
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Add(new MyJsonFormatter());
}
}
}
Artık Accept : “text/html” olarak gelen requestler de json olarak sonucumuz döncek ve header content-type bilgisinde “application/json” olacaktır.

Örnek: CSV Formater :
Apimizde response olarak csv formatın sonucu almak için örnek csv formater ve kullanımı :
CSVFormatter.cs
using Egitim_ContentNavigation.Entity;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
namespace WebApiApp
{
public class CSVFormatter : MediaTypeFormatter
{
public CSVFormatter()
{
this.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/csv"));
}
public CSVFormatter(MediaTypeMapping mediaTypeMapping):this()
{
this.MediaTypeMappings.Add(mediaTypeMapping);
}
public override bool CanReadType(Type type)
{
return false;
}
public override bool CanWriteType(Type type)
{
//List mi ?
return type.GetInterfaces().Any(x => x == typeof(IEnumerable));
}
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.Add("Content-Disposition", "attachment; filename=" + Guid.NewGuid().ToString() + ".csv");
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)
{
myWriteStream(type, value, writeStream);
var task = new TaskCompletionSource<int>();
task.SetResult(0);
return task.Task;
}
private void myWriteStream(Type type, object value, Stream stream)
{
Type itemType = type.GetGenericArguments()[0];
StringWriter _stringWriter = new StringWriter();
_stringWriter.WriteLine(
string.Join<string>(
",", itemType.GetProperties().Select(x => x.Name)
)
);
foreach (var obj in (IEnumerable<object>)value)
{
var vals = obj.GetType().GetProperties().Select(
pi => new {
Value = pi.GetValue(obj, null)
}
);
string _valueLine = string.Empty;
foreach (var val in vals)
{
if (val.Value != null)
{
var _val = val.Value.ToString();
if (_val.Contains("\r"))
_val = _val.Replace("\r", " ");
if (_val.Contains("\n"))
_val = _val.Replace("\n", " ");
_valueLine = string.Concat(_valueLine, _val, ",");
}
else
{
_valueLine = string.Concat(_valueLine, string.Empty, ",");
}
}
_stringWriter.WriteLine(_valueLine.TrimEnd(','));
}
var streamWriter = new StreamWriter(stream);
streamWriter.Write(_stringWriter.ToString());
streamWriter.Close();
}
}
}
sonrasında formatter tanımlamasını yapmamız gerekce , WebApiConfgi.cs te yapabileceğimiz gibi Global.asax dosyasında da bu tanımlamayı yapabiliriz.
Global.asax :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting;
using System.Web;
using System.Web.Http;
using System.Web.Routing;
namespace Egitim_ContentNavigation
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.Formatters.Add(new CSVFormatter(new QueryStringMapping("format", "csv","text/csv")));
//url?format=csv
}
}
}
kullanımı : wepapi url parametre olarak format=csv yazdığımızda dönen sonuç eğer IEnumerable ise csv formatında sonuç verecektir. (IEnumerable kontrolü CSVFormatter.cs dosyasında CanWriteType metodunda yapılmıştır. )
Bu şekilde csv formatında response alınabilir.

