原文:http://blog.darkthread.net/post-2015-05-11-post-json-to-mvc-action-again.aspx
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)
{
}
}
}
eg:
public ActionResult PostJson2(
[Afet.Mvc.FromBody]ArgObject args)
{
return new Newtonsoft.JsonResult.JsonResult()
{
Data = args
};
}
public ActionResult PostJson3(
[Afet.Mvc.FromPartialBody]string Name,
[Afet.Mvc.FromPartialBody]SubArgObject SubArg
)
{
return new Newtonsoft.JsonResult.JsonResult()
{
Data = new
{
ParamName = Name,
ParamSubArg = SubArg
}
};
}
public class ArgObject
{
public string Name { get; set; }
public SubArgObject SubArg { get; set; }
}
public class SubArgObject
{
public string PropA { get; set; }
[JsonProperty("PropX")]
public string PropB { get; set; }
[JsonIgnore]
public string PropC { get; set; }
}
参考资料: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api