I have created a UserSiteBaseController that gets commonly used data and sets the data to a UserSiteBaseViewData viewmodel in a method called SetViewData
public T CreateViewData<T>() where T : UserSiteBaseViewData, new()
{
....
}
I then create specific Controllers that inherit from the UserSiteBaseController as well as viewModels that inherit from UserSiteHomeViewData and can be created in the controller like so:
public ActionResult Index(string slug)
{
Slug = slug;
var viewData = CreateUserSiteHomeViewData<UserSiteHomeViewData>();
//If invalid slug - throw 404 not found
if (viewData == null)
return PageNotFound();
viewData.Announcements = _announcementsData.All(slug).ToList();
return View(viewData);
}
private T CreateUserSiteHomeViewData<T>() where T : UserSiteHomeViewData, new()
{
T viewData = CreateViewData<T>();
return viewData;
}
The UserBaseViewData holds data that needs to be use on every page so it would be great to be able to access this data from the Masterpage in a strongly typed manner. Is this possible or am I going about this in the incorrect manner?
If you get your masterpage to inherit from System.Web.Mvc.ViewMasterPage<BaseViewModel> you should be good to go...?
BUT, when I first started using MVC I went down the same route using a BaseViewModel class which contained all my generic ViewModel stuff and then I created specific view models, e.g. EventListingViewModel, which inherited from this BaseViewModel - much like you are doing. My masterpages then inherited from System.Web.Mvc.ViewMasterPage<BaseViewModel> and everything was going swell.
But after a while it all became a bit tightly coupled and a quite brittle. It became a pain in the ass to make changes and what not. I also came across this issue.
So I've reverted back to using the standard ViewData dictionary (with a static VewDataKeys class to avoid magic strings) for all my generic properties and then using custom POCO objects that don't inherit from anything as my presentation models. This is working much better and I wouldn't change back.
HTHs,
Charles
Related
I have some doubts about what are the best practices for MVVM using parent-child model relations.
In that specific case there are two models (data classes) called Group and Contact. The group is containing a list of contacts. Both of them are are implementing INotifyPropertyChanged interface.
In the view, there is a treeview displaying the hierarchy using DataTemplate and the associated ViewModel contains an ObservableCollections property.
I am wondering what is the best practice design in this case.... Having one property like above in the ViewModel which is bind to the xaml or createing a ViewModel for each model (like GroupViewModel and ContactViewModel) and instead of ObservableCollections having an List.
What is the best way (design wise)? Shoudl I bind the Model or the ViewModel to the xaml?
I'm afraid, you mixed some things up. The basics of MVVM are
Model - Contains the data the application is working with. It should be kept as simple as possible.
ViewModel - Reflects the state of the application and contains the business logic. It's the business layer.
View - Interprets the ViewModel to provide a visual representation of the business layer and its state.
With this three parts, it's pretty easy to provide separation of concerns and a decoupled architecture. If you want to read more, click here.
Back to your questions:
In that specific case there are two models (data classes) called Group and Contact. The group is containing a list of contacts. Both of them are are implementing INotifyPropertyChanged interface.
That's a bit odd. Usually, you don't need to implement INotifyPropertyChanged in the model classes, since the VM should handle value changes from the view.
But it's imaginable to have that mechanism in the model layer too. But since you don't want to track changes on this layer and IMHO the VM should take care about, you don't need it.
[...] Having one property like above in the ViewModel which is bind to the xaml or createing a ViewModel for each model (like GroupViewModel and ContactViewModel) [...]
Yes, this is usually the approach. For each model class, which should be passed to the view layer, you would create a ViewModel.
[...] and instead of ObservableCollections having an List.
That's definitely a No. If you use a List<T>, the view would not be aware of the changes (add, remove) to collection.
What is the best way (design wise)? Shoudl I bind the Model or the ViewModel to the xaml?
Simply stick to MVVM. The view is aware of the VM, but the VM is not aware of the view. Additionally the VM is aware of the model, but the model isn't aware of it. That implies, that you should always bind the VM to the View.
Edit
The following is totally legit.
public class Address : ViewModelBase // implements INotifiedPropertyChanged a.s.o.
{
public string Street { /* you know what comes here */ }
public string ZipCode { /* ... */ }
public string City { /* ... */ }
/* more properties */
}
public class Person : ViewModelBase
{
public string Name { /* ... */ }
public Address Address { /* ... */ }
}
Using EF with Winforms in C#. I’d like to add full custom properties to our entities, using partial classes. All entities already have partial classes with validation stuff and some more so I’d just add the properties that I need. By full property I mean property with getter and setter so not just a computed/readonly property. I want to this mostly to get around working directly with some DB mapped properties which are badly designed or have other problems.
For example, one case would be like this:
// entity class, generated
public partial class Customer
{
public string Spot {get;set}
}
// partial class, manually changed
public partial class Customer
{
public int? xxxSpot
{ get { return Int32.Parse(Spot.Trim()); } // some code omitted
{ set { Spot = value.ToString().PadLeft(5); }
}
So my custom properties will be built around existing, DB mapped properties of the entity. I’d like to use these custom properties like normal ones, ie to bind them to UI controls and so on. I’ve tried one and so far it works great.
Is this a good idea? If not, why ? And what else should I consider when doing this?
You have answered your own question - it works and there is no reason why to not do that. If you want to improve design of your entities you can even try to change visibility of your mapped properties to ensure that other classes must use only your custom properties with additional logic.
When using the examples for Single Page Application, I've the following TodoItem controller:
public partial class MVC4TestController : DbDataController<MVC4TestContext>
{
public IQueryable<TodoItem> GetTodoItems()
{
return DbContext.TodoItems.OrderBy(t => t.TodoItemId);
}
}
Question 1:
It seems that only EntityModels are supported ?
When using a real ViewModel (model only used for the Views, not not used as 1:1 mapping to database entity), the DbDataController does not support this.
Also using Linq.Translations or PropertyTranslator does not seem to work, see this code extract:
private static readonly CompiledExpressionMap<TodoItem, string> fullExpression =
DefaultTranslationOf<TodoItem>.Property(t => t.Full).Is(t => t.Title + "_" + t.IsDone);
public string Full
{
get
{
return fullExpression.Evaluate(this);
}
}
Question 2:
What is the recommended design when using SPA, DBContext and ViewModels ?
As far as I know so far is - it instists on the usage of "real" model classes bound to DbContext.
I have the same problem as you - I need to use my own DTO objects which are "flat".
The Json serialisation is currently not able to serialize data which has parent references in child objects (cyclic references). Usually I do not need the entity tree anyways so I created smaller classes which fits perfectly to the view.
I tried to use a normal Controller with JsonResult and parsed the returned model into ko.mapping.fromJS after retrieved the data. Thats working fine. But - you have to take care of all the nice stuff the MVC4 generated viewmodels are already dealing with (like creating navigation, etc.).
Maybe someone finds a workaround to "fake" a DbContext with DTO data.
I am finding it difficult understanding how best to implement 'IView' interface properties which are not simple types, and was wondering how others approach this in a Model View Presenter application.
The articles i've read are really good but none of them seem to approach more complex Views where you have List<> properties which are of an interface type which represent a class in your domain model, i.e. IPerson, or IName etc.
I will try to outline a scenario as briefly as i possibly can.
Presume i have a requirement for a View to ultimately persist a list of names, each consisting of 3 properties 'Forename', 'Surname', and 'Title'.
Typically i will have a domain model with a class called 'Name' with the 3 properties. This domain model will implement an Interface (in a separate 'Interfaces' class Library) called 'IName'.
Now in the 'Views' namespace in my 'Interaces' library i have an interface called 'IViewNames'. This is the view interface which any view which wants to ultimately persist the list of names will implement.
How to define this 'IViewNames' interface puzzles me. If i give it a property like so:
public List<IName> Names {get;set;}
then my implementing concrete view will ultimately have a complex property 'Names' which will need a 'getter' which loops through the fields on the View, somehow instantiate an instance of 'IName', set its properties, add to a List, before returning the List. The 'setter' will be just as complex, receiving a list of 'INames' and iterating through them setting fields on the View.
I feel like this is breaking one of the major goals of the MVP approach, which is being able to thoroughly test the application code without any concrete View implemntations. After all, i could easily write a presenter which looks at the 'View.Names' property and sends it on to a Service Layer, or set the 'View.Names' property when receiving a list of 'Name' objects back from the Service Layer. I could easily write a lot of tests which ensure everything works, everything except from that COMPLEX property in the View.
So my question is, how do others approach IView properties which are not simple types, but are in fact types of your domain model? (well types of interfaces which represent your domain model, as i clearly dont want a reference from my Presentation Layer to my Domain Model layer).
I'm more than certain there is a known technique to achieving this in an elegant way, which adheres to the Model View Presenter goals, more than my example approach does.
Thanks in advance for any help people.
I have not worked much on the MVP design pattern but will surely try my hands on it.
Approach1 : DataBinding
In this case you can also create individual properties in IView and bind these properties in presenter to the model properties. This way, your view will not get complicated. The experience is fast and seamless as the values from UI can be directly used in model. Changing the property value in model will reflect in UI immedietly. You may have to use NotifyPropertyChange events for this.
Approach 2 : Complex Types
You can try creating List or Tuples to store these values and use the values in the presenter. You may have to use events or actions to reflect the value from model to view and vice versa.
Please let me know if it helped you. Thanks.
I have lifted this explanation from one of the articles I am writing on my website
Presenter to View Communication
There are two styles utilised for populating the View with data from the Presenter and Model that I have used. The only difference between them is how tightly coupled you mind your View being to the Model. For the example of this, we will have the following as our Model:
public class Person
{
public int ID { get; private set; }
public int Age { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
Public Genders Gender { get; set; }
}
Method 1: Using the Model
Now our View code:
public interface IEmployeesView
{
void ClearList();
void PopulateList(IEnumerable<Person> people);
}
And finally the Presenter:
public class IEmployeesPresenter
{
public void Display()
{
_view.ClearList();
_view.PopulateList(_model.AllEmployees);
}
}
This method of population produces a link between the Model and the View; the Person object used as a parameter in PopulateList.
The advantage of this is that the concrete implementation of the IEmployeesView can decide on what to display in its list of people, picking from any or all of the properties on the Person.
Their are two disadvantages of this method. The first is that there is nothing stopping the View from calling methods on the Person, which makes it easy for lazy code to slip in. The second is that if the model were to change from a List<Person> to a List<Dog> for instance, not only would the Model and the Presenter need to change, but so the View would too.
Method 2: Using Generic Types
The other method population relies on using Tuple<...>, KeyValuePair<,> and custom classes and structs:
Now our View code:
public interface IEmployeesView
{
void ClearList();
void PopulateList(IEnumerable<Tuple<int, String> names);
}
And finally the Presenter:
public class IEmployeesPresenter
{
public void Display()
{
var names = _model.AllEmployees.Select(x => new Tuple<int, String>(x.ID, x.FirstName + " " + x.LastName));
_view.ClearList();
_view.PopulateList(names);
}
}
The advantages of this method of population is that the Model is free to change without needing to update the View, and the View has no decisions to make on what to display. It also prevents the View from calling any extra methods on the Person, as it does not have a reference to it.
The down sides to this method, are that you loose strong typing, and discoverability - It is quite obvious what a Person is but what a Tuple<int, String> is less obvious.
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).