views:

4872

answers:

2

Hi folks,

how do i do the following, with an ASP.NET MVC UpdateModel? I'm trying to read in a space delimeted textbox data (exactly like the TAGS textbox in a new StackOverflow question, such as this) into the model.

eg.

<input type="Tags" type="text" id="Tags" name="Tags"/>

...

public class Question
{
    public string Title { get; set; }
    public string Body { get; set; }
    public LazyList<string> Tags { get; set; }
}

....

var question = new Question();
this.UpdateModel(question, new [] { "Title", "Body", "Tags" });

the Tags property does get instantiated, but it contains only one item, which is the entire data that was entered into the Tags input field. If i want to have a single item in the List (based upon Splitting the string via space) .. what's the best practice do handle this, please?

cheers!

+8  A: 

Hi,

What you need to do is extend the DefaultValueProvider into your own. In your value provider extend GetValue(name) to split the tags and load into your LazyList. You will also need to change your call to UpdateModel:

UpdateModel(q, new[] { "Title", "Body", "Tags" }, 
   new QuestionValueProvider(this.ControllerContext));

The QuestionValueProvider I wrote is:

 public class QuestionValueProvider : DefaultValueProvider
    {
        public QuestionValueProvider(ControllerContext controllerContext)
            : base(controllerContext)
        {
        }
        public override ValueProviderResult GetValue(string name)
        {
            ValueProviderResult value = base.GetValue(name);
            if (name == "Tags")
            {
                List<string> tags = new List<string>();
                string[] splits = value.AttemptedValue.Split(' ');
                foreach (string t in splits)
                    tags.Add(t);

                value = new ValueProviderResult(tags, null, value.Culture); 
            }
            return value;
        }
    }

Hope this helps

John Oxley
yep! sure does! now i'm wondering if it's worth doing all that, instead of just doing an UpdateModel with "title" and "body", then manually setting the Tags property, after i do call Request["Tags"] and split that?
Pure.Krome
@John - just to continue this thread, when i added the <%=Html.ValidationMessage("Tags") %> to the html, it now autocompletes the textbox with System.Collections.Generic.List`1[Foo.Models.Tag]. Firstly, it's a string lazy list and not one of my other custom Tag classes. How can i fix this?
Pure.Krome
Is this solution now out of date with the current MVC RC2?
AndrewDotHay
DefaultValueProvider does not exist anymore since RC, the alternative is changing the ValueProvider that comes with the controller that is just a IDictionary<string, ValueProviderResult>. See: http://forums.asp.net/t/1382242.aspx
Marc Climent
A: 

Do you know how to get this includeProperty list working with a structured object - something like obj.Value1 obj.Value2 obj.Parent.Value3 obj.Parent.Value4

  • I can get it working fine using UpdateModel(obj) and UpdateModel(obj, new string[] {"Value1"}) just updates value1, but UpdateModel(obj, new string[] {"Value1", "Parent.Value3"}) doesn't work, and still only updates value1 and not the parent.value3.
Mad Halfling
I have found that the whitelisting/blacklisting (includeProperties/excludeProperties) do not operate on a "full path" such as your `Parent.Value3`. Even more recently I have found if you look into the MVC source, you will see that each include/exclude term is compared directly against each property name, regardless of any parents or how far nested in the object graph. Thus, supplying just "Value3" to include or exclude, will work against various properties `Value3`, `Parent.Value3`, `Parent.SomeOtherChild.Value3`, `SomeOtherObjectEntirely.Value3`.
Funka
This was confirmed as an issue on the ASP.NET forums and raised (by, AFAIK, one of the non-MS ppl involved in the MVC dev) as an issue. It was closed by an MS person as follows "The whitelist / blacklist filter is intended to affect only top-level properties. It will not (and was not designed to) filter down to child properties. For this scenario, either use a custom binder or use the default binder without a whitelist/blacklist and change the incoming model object to contain only the properties you actually are interested in updating." so be aware that method may not be 100% reliable.
Mad Halfling