使用ASP MVC中的隐式运算符将字符串绑定到参数

时间:2016-04-30 15:17:42

标签: c# asp.net

我一直在寻找,我找不到足够的答案。

我有一个名为Title的包装类,定义如下

public class Title
{
    private readonly string _title;

    public Title (string title) {
        _title = title;
    }

    public static implicit operator Title(string title)
    {
        return new Title(title);
    }
}

我在ASP MVC项目中使用此类。现在我定义了一个像这样的控制器:

public ActionResult Add(string title)
{
    //stuff
}

这很好用。 但是,我希望自动将发布的字符串值绑定到Title构造函数,从而接受Title而不是string作为参数:

public ActionResult Add(Title title)
{
    //stuff
}

然而,这不起作用,因为我会得到错误: 参数字典包含参数的空条目,这意味着模型绑定器无法将字符串绑定到Title参数。

负责发布标题数据的HTML:

<form method="post" action="/Page/Add" id="add-page-form">                
    <div class="form-group">
        <label for="page-title">Page title</label>
        <input type="text" name="title" id="page-title">
    </div>
</form>

我的问题有两个部分:

1。为什么不可能这样做,我希望bodel binder使用定义的隐式运算符来创建Title实例。

2。有没有办法在没有明确创建模型绑定器的情况下仍能完成所需的行为?

3 个答案:

答案 0 :(得分:5)

虽然我迟到了,只是为了涵盖所有可用选项:您可以实现自己的TypeConverter,如下所示:

public class TitleConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) ? true : base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string)
            return new Title((string)value);

        return base.ConvertFrom(context, culture, value);
    }
}

[TypeConverter(typeof(TitleConverter))]
public class Title
{
    ...
}

如果您需要从不同类型实例化您的类

,这种方法特别有用

答案 1 :(得分:4)

根据你的问题:

  1. 模型绑定器将调用新的Title()。他不能这样做。然后他会尝试设置Title属性。他无法找到。不,默认活页夹不会调用隐式转换。他使用的algorythm是不同的。
  2. 不,如果您接受更改模型,则不需要自定义活页夹,根据默认模型活页夹的行为,这完全是错误的。
  3. 隐式转换对于Action绑定毫无用处。

    默认模型绑定器从请求的各个部分收集一个大的值字典,并尝试将它们插入到属性中。

    因此,如果您想将Title作为Action参数使用,那么最好的办法是使Title类对Binder友好,可以这么说:

    public class Title
    {
        public string Title { get; set; }
    
        /* If you really need the conversion for something else...
        public static implicit operator Title(string title)
        {
            return new Title { Title = title };
        }
        */
    }
    

    一切都应该像在客户端那样工作。

    如果您不能(或者不想)更改您的模型类,那么您可以使用自定义模型绑定器。但我认为你真的不需要它。

答案 2 :(得分:1)

编译器对您没有帮助。这是一个模型绑定问题。 您可以创建自定义ModelBinder