using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Web.Http.Controllers;
using System.Web.Http.Validation;
using System.Web.Mvc;
namespace Afet.Mvc
{
[AttributeUsage(AttributeTargets.Parameter)]
public class FromBodyAttribute : CustomModelBinderAttribute
{
protected bool DictionaryMode = false;
public FromBodyAttribute(bool dictionaryMode = false)
{
this.DictionaryMode = dictionaryMode;
}
public override IModelBinder GetBinder()
{
return new JsonNetBinder(DictionaryMode);
}
public class JsonNetBinder : IModelBinder
{
private bool DictionaryMode;
public JsonNetBinder(bool dictionaryMode)
{
this.DictionaryMode = dictionaryMode;
}
const string VIEW_DATA_STORE_KEY = "___BodyJsonString";
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
//Verify content-type
if (!controllerContext.HttpContext.Request.
ContentType.ToLower().Contains("json"))
return null;
var stringified = controllerContext.Controller
.ViewData[VIEW_DATA_STORE_KEY] as string;
if (stringified == null)
{
var stream = controllerContext.HttpContext.Request.InputStream;
using (var sr = new StreamReader(stream))
{
stream.Position = 0;
stringified = sr.ReadToEnd();
controllerContext.Controller
.ViewData.Add(VIEW_DATA_STORE_KEY, stringified);
}
}
if (string.IsNullOrEmpty(stringified)) return null;
try
{
if (DictionaryMode)
{
//Find the property form JObject converted from body
var dict = JsonConvert.DeserializeObject<JObject>(stringified);
if (dict.Property(bindingContext.ModelName) == null)
return null;
//Convert the property to ModelType
return dict.Property(bindingContext.ModelName).Value
.ToObject(bindingContext.ModelType);
}
else
{
//Convert the whole body to ModelType
return JsonConvert.DeserializeObject(stringified,
bindingContext.ModelType);
}
}
catch
{
}
return null;
}
}
}
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class FromPartialBodyAttribute : FromBodyAttribute
{
public FromPartialBodyAttribute()
: base(true)
{
}
}
}