/// <summary> /// Executes content negotiation on current <see cref="HttpResponse"/>, utilizing an accepted media type if possible and defaulting to "application/json" if none found. /// </summary> /// <param name="response">Current <see cref="HttpResponse"/></param> /// <param name="obj">View model</param> /// <param name="cancellationToken"><see cref="CancellationToken"/></param> /// <returns><see cref="Task"/></returns> public static async Task Negotiate(this HttpResponse response, object obj, CancellationToken cancellationToken = default) { var negotiators = response.HttpContext.RequestServices.GetServices <IResponseNegotiator>(); IResponseNegotiator negotiator = null; MediaTypeHeaderValue.TryParseList(response.HttpContext.Request.Headers["Accept"], out var accept); if (accept != null) { var ordered = accept.OrderByDescending(x => x.Quality ?? 1); foreach (var acceptHeader in ordered) { negotiator = negotiators.FirstOrDefault(x => x.CanHandle(acceptHeader)); if (negotiator != null) { break; } } } if (negotiator == null) { negotiator = negotiators.FirstOrDefault(x => x.CanHandle(new MediaTypeHeaderValue("application/json"))); } await negotiator.Handle(response.HttpContext.Request, response, obj, cancellationToken); }