Composition coupled with edtiro templates will give you the easiest code reuse possibilities.
Each view model that needs this information needs a reference to the shared view model.
public class AddEditOrderDetails
{
[Display(Name = "Unit Price")]
[Required]
public decimal UnitPrice { get; set; }
[Display(Name = "Quantity")]
[Required]
public int Quantity { get; set; }
public decimal ExtendedPrice => UnitPrice * Quantity;
}
public class AddEditFoo
{
public AddEditOrderDetails Details { get; set; }
}
public class AddEditBar
{
public AddEditOrderDetails Details { get; set; }
}
Notice that the AddEditOrderDetails view model has the ExtendedPrice
which multiples the quantity and unit price.
Then create a new partial view called Views/Shared/EditorTemplates/AddEditOrderDetails.cshtml
that has the form fields (minus a field for ExtendedPrice, since this is a calculated property).
In each of the other pages:
@Html.EditorFor(model => model.Details)
Will render all the fields in the editor template, and run all associated validations.
Update: To avoid constantly mapping entities to the same view model, you can specify a common interface for your entities, and then pass the entities to a constructor on the view model that accepts the interface.
First, the define the interface to be the simplest you need it to be:
public interface IOrderLineItem
{
public decimal UnitPrice { get; }
public int Quantity { get; }
}
Then implement this interface in the entity classes:
public class Entity1 : IOrderLineItem
{
...
}
public class Entity2 : IOrderLineItem
{
...
}
Now add a few constructors to your view model to do the mapping work for you:
public class AddEditOrderDetails
{
...
// For the MVC model binder or a new order line item
public AddEditOrderDetails()
{
}
// For editing an existing order line item
public AddEditOrderDetails(IOrderLineItem orderLineItem)
{
UnitPrice = orderLineItem.UnitPrice;
Quantity = orderLineItem.Quantity;
}
}
Now mapping from entity to view model is easy:
var model = new MainPageViewModel1()
{
Details = new AddEditOrderDetails(entity1)
};
var model = new MainPageViewModel1()
{
Details = new AddEditOrderDetails(entity2)
};
var model = new MainpageViewModel()
{
Items = mainEntity.SubEntities1
.Select(s => new AddEditOrderDetails(s))
.ToList()
}