Forked from rorymurphy/JsonNetValueProviderFactory.cs
Last active
September 21, 2016 21:55
-
-
Save AuthorProxy/a8b2f54b784e55d9b30c to your computer and use it in GitHub Desktop.
ASP.NET MVC Value Provider Factory using JSON.NET
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // http://stackoverflow.com/questions/7109967/using-json-net-as-the-default-json-serializer-in-asp-net-mvc-3-is-it-possible | |
| public class JsonNetHandlerAttribute : ActionFilterAttribute | |
| { | |
| public override void OnActionExecuted(ActionExecutedContext filterContext) | |
| { | |
| var jsonResult = filterContext.Result as JsonResult; | |
| if (jsonResult != null) | |
| { | |
| filterContext.Result = new JsonNetResult<object>(jsonResult.Data) | |
| { | |
| ContentEncoding = jsonResult.ContentEncoding, | |
| ContentType = jsonResult.ContentType | |
| }; | |
| } | |
| base.OnActionExecuted(filterContext); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Newtonsoft.Json; | |
| using System; | |
| using System.Web.Mvc; | |
| namespace Proxy.Mvc.Extensions.ActionResults | |
| { | |
| public class JsonNetResult<T> : JsonResult | |
| { | |
| public JsonNetResult(T data) | |
| { | |
| Data = data; | |
| JsonRequestBehavior = JsonRequestBehavior.AllowGet; | |
| } | |
| public override void ExecuteResult(ControllerContext context) | |
| { | |
| if (context == null) | |
| { | |
| throw new ArgumentNullException(nameof(context)); | |
| } | |
| var response = context.HttpContext.Response; | |
| response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json"; | |
| response.ContentEncoding = ContentEncoding ?? response.ContentEncoding; | |
| response.Write(JsonConvert.SerializeObject(Data, Formatting.None)); | |
| } | |
| public static implicit operator JsonNetResult<T>(T d) | |
| { | |
| return new JsonNetResult<T>(d); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Newtonsoft.Json; | |
| using Newtonsoft.Json.Converters; | |
| using System; | |
| using System.Collections; | |
| using System.Collections.Generic; | |
| using System.Configuration; | |
| using System.Dynamic; | |
| using System.Globalization; | |
| using System.IO; | |
| using System.Web.Mvc; | |
| namespace Proxy.Mvc.Extensions.ValueProviders | |
| { | |
| public class JsonNetValueProviderFactory : ValueProviderFactory | |
| { | |
| public override IValueProvider GetValueProvider(ControllerContext controllerContext) | |
| { | |
| if (controllerContext == null) | |
| { | |
| throw new ArgumentNullException(nameof(controllerContext)); | |
| } | |
| var jsonData = GetDeserializedObject(controllerContext); | |
| if (jsonData == null) | |
| { | |
| return null; | |
| } | |
| var backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); | |
| var backingStoreWrapper = new EntryLimitedDictionary(backingStore); | |
| AddToBackingStore(backingStoreWrapper, string.Empty, jsonData); | |
| return new DictionaryValueProvider<object>(backingStoreWrapper.InnerDictionary, CultureInfo.CurrentCulture); | |
| } | |
| private static object GetDeserializedObject(ControllerContext controllerContext) | |
| { | |
| if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) | |
| { | |
| return null; | |
| } | |
| var streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream); | |
| var jsonReader = new JsonTextReader(streamReader); | |
| if (!jsonReader.Read()) | |
| { | |
| return null; | |
| } | |
| var jsonSerializer = new JsonSerializer(); | |
| jsonSerializer.Converters.Add(new ExpandoObjectConverter()); | |
| object jsonData; | |
| if (jsonReader.TokenType == JsonToken.StartArray) | |
| { | |
| jsonData = jsonSerializer.Deserialize<List<ExpandoObject>>(jsonReader); | |
| } | |
| else | |
| { | |
| jsonData = jsonSerializer.Deserialize<ExpandoObject>(jsonReader); | |
| } | |
| return jsonData; | |
| } | |
| private static void AddToBackingStore(EntryLimitedDictionary backingStore, string prefix, object value) | |
| { | |
| var d = value as IDictionary<string, object>; | |
| if (d != null) | |
| { | |
| foreach (var entry in d) | |
| { | |
| AddToBackingStore(backingStore, MakePropertyKey(prefix, entry.Key), entry.Value); | |
| } | |
| return; | |
| } | |
| var l = value as IList; | |
| if (l != null) | |
| { | |
| for (var i = 0; i < l.Count; i++) | |
| { | |
| AddToBackingStore(backingStore, MakeArrayKey(prefix, i), l[i]); | |
| } | |
| return; | |
| } | |
| backingStore.Add(prefix, value); | |
| } | |
| private static string MakeArrayKey(string prefix, int index) | |
| { | |
| return prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]"; | |
| } | |
| private static string MakePropertyKey(string prefix, string propertyName) | |
| { | |
| return (string.IsNullOrEmpty(prefix)) ? propertyName : prefix + "." + propertyName; | |
| } | |
| private class EntryLimitedDictionary | |
| { | |
| private static readonly int MaximumDepth = GetMaximumDepth(); | |
| private int _itemCount; | |
| internal readonly IDictionary<string, object> InnerDictionary; | |
| public EntryLimitedDictionary(IDictionary<string, object> innerDictionary) | |
| { | |
| InnerDictionary = innerDictionary; | |
| } | |
| public void Add(string key, object value) | |
| { | |
| if (++_itemCount > MaximumDepth) | |
| { | |
| throw new InvalidOperationException("Request too large"); | |
| } | |
| InnerDictionary.Add(key, value); | |
| } | |
| private static int GetMaximumDepth() | |
| { | |
| var appSettings = ConfigurationManager.AppSettings; | |
| { | |
| var valueArray = appSettings.GetValues("aspnet:MaxJsonDeserializerMembers"); | |
| if (valueArray != null && valueArray.Length > 0) | |
| { | |
| int result; | |
| if (int.TryParse(valueArray[0], out result)) | |
| { | |
| return result; | |
| } | |
| } | |
| } | |
| return 1000; | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment