filipw / Strathweb.CacheOutput

ASP.NET Web API CacheOutput - library to allow you to cache the output of ApiControllers
Other
882 stars 253 forks source link

The format of value 'application/json; charset=utf-8' is invalid. #147

Open DaveMiscampbell opened 9 years ago

DaveMiscampbell commented 9 years ago

I'm using this library and it's performing excellently however, I keep seeing the below exception in my server logs. Is there anything I can do to prevent this or is it a known issue?

Here is the stack trace:

at System.Net.Http.Headers.MediaTypeHeaderValue.CheckMediaTypeFormat(String mediaType, String parameterName)
at System.Net.Http.Headers.MediaTypeHeaderValue..ctor(String mediaType)
at WebApi.OutputCache.V2.CacheOutputAttribute.OnActionExecuting(HttpActionContext actionContext)
at System.Web.Http.Filters.ActionFilterAttribute.OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()

Looking in the source code I think it could be line 179 in CacheOutputAttribute

var contenttype = _webApiCache.Get<MediaTypeHeaderValue>(cachekey + Constants.ContentTypeKey) ?? new MediaTypeHeaderValue(cachekey.Split(new[] { ':' }, 2)[1].Split(';')[0]);

but I'm not sure. Does anyone have any advice?

geoffreys commented 9 years ago

We are seeing this same issue on frequent basis since updating to .net 4.5.2, mvc5 in the project (from net 4.0, mvc 3). At this stage we are going to remove the library as the problem is pretty fatal

tynor88 commented 8 years ago

Anyone found a work around for this? We are also gettng this error very often.

Schenz commented 7 years ago

I think it is probably related to this issue: https://github.com/filipw/Strathweb.CacheOutput/pull/142

However, I still have no clue on what to do to mitigate it. It makes sense that there can be a problem if the cache expires in the middle of a request, but how do you gracefully handle that issue, and where?

tynor88 commented 7 years ago

@Schenz seems the bug was already fixed long time ago in this commit https://github.com/filipw/Strathweb.CacheOutput/pull/142/commits/218fc9074ebdebde3e6add2278b4cb6940774fb1

But was it never merged into master and released?

Schenz commented 7 years ago

It does appear to be merged in GitHub, but perhaps the nuget package is out of date?

@filipw can you speak to how current the NuGet package is in reference to this merge? Looks like this was merged on July 22, 2015 and latest NuGet is July 11, 2016 so it should be there, but issue is still happening.

jonsagara commented 7 years ago

It looks like the original exception is fixed, but it still throws exceptions in certain instances. I can get it to fail when one of the action arguments is a DateTime whose value is rendered with ':' characters when creating the cache key. This is problematic because the ':' character is also used to separate the media type from the rest of the cache key.

Example of a cache key without colons in the action argument values:

var cachekey = "mynamespace.foocontroller.baraction-userId=1&name=Bill:application/json; charset=utf-8";
var mediaType = cachekey.Split(new[] { ':' }, 2)[1].Split(';')[0];

// Ouput: application/json
Console.WriteLine(mediaType);

// Parses "application/json" correctly
var header = new MediaTypeHeaderValue(mediaType);

Example of a cache key containing one or more colons in the action argument values:

var cachekey = "mynamespace.foocontroller.baraction-userId=1&name=Bill&dob=1980-01-01T08:00:00:application/json; charset=utf-8";
var mediaType = cachekey.Split(new[] { ':' }, 2)[1].Split(';')[0];

// Output: 00:00:application/json
Console.WriteLine(mediaType);

// Can't parse "00:00:application/json"; throws an exception: "The format of value '00:00:application/json' is invalid."
try { new MediaTypeHeaderValue(mediaType); }
catch (Exception ex) { Console.WriteLine(ex); }

Perhaps the solution is to change the separator from ':' to a nonsense string of characters with a low probability of occurring naturally.

tynor88 commented 7 years ago

Good find @jonsagara . Sounds reasonable to me to change the seperator to another charactar and make a unit test for it. Perhaps you can make a new branch, as it seems the original author of this library is not merging in PR's anymore.

Schenz commented 7 years ago

If PRs are not being merged anymore, how do we get this fix applied and pushed to nuget. I do not want to have to manage my own version of this library...

tynor88 commented 7 years ago

@Schenz There is no other way unless someone decides to maintain a fork of this project or the original author adds some new contributors to the current one. Unfortunately :-1:

filipw commented 7 years ago

Perhaps the solution is to change the separator from ':' to a nonsense string of characters with a low probability of occurring naturally.

That would be a good idea, for example a pipe | or even a double pipe || should be obscure enough.