1

In asp.net mvc3 I want to have a generic method which adds a viewmodel object to the database from wherever it is sent to the right spot in the database. To do this, I am trying to pass in the posted model. However, I am having a little difficulty doing it dynamically. I tried this but it didn't work:

view:

(psuedo)
begin form aiming at Add
 fields
input type = submit

controller action

[HttpPost]
public ActionResult Add(dynamic model,...)

The issue is that model is never filled. The hidden fields are, but the actual fields defined by the model with the helpers are not going into model. I realize that just naming it model is more than likely not going to line up right. I am sure if I strongly typed the model, such as (MyExplicitClass model,...) it would work but that defeats the dynamic approach because I want to be able to send class1, class2, class3, class5, class8, class13, etc.

Is there any way to get this working in that no matter what @model class21 is sent, the dynamic model (or equiv) will capture that object?

Travis J
  • 77,009
  • 39
  • 185
  • 250

1 Answers1

2

No. At least not without using a custom model binder.

You have a fundamental misunderstanding of how model binding works. You think that model binding works based on the @model in the view. This couldn't be further from the truth. Model binding works by looking at the parameters specified in the action method.

All the model binder does is look at the type of the parameters specified for the action method, and then look at the Request values (either querystring or post) and try to match them up. If it finds a match, it instantiates the object.

The key here is that the model binder only instantiates the objects specified in the parameters of the action method. What object is "dynamic"? It has no idea. Therefore it can't create any type.

EDIT:

You may find this question useful

Polymorphic model binding

Community
  • 1
  • 1
Erik Funkenbusch
  • 90,480
  • 27
  • 178
  • 274
  • What if I put a filter in to infer and then cast the type? Could that work? – Travis J Apr 15 '12 at 21:34
  • @TravisJ - Filters (assuming you mean an attribute) are statically bound at compile time. They wont' work at runtime, so there's no way to change the filter out at runtime. – Erik Funkenbusch Apr 15 '12 at 21:39
  • It is possible to trampoline past the binding and have it be done at runtime with a copy of the static type dynamically created. – Travis J Apr 15 '12 at 21:39
  • 1
    @TravisJ - your only choice here is to create a custom model binder, then you need to have something in your view that identifies which object to create, then have your model binder create that object. You would be better off using a common base type than a dynamic type, though. Beware though, this could be very insecure.. as an attacker could change the type and post a value that is different from what you expect – Erik Funkenbusch Apr 15 '12 at 21:40
  • What you suggested is what I was trying to formulate as far as the custom model binder, my view already identifies the object type to create ( I have this implemented for several other crud functions already ). Do you know of any good model binder tutorials? I have seen a few but they are a little dated. – Travis J Apr 15 '12 at 21:43
  • As to the aforementioned security risk - the type will be held server side. I agree that allowing the clientside to determine the type would be undesirable. Moreover, this scenario is only going to be available to high level authorization. That polymorphic link is very good (Darin always contributes such nice code). I am going to try that and see how it goes. – Travis J Apr 15 '12 at 22:19
  • Where would this modelbinder be defined? I noticed in one link that the binder had to be explicitly defined for a class. Is that going to be true of all classes which would use the dynamic modelbinder? – Travis J Apr 15 '12 at 22:23
  • @TravisJ - How will the type be held server side? Your action method has no idea what type it posted the value, since you could have any number of pages open. Remember, HTTP is stateless. You have to be able to get all information from either the action method, or the client submitted values. Also remember that you need to select which model to instantiate prior to getting to your action method. – Erik Funkenbusch Apr 15 '12 at 22:25
  • @TravisJ - As i said, it would be better to use a common base class rather than dynamic. I'm not sure if using typeof(dynamic) would work or not for a model binder. – Erik Funkenbusch Apr 15 '12 at 22:26
  • A common base class is not applicable here, I think you are missing the point. A common base class is not going to allow the retention of every field for an entity that needs to be inserted into the database. As to the server side type holding, that part is trivial, and really has nothing to do with HTTP. As stated, I have already implemented this with other crud functionality, just not `Create`. – Travis J Apr 15 '12 at 22:30
  • @TravisJ - Ok, since you know what you're doing, i won't bother answering your question anymore. – Erik Funkenbusch Apr 15 '12 at 22:31
  • I was just trying to respond to your rather large list of questions in response to asking where the modelbinder was registered. Sorry if I offended you, and thank you for your time. – Travis J Apr 15 '12 at 22:35
  • @TravisJ - you didn't offend me, but you did try to tell me that a key concept that is crucial to solving your problem is unimportant. If refuse to accept that it is important, i can't help you. – Erik Funkenbusch Apr 15 '12 at 22:37
  • Holding the type is on server side, in the session. The user never has access to it, nor knows what or where it is. The session dictionary is never accessed anywhere through HTTP. What I was explaining is that there is no need to worry about the type. Only getting the model passed somewhere that I can manipulate it into the correct type (which I already have instantiated and know of). – Travis J Apr 15 '12 at 22:41