What order are objects placed into a Model in MVC3 and how can I control it

Go To StackoverFlow.com

1

I have an model being passed back successfully from my view except that I would like an ID value to be the first thing that is bound back to the Model so it can fill some information from the db. The information being passed back is as follows

SetupID:91c16e34-cf7d-e111-9b66-d067e53b2ed6
SwayBarLinkLengthLF:
SwayBarLinkLengthRF:
.....way more information....

My Action is as follows

[HttpPostAttribute]
public ActionResult SaveSetup(SetupAggregate setup)
{
   setup.SaveSetup();
   return null;
}

I would like the SetupID to be the first property that is set on the empty setup object but it looks like the first property alphabetically is being set first.

2012-04-04 19:35
by PlTaylor
You may need to create your own custom ModelBinder for your needs - Nick Bork 2012-04-04 19:41
This form posts back a lot of data. Is there anyway to do a custom model binder without having to set every property....I.E. set the property I can about and then let the default handle the rest - PlTaylor 2012-04-04 19:49
By inheriting from the default provider, most likely yes. Check out this thread: http://stackoverflow.com/questions/3636747/asp-net-mvc-custom-model-binder-for-id-fields Your goal is going to inherit from the base model binder, populate your ID field FIRST, then use base.BindModel(controllerContext, bindingContext); though you may have issues to work throug - Nick Bork 2012-04-04 20:14
Let me work through that for a little bit and I'll get back to you - PlTaylor 2012-04-04 20:18
you dynamically do 'a bunch of work' when the binder sets this property? if so, I highly recommend against it. Do the work after you are handed your model. Its easier to trace,debug, more standard, etc. Also you just need [HttpPost] not [HttpPostAttribute] again standard usage - Adam Tuliper - MSFT 2012-04-04 20:49
I am setting the id on a model from our in-house orm. It uses the id to load the rest of the data from the db, and then I want the values from the form post to fill in what the user submitted. If it changes the orm marks an is dirty and saves it to the db. The more I'm thinking about it the more I wonder if I shouldn't cache the model some how - PlTaylor 2012-04-05 00:07


0

In my opinion you really need to be working with 2 separate "models" - your ViewModel, which is what is in your MVC project and is rendered to your view. And a 2nd EntityModel in a business logic layer. This is standard "enterprise" programming design. It gives you a lot more control of your data. The idea is this.

UI Assembly (MVC project)

ViewModel definition

public class MyModel {
    public int ID { get; set; }
    .... // bunch of other properties
}

Controller

public class InterestingController : Controller {

    public ActionResult CreateNewWidget() {
        var model = new MyModel();
        return View(model);
    }

    [HttpPost]
    public ActionResult CreateNewWidget(MyModel model) {
        if(ModelState.IsValid) {
            // your ctor can define the order of your properties being sent in and you can set the entity values in the ctor body however you choose to. Note never SET an ID/Primary key on a Create, let the DB handle that. If you need to return the new Key value, get it from the insert proc method in your DAL and return it up the stack
            var entityModel = new EntityFromBLL(model.Name, model.OtherProperty, ... etc);
            entityModel.Save(User.Identity.Name); // your save method should always capture WHO is doing the action
        }
        return View(model);
    }

    public ActionResult UpdateExistingWidget(int id) {
        var entityModel = new EntityFromBLL(id); // get the existing entity from the DB
        var model = new MyModel(entityModel.ID, entityModel.Name, ... etc); // populate your ViewModel with your EntityModel data in the ViewModel ctor - note remember to also create a parameterless default ctor in your ViewModel as well anytime you create a ctor in a ViewModel that accepts parameters
        return View(model);
    }

    [HttpPost]
    public ActionResult UpdateExistingWidget(MyModel model) {
        if(ModelState.IsValid) {
            var entityModel = new EntityFromBLL(model.ID); // always pull back your original data from the DB, in case you deal with concurrency issues
            // now go thru and update the EntityModel with your new ViewModel data
           entityModel.Name = model.Name;
           //... etc set all the rest of the properties
           // then call the save
           entityModel.Save(User.Identity.Name);
        }
        return View(model)
    }
}

Your Entity Model should be defined with private fields, public properties, a ctor that takes in all required fields for an insert (minus the primary key), a ctor that takes in the primary key and then can call an internal load method statically to return a populated object. Business rules and property validation and a single Save method. The Save method should check for the IsDirty bit after all the properties have been set and call the respective Insert or Update methods .. which in turn should call into a DAL passing DTOs

2012-04-05 02:21
by CD Smith
I ended up using something very similar to what you describe. I handled it all in my viewmodel though. I just made a constructor of my viewmodel that accepted another instance of the viewmodel and did the logic from there - PlTaylor 2012-04-05 11:16
I was actually considering suggesting that if using an N-tier structure was out of the question, very cool - CD Smith 2012-04-05 11:31
Ads