Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带下划线的MVC 3模型绑定_C#_Asp.net Mvc_Json_Asp.net Mvc 3_Model Binding - Fatal编程技术网

C# 带下划线的MVC 3模型绑定

C# 带下划线的MVC 3模型绑定,c#,asp.net-mvc,json,asp.net-mvc-3,model-binding,C#,Asp.net Mvc,Json,Asp.net Mvc 3,Model Binding,我正在发布带有下划线(如此)变量名的json,并试图绑定到一个camelcased(如此)模型,但无法绑定值 我知道我可以编写一个定制的模型绑定器,但由于下划线约定如此普遍,我希望已经存在一个解决方案 我试图发布的操作/模型是: /* in controller */ [HttpPost] public ActionResult UpdateArgLevel(UserArgLevelModel model) { // do something with the data } /* mo

我正在发布带有下划线(
如此
)变量名的json,并试图绑定到一个camelcased(
如此
)模型,但无法绑定值

我知道我可以编写一个定制的模型绑定器,但由于下划线约定如此普遍,我希望已经存在一个解决方案

我试图发布的操作/模型是:

/* in controller */
[HttpPost]
public ActionResult UpdateArgLevel(UserArgLevelModel model) {
    // do something with the data
}

/* model */
public class UserArgLevelModel {
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string Surname { get; set; }
    public int ArgLevelId { get; set; }
}
json数据如下所示:

{
    id: 420007,
    first_name: "Marc",
    surname: "Priddes",
    arg_level_id: 4
}
(不幸的是,我无法更改json或模型的命名)

您可以开始编写一个
ContractResolver

public class DeliminatorSeparatedPropertyNamesContractResolver :
    DefaultContractResolver
{
    private readonly string _separator;

    protected DeliminatorSeparatedPropertyNamesContractResolver(char separator)
        : base(true)
    {
        _separator = separator.ToString();
    }

    protected override string ResolvePropertyName(string propertyName)
    {
        var parts = new List<string>();
        var currentWord = new StringBuilder();

        foreach (var c in propertyName)
        {
            if (char.IsUpper(c) && currentWord.Length > 0)
            {
                parts.Add(currentWord.ToString());
                currentWord.Clear();
            }
            currentWord.Append(char.ToLower(c));
        }

        if (currentWord.Length > 0)
        {
            parts.Add(currentWord.ToString());
        }

        return string.Join(_separator, parts.ToArray());
    }
}
public class SnakeCasePropertyNamesContractResolver :
    DeliminatorSeparatedPropertyNamesContractResolver
{
    public SnakeCasePropertyNamesContractResolver() : base('_') { }
}
然后,您可以编写自定义属性来装饰控制器动作:

public class JsonFilterAttribute : ActionFilterAttribute
{
    public string Parameter { get; set; }
    public Type JsonDataType { get; set; }
    public JsonSerializerSettings Settings { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {    
        if (filterContext.HttpContext.Request.ContentType.Contains("application/json"))
        {
            string inputContent;
            using (var reader = new StreamReader(filterContext.HttpContext.Request.InputStream))
            {
                inputContent = reader.ReadToEnd();
            }

            var result = JsonConvert.DeserializeObject(inputContent, JsonDataType, Settings ?? new JsonSerializerSettings());
            filterContext.ActionParameters[Parameter] = result;
        }
    }
}
最后:

[JsonFilter(Parameter = "model", JsonDataType = typeof(UserArgLevelModel), Settings = new JsonSerializerSettings { ContractResolver = new SnakeCasePropertyNamesContractResolver() })]
public ActionResult UpdateArgLevel(UserArgLevelModel model) {
{
    // model is deserialized correctly!
}

补充说,这真的没什么令人兴奋的…为什么不改变JSON以匹配模型属性名呢?对不起,忘了提到这一点!(写了一次问题,但意外地删除了它)。我正在使用一个javascript库来生成post请求,它使用下划线命名约定,不幸的是,我无法更改它。您会发现,像DOBProperty这样的属性名称的序列化将解析为d_o_b_属性,如果您需要满足此用例的要求,它将提供更好的结果。