自定义MVC模型绑定在没有公共属性的类型上

时间:2015-01-12 14:56:03

标签: c# asp.net-mvc

我在我的项目中创建了强类型ID类,因为目前存在可互换字符串ID的混淆,导致容易错过的错误。

我已将操作方法​​中的所有string id参数更改为新的强类型,以实现MVC模型绑定器现在无法将字符串绑定到新类型(尽管此类型存在隐式字符串转换运算符)。

e.g。

public ActionResult Index(JobId jobId)
{
  //...
}

我已经阅读了有关创建自定义模型绑定器的内容,但是当我们知道查询参数/表单值的名称时,所有教程都是关于绑定POCO类。

我只是想告诉框架'if参数是强类型id类型,使用这个构造函数实例化',所以无论参数名称是什么,它都会一直有效。

有人能指出我正确的方向吗?

修改

这是强类型ID继承自的基类:

public class StronglyTypedId
{    
    private readonly string _id;

    public StronglyTypedId(string id)
    {
        _id = id;
    }

    public static bool operator ==(StronglyTypedId a, StronglyTypedId b)
    {
        if (ReferenceEquals(a, b))
        {
            return true;
        }

        if (((object)a != null) && ((object)b == null) || ((object)a == null))
        {
            return false;
        }

        return a._id == b._id;
    }

    public static bool operator !=(StronglyTypedId a, StronglyTypedId b)
    {
        return !(a == b);
    }

    public override string ToString()
    {
        return _id;
    }

    public override bool Equals(object obj)
    {
        if (!(obj is StronglyTypedId))
        {
            return false;
        }

        return ((StronglyTypedId)obj)._id == _id;
    }

    public Guid ToGuid()
    {
        return Guid.Parse(_id);
    }

    public bool HasValue()
    {
        return !string.IsNullOrEmpty(_id);
    }
}

1 个答案:

答案 0 :(得分:0)

我现在想出了一种使用自定义模型绑定器的方法。无论需要绑定的参数名称是什么,这种方式都可以工作:

public class JobIdModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(JobId))
        {
            var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            string id = value.AttemptedValue;

            return new JobId(id);
        }
        else
        {
            return base.BindModel(controllerContext, bindingContext);
        }
    }
}

所以它与为特定模型类型实现自定义绑定器几乎相同,除了这有点神奇var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName),这意味着无论参数命名如何都可以工作。

然后您只需在Global.cs中注册活页夹,就像这样:

ModelBinders.Binders.Add(typeof(JobId), new JobIdModelBinder());