“Unwrapping”发布了JSON

时间:2017-08-16 10:33:04

标签: c# asp.net-mvc asp.net-core-mvc

我正在寻找一种方法来“解包”已发布到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]属性,但由于这个原因,这是不可能的。

1 个答案:

答案 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} !";
}