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

1

6

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?

Conflux answered 30/7, 2009 at 5:13 Comment(0)
F
1

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.

Fading answered 30/7, 2009 at 18:36 Comment(1)
Hi, I went down same route following source code to see what is going on inside there (having a lot of problems with my dropdownlists sometimes not binding depending on where selectlist comes from...). How did you do this in Reflector? Would be helpful to be able to get the call stack for a few things in MVC framework.Spiros

© 2022 - 2024 — McMap. All rights reserved.