Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

SupportedMediaTypes for output formatters are incorrectly updated with charset data during requests #1836

Closed
rmja opened this issue Jan 17, 2015 · 3 comments
Assignees
Milestone

Comments

@rmja
Copy link

rmja commented Jan 17, 2015

To reproduce, configure a custom JsonOutputFormatter in Startup.cs as follows:

services.AddMvc().Configure<MvcOptions>(options =>
    {
        var formatter = new JsonOutputFormatter();

        formatter.SerializerSettings = new JsonSerializerSettings();
        formatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

        options.OutputFormatters.Clear();
        options.OutputFormatters.Add(formatter);
    });

In the first two requests, the custom settings are used, and the returned properties are camel case. After the first two requests, the settings are not respected, and the default json formatter settings are used.

I have tracked the problem to CanWriteResult() in OutputFormatter.cs. In the first request, the SupportedMediaTypes reads as follows:

SupportedMediaTypes[0].Charset == null
SupportedMediaTypes[0].MediaType == "application/json"
SupportedMediaTypes[0].Charset == null
SupportedMediaTypes[0].MediaType == "text/json"

and

SupportedMediaTypes[0] == SupportedMediaTypes.FirstOrDefault(supportedMediaType => supportedMediaType.IsSubsetOf(contentType))

In the 2nd request, the SupportedMediaTypes reads as follows:

SupportedMediaTypes[0].Charset == "utf-8"
SupportedMediaTypes[0].MediaType == "application/json"
SupportedMediaTypes[1].Charset == null
SupportedMediaTypes[1].MediaType == "text/json"

In this case:

SupportedMediaTypes[1] == SupportedMediaTypes.FirstOrDefault(supportedMediaType => supportedMediaType.IsSubsetOf(contentType))

Note the index change. The first supported media type is not found anymore. From now on the SupportedMediaTypes are fully populated with Charset data, and the custom json formatter is not found by the .FirstOrDefault().

@rynowak
Copy link
Member

rynowak commented Jan 17, 2015

@rmja thanks for the thorough report. It looks like the issue might be in OutputFormatter@192.

            var selectedMediaType = context.SelectedContentType;

            // If content type is not set then set it based on supported media types.
            selectedMediaType = selectedMediaType ?? SupportedMediaTypes.FirstOrDefault();

<skipping over a few lines...>

            context.SelectedEncoding = selectedEncoding;

            // Override the content type value even if one already existed.
            selectedMediaType.Charset = selectedEncoding.WebName;

selectedEncoding might refer to one of the values from SupportedMediaTypes. We should be making a copy before mutating it.

@yishaigalatzer
Copy link
Contributor

@rmja can you please clarify what your action code looks like?

I assume you are calling return Json(model) which is when we might fallback to the default json formatter?

In that case I assume you can just return the model directly (or return ObjectResult(model))

@yishaigalatzer yishaigalatzer added this to the 6.0.0-rc1 milestone Jan 19, 2015
@rmja
Copy link
Author

rmja commented Jan 19, 2015

@yishaigalatzer correct. I am calling Json(model). I was not aware of new ObjectResult(model). It does not produce the same error.

kichalla added a commit that referenced this issue Jan 20, 2015
…y updated with charset data during requests
kichalla added a commit that referenced this issue Jan 20, 2015
…y updated with charset data during requests
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants