/// <summary> /// As a <see cref="IResourceFilter"/>, this filter looks at the request and rejects it before going ahead if /// 1. The format in the request does not match any format in the map. /// 2. If there is a conflicting producesFilter. /// </summary> /// <param name="context">The <see cref="ResourceExecutingContext"/>.</param> public void OnResourceExecuting(ResourceExecutingContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var format = GetFormat(context); if (format == null) { // no format specified by user, so the filter is muted return; } var contentType = _options.FormatterMappings.GetMediaTypeMappingForFormat(format); if (contentType == null) { _logger.UnsupportedFormatFilterContentType(format); // no contentType exists for the format, return 404 context.Result = new NotFoundResult(); return; } // Determine media types this action supports. var responseTypeFilters = context.Filters.OfType <IApiResponseMetadataProvider>(); var supportedMediaTypes = new MediaTypeCollection(); foreach (var filter in responseTypeFilters) { filter.SetContentTypes(supportedMediaTypes); } // Check if support is adequate for requested media type. if (supportedMediaTypes.Count == 0) { _logger.ActionDoesNotExplicitlySpecifyContentTypes(); return; } // We need to check if the action can generate the content type the user asked for. That is, treat the // request's format and IApiResponseMetadataProvider-provided content types similarly to an Accept // header and an output formatter's SupportedMediaTypes: Confirm action supports a more specific media // type than requested e.g. OK if "text/*" requested and action supports "text/plain". if (!IsSuperSetOfAnySupportedMediaType(contentType, supportedMediaTypes)) { _logger.ActionDoesNotSupportFormatFilterContentType(contentType, supportedMediaTypes); context.Result = new NotFoundResult(); } }