Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't seem to get IncludeProperties working on UpdateModel in ASP.NET MVC

Has anybody had luck with this?

Please let me know if I understand it correctly, if I have a simple model let's say with:

public string Name { get; set; }
public string Details { get; set; }
public DateTime? Created { get; set; }

and then I perform a:

var myModel = getCurrentModelFromDb(id);
UpdateModel(myModel, "ModelName", new string { "Name", "Details" });

Should this ONLY update the name and detail properties? Because let's say there was a date already from db in 'created', when I do the above it seems to set my created date to 01-01-0001 from the original.

Moreover, when I then try to explicitly exclude this field with:

UpdateModel(myModel, "ModelName", 
   new string { "Name", "Details" }, new string { "Created" });

It is still being set to 01-01-0001. Is this a bug, or a strange thing I am doing wrong?

What I effectively want to do, is update my model properties for which there are corresponding form fields for, but leave the rest of them alone which were set from the db fetch alone and not set them to null or default, which is what it currently appears to be doing.

I will say though, perhaps the only difference between above and my real-world scenario is I am using updateModel on a list, so I am effectively getting listFromDb(parentId) and then applying updateModel(myList, "ListPrefix") on that which picks up each item by [0], [1] etc... It works, as all the names are updating, but everything else is not.

Update: I've just realised probably 'includeProperties' is to define which properties you wish to include from the form, similar to how the bind works. If this *is* the case, then how can I tell it to only update certain model properties instead?

like image 912
GONeale Avatar asked Jul 30 '09 05:07

GONeale


1 Answers

I've been looking into this using Reflector... the call stack is:

UpdateModel() --> TryUpdateModel() --> DefaultModelBinder.BindModel() ---> either BindComplexModel() or BindSimpleModel().

Here's the disassembly for BindSimpleModel():

 if (bindingContext.ModelType != typeof(string))
    {
        if (bindingContext.ModelType.IsArray)
        {
            return ConvertProviderResult(bindingContext.ModelState, bindingContext.ModelName, valueProviderResult, bindingContext.ModelType);
        }
        Type type = ExtractGenericInterface(bindingContext.ModelType, typeof(IEnumerable<>));
        if (type != null)
        {
            object o = this.CreateModel(controllerContext, bindingContext, bindingContext.ModelType);
            Type collectionType = type.GetGenericArguments()[0];
            Type destinationType = collectionType.MakeArrayType();
            object newContents = ConvertProviderResult(bindingContext.ModelState, bindingContext.ModelName, valueProviderResult, destinationType);
            if (typeof(ICollection<>).MakeGenericType(new Type[] { collectionType }).IsInstanceOfType(o))
            {
                CollectionHelpers.ReplaceCollection(collectionType, o, newContents);
            }
            return o;
        }
    }

It's pretty clear that there are new elements being created. I'm unclear as to the exact logic of the flags though, and I don't have time to investigate it further right now. Incidentally, BindComplexModel is similar in that it seems to be creating new elements for collection types.

I'll try to analyze it more later.

like image 160
womp Avatar answered Oct 21 '22 12:10

womp