The MediaTypeFormatter is the wrong layer to close the session at because this behavior really has nothing to do with the particular formatter you're using. Here's what I recommend doing:
Derive from HttpContent and create a class that derives from ObjectContent. Override the SerializeToStreamAsync implementation to await the base implementation's SerializeToStreamAsync then close the session:
public class SessionClosingObjectContent : ObjectContent { private Session _session; public SessionClosingObjectContent(Type type, object value, MediaTypeFormatter formatter, Session session) : base(type, value, formatter) { _session = session; } protected async override Task SerializeToStreamAsync(Stream stream, TransportContext context) { await base.SerializeToStreamAsync(stream, context); // Close the session and anything else you need to do _session.Close(); } }
Now in your action filter, instead of closing the session, you want to replace the response Content with your new class that closes the session:
public class SessionManagement : ActionFilterAttribute { public SessionManagement() { SessionFactory = WebApiApplication.SessionFactory; } private ISessionFactory SessionFactory { get; set; } public override void OnActionExecuting(HttpActionContext actionContext) { var session = SessionFactory.OpenSession(); CurrentSessionContext.Bind(session); session.BeginTransaction(); } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { var session = SessionFactory.GetCurrentSession(); var response = actionExecutedContext.Response; if (response.Content != null) { ObjectContent objectContent = response.Content as ObjectContent; if (objectContent != null) { response.Content = new SessionClosingObjectContent(objectContent.ObjectType, objectContent.Value, objectContent.Formatter, session); foreach (KeyValuePair<string, IEnumerable<string>> header in objectContent.Headers) { response.Content.Headers.TryAddWithoutValidation(header.Key, header.Value); } } } } }
You could also choose instead to return an HttpResponseMessage with your new Content directly from your controller code wherever you need it.