ASP.NET MVC ModelMetadata - Do we violate separation of concerns when we put attributes to describe UI on model?
Asked Answered
F

3

7

According to this blog post "ModelMetadata objects are constructed with data taken from attributes, primarily from the System.ComponentModel and System.ComponentModel.DataAnnotations namespaces."

By putting UI helper attributes on Model objects (DisplayFormat or UIHint) aren't we coupling Model and View?

Flack answered 17/8, 2011 at 15:0 Comment(1)
That's why these "models" are usually called ViewModels.Forestay
C
9

I believe so. Personally I keep my model completely ui-agnostic and I write ViewModels which will represent my model in my View. Then assign all annotations to these ViewModels.

I think the violation comes from the fact that this limits your ability to reuse your model, since you are basically defining view behavior in your model.

Corrigan answered 17/8, 2011 at 15:27 Comment(4)
It looks like this is one solution. If I don't have control over Model object, I can create a wrapper object(ViewModel) that describes UI behavior.Flack
Exactly, and it is what I consider to be cleaner and more expandable. At first the prospect of coding your ViewModels seems like extra work, and it is, but its worth it. More so if you take into account that you view models can be different from your business models.Corrigan
+1 I do exactly the same. My Views doesn't coupled to the model and I've ViewModel for each ViewMadonnamadora
can you give some examples where model data annotations would change with views? Surely an email field is always an email, a post code always a post code etc? Isn't that more of an edge case you should do as required? Anything that adds this much time & repetition must be highly justifiable to be worth it...Jalbert
G
0

I think so.

I create specific view model classes that represent the information exchange between browser and server. If the model state is valid, then I copy the values or call the domain methods with those values (that's what the Models folder is for). I never put MVC specific attributes on my domain entities.

Rule of thumb, I keep my entities in a separate assembly, that knows nothing about MVC.

Watch out with expose domain entities in your MVC action methods... the model binder could do you a bad joke :D If for example, you have a class "Account", with a property "IsAdmin" and you expose this entity in a registration form, the user could try to pass an arbitrary "IsAdmin=true" parameter in the GET string or in the POST payload, and the MVC model binder will set that property in your model... and your code will probably save that information in the database.

Therefore, I think is very important to keep attention on the view models.

I know that with all this "dynamic" stuff like the ViewBag and let your own LINQ entities be parameters in the action methods everything becomes very easy to do... but we shouldn't overlook security, and to enforce security we have to be sure that only the information we want can arrive to our domain.

Cheers.

Greenwood answered 26/8, 2011 at 17:1 Comment(0)
M
0

That largely depends on how you define "coupling". You have already "coupled" your View to your model in a sense: your View uses the same properties that your Model defines. The problem is not with "coupling" it's about "what" and "how". The Model describes the What (should be displayed), it's up to the View to define the How (to do it). If you want to strictly follow this principle, you should discard the UI hints.

If you want to be more practical, sometimes these attributes can simplify your Views (that often get too complicated). So, it's up to you.

If you want to make your model reusable (which is in most cases not a good idea, but let's not get dogmatic here), make sure that you use only attributes that are consistent across the application. For example, if you display all floating point numbers in the same way, it makes sense to put the DisplayFormat attribute on the model, rather than type it again and again in your Views, polluting them with the boring details.

I tend to put the general structure in my main View and delegate the details to the partials, the UIHint attribute helps me a lot. Call it coupling, but the benefit is just huge.

Maribelmaribelle answered 28/8, 2011 at 11:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.