我在这上面看过很多类似的帖子,但没有找到特定于控制器parameters
的答案。
我编写了一个名为AliasAttribute
的自定义属性,允许我在模型绑定期间为参数定义别名。例如,如果我在服务器上有public JsonResult EmailCheck(string email)
,我希望将email
参数绑定到名为 PrimaryEmail 或 SomeCrazyEmail 的字段,我可以使用alias属性“映射”这样:public JsonResult EmailCheck([Alias(Suffix = "Email")]string email)
。
问题:在我的自定义模型绑定器中,我无法保持应用于AliasAttribute
参数的email
类。它总是返回null。
我已经看到 DefaultModelBinder 类正在做什么来在反射器中获取 BindAttribute 并且它相同但不适用于我。
问题:如何在绑定过程中获取此属性?
AliasModelBinder:
public class AliasModelBinder : DefaultModelBinder
{
public static ICustomTypeDescriptor GetTypeDescriptor(Type type)
{
return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
}
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = base.BindModel(controllerContext, bindingContext);
var descriptor = GetTypeDescriptor(bindingContext.ModelType);
/*************************/
// this next statement returns null!
/*************************/
AliasAttribute attr = (AliasAttribute)descriptor.GetAttributes()[typeof(AliasAttribute)];
if (attr == null)
return null;
HttpRequestBase request = controllerContext.HttpContext.Request;
foreach (var key in request.Form.AllKeys)
{
if (string.IsNullOrEmpty(attr.Prefix) == false)
{
if (key.StartsWith(attr.Prefix, StringComparison.InvariantCultureIgnoreCase))
{
if (string.IsNullOrEmpty(attr.Suffix) == false)
{
if (key.EndsWith(attr.Suffix, StringComparison.InvariantCultureIgnoreCase))
{
return request.Form.Get(key);
}
}
return request.Form.Get(key);
}
}
else if (string.IsNullOrEmpty(attr.Suffix) == false)
{
if (key.EndsWith(attr.Suffix, StringComparison.InvariantCultureIgnoreCase))
{
return request.Form.Get(key);
}
}
if (attr.HasIncludes)
{
foreach (var include in attr.InlcludeSplit)
{
if (key.Equals(include, StringComparison.InvariantCultureIgnoreCase))
{
return request.Form.Get(include);
}
}
}
}
return null;
}
}
AliasAttribute:
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class AliasAttribute : Attribute
{
private string _include;
private string[] _inlcludeSplit = new string[0];
public string Prefix { get; set; }
public string Suffix { get; set; }
public string Include
{
get
{
return _include;
}
set
{
_include = value;
_inlcludeSplit = SplitString(_include);
}
}
public string[] InlcludeSplit
{
get
{
return _inlcludeSplit;
}
}
public bool HasIncludes { get { return InlcludeSplit.Length > 0; } }
internal static string[] SplitString(string original)
{
if (string.IsNullOrEmpty(original))
{
return new string[0];
}
return (from piece in original.Split(new char[] { ',' })
let trimmed = piece.Trim()
where !string.IsNullOrEmpty(trimmed)
select trimmed).ToArray<string>();
}
}
用法:
public JsonResult EmailCheck([ModelBinder(typeof(AliasModelBinder)), Alias(Suffix = "Email")]string email)
{
// email will be assigned to any field suffixed with "Email". e.g. PrimaryEmail, SecondaryEmail and so on
}
答案 0 :(得分:0)
放弃这个,然后偶然发现了可能允许我这样做的Action Parameter Alias代码库。它不像我开始编写的那样灵活,但可能会被修改为允许使用外卡。
答案 1 :(得分:0)
我所做的是创建我的属性子类System.Web.Mvc.CustomModelBinderAttribute
,然后允许您返回使用别名修改的自定义模型绑定器的版本。
示例:
public class AliasAttribute : System.Web.Mvc.CustomModelBinderAttribute
{
public AliasAttribute()
{
}
public AliasAttribute( string alias )
{
Alias = alias;
}
public string Alias { get; set; }
public override IModelBinder GetBinder()
{
var binder = new AliasModelBinder();
if ( !string.IsNullOrEmpty( Alias ) )
binder.Alias = Alias;
return binder;
}
}
然后允许这种用法:
public ActionResult Edit( [Alias( "somethingElse" )] string email )
{
// ...
}