gpt4 book ai didi

c# - 从括号表示法中的查询字符串绑定(bind)模型

转载 作者:行者123 更新时间:2023-11-30 12:21:44 26 4
gpt4 key购买 nike

多余的评论:我不敢相信我在任何地方都找不到明确的答案!

使用 ASP.NET MVC 模型绑定(bind)需要在使用查询字符串时使用点符号 (variableName.propertyName)。但是,jQuery 在使用 GET 请求时会使用括号表示法,例如 variableName[propertyName]=value&。 ASP.NET MVC 无法理解这种表示法。

如果我发出 POST 请求,ASP.NET 能够正确绑定(bind)模型,因为它在发布的正文中使用点表示法。

当在查询字符串中使用方括号表示法时,是否有任何方法可以强制 ASP.NET 绑定(bind)到复杂对象模型?

最佳答案

我不确定这是否是理想的解决方案,但我通过实现 IModelBinder 的通用实现,使用一些反射魔法解决了这个问题。此实现的规定是,它假定查询字符串中来自 JavaScript 的元素采用驼峰式命名法,而 C# 中的类采用标准样式的 PascalCase 法。此外,它仅适用于公共(public) [set-able] 属性。下面是我的实现:

public class BracketedQueryStringModelBinder<T> : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.CanWrite);
Dictionary<string, object> values = new Dictionary<string, object>();
foreach (var p in properties)
{
if (!IsNullable(p.PropertyType))
{
object val = TryGetValueType(p.PropertyType, bindingContext, p.Name);
if (val != null)
{
values.Add(p.Name, val);
}
}
else
{
object val = GetRefernceType(p.PropertyType, bindingContext, p.Name);
values.Add(p.Name, val);
}
}

if (values.Any())
{
object boundModel = Activator.CreateInstance<T>();
foreach (var p in properties.Where(i => values.ContainsKey(i.Name)))
{
p.SetValue(boundModel, values[p.Name]);
}

return boundModel;
}

return null;
}

private static bool IsNullable(Type t)
{
if (t == null)
throw new ArgumentNullException("t");

if (!t.IsValueType)
return true;

return Nullable.GetUnderlyingType(t) != null;
}

private static object TryGetValueType(Type type, ModelBindingContext ctx, string key)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException("key");

key = ConvertToPascalCase(key);

ValueProviderResult result = ctx.ValueProvider.GetValue(string.Concat(ctx.ModelName, "[", key, "]"));
if (result == null && ctx.FallbackToEmptyPrefix)
result = ctx.ValueProvider.GetValue(key);

if (result == null)
return null;

try
{
object returnVal = result.ConvertTo(type);
ctx.ModelState.SetModelValue(key, result);
return returnVal;
}
catch (Exception ex)
{
ctx.ModelState.AddModelError(ctx.ModelName, ex);
return null;
}
}

private static object GetRefernceType(Type type, ModelBindingContext ctx, string key)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException("key");

key = ConvertToPascalCase(key);

ValueProviderResult result = ctx.ValueProvider.GetValue(string.Concat(ctx.ModelName, "[", key, "]"));
if (result == null && ctx.FallbackToEmptyPrefix)
result = ctx.ValueProvider.GetValue(key);

if (result == null)
return null;

try
{
object returnVal = result.ConvertTo(type);
ctx.ModelState.SetModelValue(key, result);
return returnVal;
}
catch (Exception ex)
{
ctx.ModelState.AddModelError(ctx.ModelName, ex);
return null;
}
}

private static string ConvertToPascalCase(string str)
{
char firstChar = str[0];
if (char.IsUpper(firstChar))
return char.ToLower(firstChar) + str.Substring(1);

return str;
}
}

然后在你的 Controller 中你可以像这样使用它:

[HttpGet]
public ActionResult myAction([ModelBinder(typeof(BracketedQueryStringModelBinder<MyClass>))] MyClass mc = null)
{
...
}

此方法的主要缺点是,如果您确实以点表示法获取查询字符串,此绑定(bind)将失败,因为它不会恢复为标准模型绑定(bind)器。

关于c# - 从括号表示法中的查询字符串绑定(bind)模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44572169/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com