Does ASP.NET MVC offer any simple way to get model binding to work when you have model classes that inherit from others?
In my scenario I have a View that is strongly typed to List<Person>.
I have a couple of classes that inherit from Person, namely PersonTypeOne and PersonTypeTwo.
I have three strongly typed partial views with names that match these class names (and render form elements for the properties of their respective models).
This means that in my main View I can have the following code:
<% for(int i = 0; i < Model.Count; i++)
{
Html.RenderPartial(Model[i].GetType().Name, Model[i]);
} %>
This works well, apart from when the user submits the form the relevant controller action method just gets a List<Person>, rather than a list of Person, PersonTypeOne and PersonTypeTwo.
This is pretty much as expected as the form submission doesn't contain enough information to tell the default model binder to create any instances of PersonTypeOne and PersonTypeTwo classes.
So, is there any way to get such functionality from the default model binder?
You should just create separate models to bind to your input. Your ViewModels and EditModels are truly distinct responsibilities and thus deserve their own objects.
Related
The title may seems confusing, but it's not easy to describe the question in few words. Let me explain the situation:
We have a web application project, and a calculation engine project. The web application collect user input and use the engine to generate some result, and represent to user. Both user input, engine output and other data will be persisted to DB using JPA.
The engine input and output consist of objects in tree structure, example like:
Class InputA {
String attrA1;
List<InputB> inputBs;
}
Class InputB {
String attrB1;
List<InputC> inputCs;
}
Class InputC {
String attrC1;
}
The engine output is in similar style.
The web application project handle the data persistence using JPA. We need to persist the engine input and output, as well as some other data that related to the input and output. Such data can be seem as extra fields to certain class. For example:
We want to persist extra field, so it looks like:
Class InputBx extends InputB{
String attrBx1;
}
Class InputCx extends InputC{
String attrCx1;
}
In Java OO world, this works, we can store a list of InputBx in InputA, and store a list of InputCx in InputBx because of the inheritance.
But we meet trouble when using JPA to persist the extended objects.
First of all, it requires the engine project to make their class become JPA entities. The engine was working fine by itself, it accept correct input and generate correct output. It doesn't smell good to force their model to become JPA entities when another project try to persist the model.
Second, the JPA doesn't accept the inherited objects when using InputA as the entry. From JPA point of view, it only know that InputA contains a list of InputB, and not possible to persist/retrieve a list of InputBx in object of InputA.
When trying to solve this, we had come up 2 ideas, but neither one satisfied us:
idea 1:
Use composition instead inheritance, so we still persist the original InputA and it's tree structure include InputB and InputC:
Class InputBx{
String attrBx1;
InputB inputB;
}
Class InputCx{
String attrCx1;
InputC inputC;
}
So the original input object tree can be smoothly retrieved, and InputBx and InputCx objects needs to be retrieved using the InputB and InputC objects in the tree as references.
The good thing is that no matter what changes made to the structure of the original input class tree (such as change attribute name, add/remove attributes in the classes), the extended class InputBx and InputCx and their attributes automatically synchronized.
The drawback is that this structure increases the calls to the database, and the model is not easy to use in the application(both back end and front end). Whenever we want related information of InputB or InputC, we need to manually code to search the corresponding object of InputBx and InputCx.
idea 2:
Manually make mirror classes to form a similar structure of the original input classes. So we created:
Class InputAx {
String attrA1;
List<InputBx> inputBs;
}
Class InputBx {
String attrB1;
List<InputCx> inputCs;
String attrBx1;
}
Class InputCx {
String attrC1;
String attrCx1;
}
We could use this as model of the web application, and the JPA entities as well. Here's what we could get:
Now the engine project can be set free, it doesn't need to bind to how the other projects persist these input/output objects. The engine project is independant now.
The JPA persistence works just fluent, no extra calls to database is required
The back end and front end UI just use this model to get both original input objects and related information with no effort. When trying use engine to perform calculation, we can use a mapping mechanism to transfer between the original objects and extended objects.
The drawback is also obvious:
There is duplication in the class structure, which is not desired from the OO point of view.
When considering it as DTO to reduce the database calls, it can be claimed as anti-pattern when using DTO in local transfer.
The structure is not automatically synchronized with the original model. So if there are any changes made to the original model, we need to manually update this model as well. If some developers forget to do this, there will be some not-easy-to-find defects.
I'm looking for the following help:
Is there any existing good/best practices or patterns to solve similar situation we meet? Or any anti-patterns that we should try to avoid? References to web articles are welcome.
If possible, can you comment on the idea 1 and idea 2, from the aspect of OO design, Persistence practices, your experience, ect.
I will be grateful for your help.
Briefly, I'm loading objects that descend from a base class using a repository defined against the base class. Although my objects are created with the correct descendant classes, any descendant classes that add navigation properties not present in the base class do not have those related objects loaded, and I have no way to explicitly request them.
Here is a simple method in a repository class that loads a given calendar event assuming you know its ID value:
public CalendarEvent GetEvent(int eventId)
{
using (var context = new CalendarEventDbContext(ConnectionString))
{
var result = (from evt in context.CalendarEvents
where eventId.Equals((int)evt.EventId)
select evt).ToList();
return result.ToList()[0];
}
}
CalendarEvent is a base class from which a large number of more specific classes descend. Entity Framework correctly determines the actual class of the calendar event specified by eventId and constructs and returns that derived class. This works perfectly.
Now, however, I have a descendant of CalendarEvent called ReportIssued. This object has a reference to another object called ReportRequest (another descendant of CalendarEvent, although I don't think that's important).
My problem is that when Entity Framework creates an instance of ReportIssued on my behalf I always want it to create and load the related instance of ReportRequested, but because I am creating the event in the context of generic calendar events, although I correctly get back a ReportIssued event, I cannot specify the .Include() to get the related object. I want to do it through this generically-expressed search because I won't necessarily know the type of eventId's event and also I have several other "Get" methods that return collections of CalendarEvent descendants.
I create my mappings using the Fluent API. I guess what I'm looking for is some way to express, in the mapping, that the related object is always wanted or, failing that, some kind of decorator that expresses the same concept.
I find it odd that when saving objects Entity Framework always walks the entire graph whereas it does not do the equivalent when loading objects.
I'm trying to port the core of an application across to Portable Class Libraries and don't appear to have binding support.
I'm trying to bind a property on my ViewModel to my Model, which consists of an ObservableDictionary (INotifyPropertyChanged, INotifyCollectionChanged, IDictionary<string, string>). I do this usually (with WP7) by using the following code when initialising the view model:
SetBinding(MyProperty, new Binding(string.Format("MyDictionary[{0}]", "thekey")) { Source = MyModel });
How would I approach this when using Portable Class Libraries, where it seems like the Binding class is unavailable?
I've implemented this by having the base class for the ViewModels wire up to the PropertyChanged event of the ViewModel and the NotifyCollectionChanged event of the ObservableDictionary. I then have a method (with a set of overloads for additionally supplying an implementation of an IPclValueConverter which is a copy of the IValueConverter) which adds to a collection of PclBinding objects which is a set of PropertyInfo, dictionary key, IPclValueConverter and a converter parameter.
Within the PropertyChanged/NotifyCollectionChanged I check to see if the binding should be updated, and if so perform the update passing the value through a converter if present.
This means that from my original example, I now write the following inside my ViewModel which creates the binding as required:
SetBinding(() => MyProperty, "theKey");
If anyone is actually interested in this code I'd be happy to post it up. :)
I have recently been looking for a way to bind data in WinForms using MVVM.
I ended up creating a custom implementation of the MVVM pattern.
However, due to the lack of two-way binding, I have decided to give WPF a try.
I already have the Model, which encapsulates the non-ui functionality. For example the Model reads a configuration file, has a few properties, listens for incoming data on a socket, and saves incoming packets if needed.
Some of the Model's properties throws an exception if they are set out of range. I.e. the validation is done in the Model.
How is validation usually done in WPF? I have read a good deal of articles, and there seems to be some consistency in putting validation in the ViewModel. In fact, most articles only use ViewModel and View. Has the Model been buried?
Glad to see your decision to move away from custom implementations of MVVM when so much already exists that just ... works.
WPF is very strong for two way binding and that gives it its' greatest strengths.
The view model is bound to the view and acts as the mechanism to communicate with the data layer. Also Entity Framework (if you are on framework 4.0) will give you a great data layer for populating your entities in your ViewModel. This basically becomes your Model. It gives you an encapsulated form of UnitOfWork as well as Repository patterns.
While your view model in all examples are usually on a one-to-one basis, if the design calls for it you can have view models that span multiple views. I have a "menu" which displays key identifiers from each item in the list and a detail form that shows all fields for editing from the same object. So I span the view between the two.
You can hard code the view model in the xaml binding it to the datacontext or you can use Unity and inject the viewmodel into the view. Unfortunately the injection requires adding one public property for the purpose of setting the datacontext. So you'd have code like this:
public class MyView:Window
{
public MyView(MyViewModel model)
{
InitializeComponent();
ViewModel = model;
}
public MyViewModel ViewModel
{
set{ this.DataContext = value; }
}
}
So the rest is just TwoWay binding for each field and the setter can encapsulate single value editing. Your error message can even be bound to a text field on the form and it displays when the value is not null.
Also if you dig into Unity you will also get a truly great function called Event Aggregation which basically provides a vehicle for publish/subscribe of events and that ties into your ICommand implementation when getting a button click handled.
in my ASP MVC 2 application I follow the strongly typed view pattern with specific viewmodels.
Im my application viewmodels are responsible for converting between models and viewmodels. My viewmodels I have a static ToViewModel(...) function which creates a new viewmodel for the corresponding model. So far I'm fine with that.
When want I edit a model, I send the created viewmodel over the wire and apply the changes to back to the model. For this purpose I use a static ToModel(...) method (also declared in the view model). Here the stubs for clarification:
public class UserViewModel
{
...
public static void ToViewModel(User user, UserViewModel userViewModel)
{
...
}
public static void toModel(User user, UserViewModel userViewModel)
{
???
}
}
So, now my "Problem":
Some models are complex (more than just strings, ints,...). So persistence logic has to be put somewhere.(With persistence logic I mean the decisions wheater to create a new DB entry or not,... not just rough CRUD - I use repositories for that)
I don't think it's a good idea to put it in my repositories, as repositories (in my understanding) should not be concerned with something that comes from the view.I thought about putting it in the ToModel(...) method but I'm not sure if thats the right approach.
Can you give me a hint?
Lg
warappa
Warappa - we use both a repository pattern and viewmodels as well.
However, we have two additonal layers:
service
task
The service layer deals with stuff like persisting relational data (complex object models) etc. The task layer deals with fancy linq correlations of the data and any extra manipulation that's required in order to present the correct data to the viewmodel.
Outwith the scope of this, we also have a 'filters' class per entity. This allows us to target extension methods per class where required.
simples... :)
In our MVC projects we have a seperate location for Converters.
We have two types of converter, an IConverter and an ITwoWayConverter (a bit more too it than that but I'm keeping it simple).
The ITwoWayConverter contains two primary methods ConvertTo and ConvertFrom which contain the logic for converting a model to a view model and visa versa.
This way you can create specific converts for switching between types such as:
public class ProductToProductViewModelConverter : ITwoWayConverter<Product,ProductViewModel>
We then inject the relevant converters into our controller as needed.
This means that your conversion from one type to another is not limited by a single converter (stored inside the model or wherever).