I have a parent and child domain object being mapped to a single ViewModel object. E.G.
class Parent
{
public int ID {get;set;}
public string Name {get;set;}
public Child Child {get;set;}
}
class Child
{
public int ID {get; set;}
public string Name {get; set;}
}
class ParentChildVM
{
public int ID {get;set;}
public string Name {get;set;}
public int ChildID {get;set;}
public string ChildName {get; set;}
}
The types are mapped in static configuration file and it just uses the built in naming conventions to map the properties and achieve the flattening.
I'm using this ParentChildVM with an ASP.NET MVC view that puts ID and Name in form inputs, but only displays ChildID and ChildName. Since the Child's properties are not in form fields, they are not posted back to the server upon saving and are empty in the ParentChildVM that is reconstructed from the posted values.
So I want to remap the Child domain object to my ParentChildVM to fill in the missing properties. But I don't want to map the Parent again because it would overwrite the edited values. Is there any way to map a given Child instance into my existing ParentChildVM with AutoMapper (v6.1.1.0)?
EDIT:
I guess I know I could add a mapping from Child -> ParentChildVM and then use .ForMember to tell it how to map ChildID and ChildName, but in reality there are a lot more properties so what I'm asking is: is there a way to do it and still take advantage of the naming-convention-based mapping? I.E. keep using the "Auto" part of AutoMapper.
Related
If I have a database and I base all my models on the database (using LINQ basically to fetch/set the data). Is it possible to only use a part of those models to create my views? Say I have three columbs in a table, and I only need two for my view, can I simply use two of the three using my database model or should I create a new model to use in my views.
And if I have to create new models, any simple way to do this? I'm using Visual Studio 2015.
Thank you
It is common to create View Models to represent a slice of your domain model when putting data in a view.
For example you may have a BookViewModel and a BookEditModel. You could show and permit editing of different fields depending on the model.
class BookViewModel
{
[ReadOnly]
public string ISBN { get; set;}
[ReadOnly]
public string Title { get; set;}
[ReadOnly]
public string Author { get; set;}
}
class BookEditModel
{
[ReadOnly]
public string ISBN { get; set;}
[Validate(...)]
public string Title { get; set;}
[Validate(...)]
public string Author { get; set;}
[ReadOnly]
public DateTime LastUpdated {get;set;}
}
If you're looking into an easy way to create these view models, there is a tool called AutoMapper that allows you to easily map between domain and view models.
I am building a Web Application where i am creating a dynamic form where user can create different field to make his or her own form.Then i want the application build their model dynamically based on the form fields.At the end database table will be created from that generated model and field value will be inserted as table data.Any suggestion or solution is highly appreciated.
I personally would shy away from trying to create the database table dynamically, but take an approach where you store the fields in a table, and relate them to a form object. Something like this:
public Form
{
[Key]
public int FormId {get;set;}
public string Name {get;set;}
public IList<Field> {get;set;}
}
public Field
{
[Key]
public int FieldId {get;set;}
public string FieldName {get;set;}
public string FieldValue {get;set;}
[ForeignKey("FormId")]
public Form Form {get;set;}
public int FormId {get;set;}
}
With this structure, creating a form would simply be a case of creating a Form object, and then you can just simply add as many Field objects to it as you wish. Each Field object can be named anything that you want, and would be unique to the Form it is associated to
Here is the situation I am struggling with.
I have an Object Model:
public class MyModel
{
public string Prop1 {get; set;}
public string Prop2 {get; set;}
//etc
}
Then I have Object ModelView
public class MyModelView
{
public MyModel MyModelObject;
public SelectList PropToBeSelected1 {get; set;}
public SelectList PropTobeSelected2 {get; set;}
//etc
}
I have the MyModelRepository class as well that does the delete, update operations for MyModel.
All good and clear so far.
Question:
PropToBeSelected1 and PropTobeSelected2 are drop down lists whose contents come from the database. Should the methods retrieving these contents be put in my MyModelRepository? Or should I create another repository for ViewModel?
Thank you.
First you really don't want domian-ish objects in your viewModel. Your viewModel should be clean with only primitives (like strings, ints... etc). So I'd suggest using a AutoMapper to map your two string props to your viewModel.
With the select list, there are many ways to go about this but I can imagine if they are lists of properties then they are not actual entities, but value objects instead. In this case creating a repository for them is over kill and boarders bad design.
I'd put the 'get' of the property lists in your MyModelRepository. Something like
_myModelRepository.getProperties1For(myModel);
Then AutoMap again on to get your select list.
Edit:
Like #M.Radwan pointed out for complex domain models I'll make viewModels insdie viewModels for easy of mapping.
Domain Model--
public class User : Entity
{
public Address Address { get; set; }
}
public class Address
{
public string Street { get; set; }
public string Zip { get; set; }
}
would map to
public class DetailsViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public AddressViewModel Address { get; set; }
public class AddressViewModel
{
public string Street { get; set; }
public string Zip { get; set; }
}
}
which in our experience has been the only reason to add any complexity to your viewModel. We will put SelectLists in our viewModel though but lately we've been using IEnumerables of inner viewModels and calling custom EditorFor or DisplayFor to turn them into a dropdown / list of checkboxes / radio buttons.
The answer is NO, you should not make any repository for them if you really need them with this view. so they probably are value objects as #jasonhooten said and they should connected to the main aggregate object that used by the repository
Finally I don't decide the ViewModel structure until I finish the view and make it working first and this why I founder and create DevMagicFake, by using DevMagicFake you will delay all decisions of the design regarding the structure of the ViewModel or the repository or how you will use service layer, all this will be delayed after full complete your view and make it working first as BDD (Behavior Driven Development) and TDD (Test Driven Development) so you can take the right decisions of the design and the object model itself
So I just create the action method as the following
public ActionResult List(MyModelView myModelView)
{
FakeRepository<MyModelView> repository = new FakeRepository<MyModelView>();
repository.Add(myModelView);
}
This fake repository will enable me to save and retrieve my whole model even it's a complex model until I finish and complete the whole view and make it working first, and then I start thanking on how the real design and the real repository should looks like, and do on
For more information about DevMagicFake and this approach see this link
DevMagicFake on CodePlex
Validating a form with Data Annotations using MVC.
Are you to define all properties of an input object parameter as string with data annotations so one can check the model state to catch errors, or should I just use the native data types for objects?
I created numerous "control function" models in bound which are identical to the View Models with the exception of Regex validators and "string" for each field.
Doing this seems to be unnecessary complexity. Just want to make sure I am on the right track, or that the double data models is something that MVC normally handles anyway.
For example:
public class Product
{ public int id {get;set;}
public string name {get;set;}
public double? retailPrice {get;set;}
[Required]
public int deptId {get;set;}
[Required]
public bool active {get;set;}
}
public class Product
{ [RegularExpression(#"^\d*$", ErrorMessage = "*")]
public string id {get;set;}
public string name {get;set;}
[RegularExpression(#"^\d*$", ErrorMessage = "*")]
public string retailPrice {get;set;}
[RegularExpression(#"^\d+$", ErrorMessage = "*")]
public string deptId {get;set;}
[RegularExpression(#"(?i)^true$|^false$", ErrorMessage = "*")]
public string active {get;set;}
}
Could just use the first as the inbound object, or use the second and convert to the first upon successful validation.
You should define your view models to have properties (or fields) with the correct data type. There is no requirement for them to be strings. If you have defined a property to be of type int and the model binder binds the request data to it, but cannot coerce the value to an int then the property will not be set and the model state will indicate that there is an error.
Some people have the concern of wanting to rerender the page and still have the user value in the textbox to allow them to correct it. If you use the built in Html helper methods, then this will be done for you as it looks to see if there is a model state error for that field and if there is, it will try and find the value from the request data and use that instead.
let's say we have something like this
public class Person
{
public string Name {get; set;}
public Country Country {get; set;}
}
public class PersonViewModel
{
public Person Person {get; set;}
public SelectList Countries {get; set;}
}
can automapper be used to perform to parse from Person into PersonViewModel and back ?
Don't use AutoMapper for this - it's not worth it. For example, in the cases where you have a validation failure and you show the form again - AutoMapper is not executed here (usually). We usually go two routes:
If the list is not context-specific, create an HtmlHelper that queries some ISelectListProvider for the select list items: Html.DropDownList(). You'd use your IoC container of choice to locate the personListProvider, query for the list of items, and populate the dropdown list.
If the list is context-specific, just construct the list in the controller action
It sounds like you want to send a Person to the view via the PersonViewModel which has all the bonus info you need to generate and return a new (or updated) Person object.
If this is correct, I don't think you need automapper at all. From what I understand of automapper it is for mapping collection of related objects to a more view model type of state, but in this case, you are sending a Person to the client and trying to receive a Person back. In this case, it seems easier to use your view model to populate the page, but have the page return a Person instead (or extract the updated Person from the view model to save a few keystrokes).
EDIT: That being said, yes you should be able to use automapper to move the info around. Its just a unnecessary layer for this easy scenario.
if one chose to, you could do this:
public class Person
{
public string Name {get; set;}
public Country Country {get; set;}
public Country[] GetCountries
{
... add method for countries here
}
}
Then in your ViewModel you can have your select list pull data from that collection.
public class PersonViewModel
{
public Person Person {get; set;}
public Country[] Countries {get; set;}
public SelectList Countries { get{ .. add new select list code here getting vals from Countries..}}
}
Again, this is for context sensitive lists. You are however muddling concerns a wee bit here (should a person get a list of countries?)