我正在寻找一种方法来“解包”已发布到MVC Core服务的JSON。比方说,我有以下方法:
[HttpPost]
public dynamic SayHello(string FirstName, string SecondName)
{
return $"Hello {FirstName} {SecondName} !";
}
我发布了以下JSON:
{
"FirstName":"Joe",
"SecondName": "Bloggs"
}
我希望得到Hello Joe Bloggs !
的响应,但我似乎找不到一种简单的方法来将JSON对象解包到方法的属性中。
我知道正确的解决方案是让HelloModel
包含这两个属性,打一个[FromBody]
属性,但由于这个原因,这是不可能的。
答案 0 :(得分:3)
这是另一个(略微复杂的)选项。您可以创建自己的动作过滤器来拦截请求,并根据自己决定JSON的值填充参数。例如:
public class JsonToParametersAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
var stream = filterContext.HttpContext.Request.Body;
using (var sr = new StreamReader(stream))
using (var jsonTextReader = new JsonTextReader(sr))
{
var serializer = new JsonSerializer();
var body = serializer.Deserialize<JObject>(jsonTextReader);
if (body == null) return;
foreach (var parameter in filterContext.ActionDescriptor.Parameters)
{
var jsonProperty = body.Properties().SingleOrDefault(p => p.Name == parameter.Name);
if (jsonProperty != null)
{
var param = filterContext.ActionDescriptor.Parameters.OfType<ControllerParameterDescriptor>().FirstOrDefault(e => e.Name == parameter.Name);
if (param == null)
{
continue;
}
if (!filterContext.ActionArguments.ContainsKey(parameter.Name))
{
object value;
try
{
value = jsonProperty.Value.ToObject(param.ParameterInfo.ParameterType);
}
catch (Exception)
{
value = GetDefault(param.ParameterInfo.ParameterType);
}
filterContext.ActionArguments.Add(parameter.Name, value);
}
}
}
}
}
private static object GetDefault(Type type)
{
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
}
现在用这个新属性装饰你的动作方法:
[HttpPost]
[JsonToParameters]
public dynamic SayHello(string FirstName, string SecondName)
{
return $"Hello {FirstName} {SecondName} !";
}