Glubus Glubus - 2 months ago 17
ASP.NET (C#) Question

Binding a string to a parameter using an implicit operator in ASP MVC

I've looked around on SO, I can't find a sufficient answer to my question.

I have a wrapper class called

Title
defined like this

public class Title
{
private readonly string _title;

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

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


I am using this class in an ASP MVC project. Right now I defined a controller like this:

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


and this works fine.
However, I wish to automatically bind the posted string value to the
Title
constructor, thus accepting a
Title
instead of a
string
as a parameter:

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


This however, does not work, as I will get the error:
The parameters dictionary contains a null entry for parameter, meaning the model binder can't bind the string to the
Title
parameter.

The HTML responsible for posting the title data:

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


My question exists of two parts:

1. Why is it not possible to do this, I would expect the bodel binder to use the defined implicit operator to create a
Title
instance.


2. Is there a way to still accomplish getting the desired behavior, without explicitly creating a modelbinder?

Answer

As per you questions:

  1. The model binder is going to call new Title(). Which he can't. Then he would try to set a Title property. Which he can't find. No, the default binder does not call implicit conversions. The algorythm he uses is different.
  2. No, you don't need a custom binder, if you accept to change your Model, which is completely wrong in according to the behaviour of the default model binder.

The implicit conversion doesn't matter at all for Action binding.

The default model binder takes a big dictionary of values, gathered from the various parts of the request, and tries to insert them into properties.

So, if you want to use your Title as an Action parameter, your best bet is to make the Title class Binder-friendly, so to speak:

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

Everything should work as it is on the client side.

If you cannot (or don't want to) change your model class, then you can go for a custom model binder. But I don't think you really need it.

Comments