【问题标题】:Binding a string to a parameter using an implicit operator in ASP MVC在 ASP MVC 中使用隐式运算符将字符串绑定到参数
【发布时间】:2016-04-30 15:17:42
【问题描述】:

我环顾四周,找不到足够的答案来回答我的问题。

我有一个名为 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。有没有办法在不显式创建模型绑定器的情况下仍然获得所需的行为?

【问题讨论】:

  • 你能展示你的观点吗?您必须将视图的模型设置为标题类型而不是字符串才能正常工作
  • 发送post到这个action的partial view不使用模型,只是一个表单,有一个textfield作为输入,不管怎样我都会添加负责发帖的html。

标签: c# asp.net


【解决方案1】:

虽然我迟到了,只是为了涵盖所有可用选项:您可以实现自己的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
{
    ...
}

如果您需要从不同类型实例化您的类,这种方法特别有用

【讨论】:

  • 那么这在实际意义上完成了什么?这是否允许我接受绑定器试图将字符串绑定到参数的Title 对象?感觉这只是您在实现隐式运算符之前要做的事情。我知道这主要是为了完整性,我只是想知道这是否允许除了已经提供的答案之外的任何其他内容。
  • 是的,它将string 绑定到Title。将其视为使用完全不同的基于类型的机制的模型绑定器的替代品。虽然它允许您专注于输入 type,但在某些需要控制器或绑定上下文的场景中,您仍然必须求助于 binder。
  • 漂亮!我可能会在某个时候尝试一下,感谢您留下您的答案,尽管我已经发布了这个帖子。
【解决方案2】:

根据你的问题:

  1. 模型绑定器将调用 new Title()。他不能。然后他会尝试设置一个 Title 属性。他找不到。不,默认绑定器不调用隐式转换。他使用的算法不同。
  2. 不,如果您接受更改模型,则不需要自定义绑定器,根据默认模型绑定器的行为,这是完全错误的。

对于 Action 绑定,隐式转换根本不重要。

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

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

/* We call the class TitleModel in order not to clash
 * with the Title property.
 */
public class TitleModel
{
    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 };
    }
    */
}

一切都应该在客户端正常工作。

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

【讨论】:

  • 我希望将给定的字符串隐藏到 Title 实例中,因此我不想创建公共属性。我想我会创建一个自定义活页夹。我只是觉得应该有办法做到这一点。哦,好的,谢谢。
  • 私人被高估了。在现实世界中,为什么 Title 属性不是只读的?无论如何,它是一个信使对象。一些理论上的公牛%%t 不算数,抱歉 ;) 我只是在开玩笑!但我鼓励您尝试按预期使用框架,不要重新发明轮子。
  • 这是一门学科。标题是不可变的东西。一本书有一个标题,而这本书的标题永远不会改变(通常,显然这是一个抽象)。现在至于为什么不把这个标题表示为一个字符串:一个字符串不会告诉你它的值的语义。标题实例清楚地表示某物的标题。这允许您不会混淆像 Tttle 和 Author 这样的属性,这些属性通常都表示为字符串。
  • 是的,但是在您的示例中,您的 Title 类是来自客户端的请求对象。您不应该将这个确切的类用于数据库操作。我更愿意调用这个类 AddPageRequest(因为这是这个类的真正意义:对 AddPage 操作的请求)并在 Request 对象中有一个 ToTitle 方法。 MVC 真的不希望你那样做。只是我的 2 美分。
  • 但是……成员名怎么能和封闭类型一样呢?
【解决方案3】:

编译器不会帮你。这是一个模型绑定问题。 您可以创建自定义ModelBinder

【讨论】:

  • 嗯,请原谅我选择不当的术语,显然模型绑定是在运行时完成的。但是,我的问题是为什么这不起作用,我知道我可以创建一个自定义模型绑定器,并且我在我的问题中声明,如果 tehre 是使用隐式运算符的一种解决方法,我不希望这样做。
猜你喜欢
  • 2015-11-19
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
相关资源
最近更新 更多