2

我看过很多类似的帖子,但还没有找到特定于控制器的答案parameters

我编写了一个名为的自定义属性AliasAttribute,它允许我在模型绑定期间为参数定义别名。因此,例如,如果我有:public JsonResult EmailCheck(string email)在服务器上并且我希望将email参数绑定到名为PrimaryEmailSomeCrazyEmail的字段,我可以使用 aliasattribute 像这样“映射”它:public JsonResult EmailCheck([Alias(Suffix = "Email")]string email)

问题:在我的自定义模型绑定器中,我无法掌握AliasAttribute应用于email参数的类。它总是返回 null。我已经看到DefaultModelBinder类为在反射器中获取BindAttribute所做的工作,它是相同的,但对我不起作用。

问题:如何在绑定期间获取此属性?

别名模型绑定器:

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;
    }
}

别名属性:

[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
}
4

2 回答 2

0

放弃了这一点,然后偶然发现了可能允许我这样做的动作参数别名代码库。它不像我开始写的那样灵活,但可能可以修改为允许通配符。

于 2013-08-22T17:54:37.553 回答
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 )
{
    // ...
}
于 2015-04-10T16:06:46.973 回答