Rich Domain Model Implementation - c#

I recently started reading about rich domain model instead of anemic models. All the projects I worked on before, we followed service pattern. In my new new project I'm trying to implement rich domain model. One of the issues I'm running into is trying to decide where the behavior goes in (in which class). Consider this example -
public class Order
{
int OrderID;
string OrderName;
List<Items> OrderItems;
}
public class Item
{
int OrderID;
int ItemID;
string ItemName;
}
So in this example, I have the AddItem method in Item class. Before I add an Item to an order, I need to make sure a valid order id is passed in. So I do that validation in AddItem method. Am I on the right track with this? Or do I need create validation in Order class that tells if the OrderID is valid?

Wouldn't the Order have the AddItem method? An Item is added to the Order, not the other way around.
public class Order
{
int OrderID;
string OrderName;
List<Items> OrderItems;
bool AddItem(Item item)
{
//add item to the list
}
}
In which case, the Order is valid, because it has been created. Of course, the Order doesn't know the Item is valid, so there persists a potential validation issue. So validation could be added in the AddItem method.
public class Order
{
int OrderID;
string OrderName;
List<Items> OrderItems;
public bool AddItem(Item item)
{
//if valid
if(IsValid(item))
{
//add item to the list
}
}
public bool IsValid(Item item)
{
//validate
}
}
All of this is in line with the original OOP concept of keeping the data and its behaviors together in a class. However, how is the validation performed? Does it have to make a database call? Check for inventory levels or other things outside the boundary of the class? If so, pretty soon the Order class is bloated with extra code not related to the order, but to check the validity of the Item, call external resources, etc. This is not exactly OOPy, and definitely not SOLID.
In the end, it depends. Are the behaviors' needs contained within the class? How complex are the behaviors? Can they be used elsewhere? Are they only needed in a limited part of the object's life-cycle? Can they be tested? In some cases it makes more sense to extract the behaviors into classes that are more focused.
So, build out the richer classes, make them work and write the appropriate tests Then see how they look and smell and decide if they meet your objectives, can be extended and maintained, or if they need to be refactored.

First of all, every item is responsible of it's own state (information). In good OOP design the object can never be set in an invalid state. You should at least try to prevent it.
In order to do that you cannot have public setters if one or more fields are required in combination.
In your example an Item is invalid if its missing the orderId or the itemId. Without that information the order cannot be completed.
Thus you should implement that class like this:
public class Item
{
public Item(int orderId, int itemId)
{
if (orderId <= 0) throw new ArgumentException("Order is required");
if (itemId <= 0) throw new ArgumentException("ItemId is required");
OrderId = orderId;
ItemId = itemId;
}
public int OrderID { get; private set; }
public int ItemID { get; private set; }
public string ItemName { get; set; }
}
See what I did there? I ensured that the item is in a valid state from the beginning by forcing and validating the information directly in the constructor.
The ItemName is just a bonus, it's not required for you to be able to process an order.
If the property setters are public, it's easy to forget to specify both the required fields, thus getting one or more bugs later when that information is processed. By forcing it to be included and also validating the information you catch bugs much earlier.
Order
The order object must ensure that it's entire structure is valid. Thus it need to have control over the information that it carries, which also include the order items.
if you have something like this:
public class Order
{
int OrderID;
string OrderName;
List<Items> OrderItems;
}
You are basically saying: I have order items, but I do not really care how many or what they contain. That is an invite to bugs later on in the development process.
Even if you say something like this:
public class Order
{
int OrderID;
string OrderName;
List<Items> OrderItems;
public void AddItem(item);
public void ValidateItem(item);
}
You are communicating something like: Please be nice, validate the item first and then add it through the Add method. However, if you have order with id 1 someone could still do order.AddItem(new Item{OrderId = 2, ItemId=1}) or order.Items.Add(new Item{OrderId = 2, ItemId=1}), thus making the order contain invalid information.
imho a ValidateItem method doesn't belong in Order but in Item as it is its own responsibility to be in a valid state.
A better design would be:
public class Order
{
private List<Item> _items = new List<Item>();
public Order(int orderId)
{
if (orderId <= 0) throw new ArgumentException("OrderId must be specified");
OrderId = orderId;
}
public int OrderId { get; private set; }
public string OrderName { get; set; }
public IReadOnlyList<Items> OrderItems { get { return _items; } }
public void Add(Item item)
{
if (item == null) throw new ArgumentNullException("item");
//make sure that the item is for us
if (item.OrderId != OrderId) throw new InvalidOperationException("Item belongs to another order");
_items.Add(item);
}
}
Now you have gotten control over the entire order, if changes should be made to the item list, it has to be done directly in the order object.
However, an item can still be modified without the order knowing it. Someone could for instance to order.Items.First(x=>x.Id=3).ApplyDiscount(10.0); which would be fatal if the order had a cached Total field.
However, good design is not always doing it 100% properly, but a tradeoff between code that we can work with and code that does everything right according to principles and patterns.

I would agree with the first part of dbugger's solution, but not with the part where the validation takes place.
You might ask: "Why not dbugger's code? It's simpler and has less methods to implement!"
Well the reason is that the resulting code would be somewhat confusing.
Just imagine someone would use dbuggers implementation.
He could possibly write code like this:
[...]
Order myOrder = ...;
Item myItem = ...;
[...]
bool isValid = myOrder.IsValid(myItem);
[...]
Someone who doesn't know the implementation details of dbugger's "IsValid" method would simply not understand what this code is supposed to do.
Worse that that, he or she might also guess that this would be a comparison between an order and an item.
That is because this method has weak cohesion and violates the single responsibility principle of OOP.
Both classes should only be responsible for validating themself.
If the validation also includes the validation of a referenced class (like item in Order), then the item could be asked if it is valid for a specific order:
public class Item
{
public int ItemID { get; set; }
public string ItemName { get; set; }
public bool IsValidForOrder(Order order)
{
// order-item validation code
}
}
If you want to use this approach, you might want to take care that you don't call a method that triggers an item validation from within the item validation method. The result would be an infinite loop.
[Update]
Now Trailmax stated that acessing a DB from within the validation-code of the application domain would be problematic and that he uses a special ItemOrderValidator class to do the validation.
I totally agree with that.
In my opinion you should never access the DB from within the application domain model.
I know there are some patterns like Active Record, that promote such behaviour, but I find the resultig code always a tiny bit unclean.
So the core question is: how to integrate an external dependency in your rich domain model.
From my point of view there are just two valid solutions to this.
1) Don't. Just make it procedural. Write a service that lives on top of an anemic model. (I guess that is Trailmax's solution)
or
2) Include the (formerly) external information and logic in your domain model. The result will be a rich domain model.
Just like Yoda said: Do or do not. There is no try.
But the initial question was how to design a rich domain model instead of an anemic domain model.
Not how to design an anemic domain model instead of a rich domain model.
The resulting classes would look like this:
public class Item
{
public int ItemID { get; set; }
public int StockAmount { get; set; }
public string ItemName { get; set; }
public void Validate(bool validateStocks)
{
if (validateStocks && this.StockAmount <= 0) throw new Exception ("Out of stock");
// additional item validation code
}
}
public class Order
{
public int OrderID { get; set; }
public string OrderName { get; set; }
public List<Items> OrderItems { get; set; }
public void Validate(bool validateStocks)
{
if(!this.OrderItems.Any()) throw new Exception("Empty order.");
this.OrderItems.ForEach(item => item.Validate(validateStocks));
}
}
Before you ask: you will still need a (procedural) service method to load the data (order with items) from the DB and trigger the validation (of the loaded order-object).
But the difference to an anemic domain model is that this service does NOT contain the validation logic itself.
The domain logic is within the domain model, not within the service/manager/validator or whatever name you call your service classes.
Using a rich domain model means that the services just orchestrate different external dependencies, but they don't include domain logic.
So what if you want to update your domain-data at a specific point within your domain logic, e.g. immediately after the "IsValidForOrder" method is called?
Well, that would be problem.
If you really have such a transaction-oriented demand I would recommend not to use a rich domain model.
[Update: DB-related ID checks removed - persistence checks should be in a service]
[Update: Added conditional item stock checks, code cleanup]

If you go with Rich Domain Model implement AddItem method inside Order. But SOLID principles don't want you validation and other things inside this method.
Imagine you have AddItem() method in Order that validates item and recalculate total order sum including taxes. You next change is that validation depends on country, selected language and selected currency. Your next change is taxes depends on country too. Next requirements can be translation check, discounts etc. Your code will become very complex and difficult to maintenance. So I thing it is better to have such thing inside AddItem:
public void AddItem(IOrderContext orderItemContext) {
var orderItem = _orderItemBuilder.BuildItem(_orderContext, orderItemContext);
_orderItems.Add(orderItem);
}
Now you can test item creation and item adding to the order separately. You IOrderItemBuilder.Build() method can be like this for some country:
public IOrderItem BuildItem(IOrderContext orderContext, IOrderItemContext orderItemContext) {
var orderItem = Build(orderItemContext);
_orderItemVerifier.Verify(orderItem, orderContext);
totalTax = _orderTaxCalculator.Calculate(orderItem, orderContext);
...
return orderItem;
}
So you can test and use separately code for different responsibility and country. It is easy to mock each component, as well as change them at runtime depending on user choice.

To model a composite transaction, use two classes: a Transaction (Order) and a LineItem (OrderLineItem) class. Each LineItem is then associated with a particular Product.
When it comes to behavior adopt the following rule:
"An action on an object in the real world, becomes a service (method) of that object in an Object Oriented approach."

Related

how to ensure that the editing (IsEdited or whatever) state of an EFCore entity is notified

I've got a class Invoice that has InvoiceRows.
public class Invoice
{
[Key]
public int? Id { get; set; }
public DateTime InvoiceDate {
get => invoiceDate;
set => PropertySet<DateTime>(value, ref invoiceDate);
}
private DateTime invoiceDate;
public List<InvoiceRow> Rows { get; } = new List<InvoiceRow>();
[NotMapped]
public bool IsEdited { get; set; } = false;
public void PropertySet<T>(T value, ref T field)
{
if (value.Equals(field)) return;
field = value;
IsEdited = true;
}
}
The Invoice is edited in a WPF graphical interface that need notifications when the invoice has been edited in order to activate the save button, for example.
(In a first implementation i thought that IsEdited was a viewmodel thing and I omitted it from the model and included in the viewmodel instead. Turns out to be quite complex when handling sub-records. However I've not yet fully realized which option the model or the viewmodel implementation is best, and this is possibly a second question.)
The IsEdited is easily managed at record level, but how to handle it at the InvoiceRow level?
The first idea that comes to mind is to notify back to the main record.
This in turn requires additional code to wire up notifications between Invoice and Rows.
Another idea is to leverage the DbContext state that holds in one place the required information instead of gathering it around sub-records.
Are there any other options left? One of the challages of such decision is to fully evaluate the consequences of each approach before hand. What are the pros/cons of different ways of handling this?
In my little experience of WPF I've read something about hirearchical viewmodels. Maybe they are suitable for this, handling the wrap-up at the viewmodel level?

Which class should be responsible for certain actions?

I am making a Storage System Application. Each storage system contains up to 10 Warehouses capable of storing Stock Items.
I want to create a method for updating a Warehouse properties (Name, Description etc). There is a business rule that each Warehouse within a storage system must have a unique name, and im unsure which class should be responsible for this. Im trying to stick to the principle that each class should only be responsible for itself.
Here is a simple mock up of the code (C#)
public class StorageSystem
{
public List<Warehouse> Warehouses{Get;}
}
public class Warehouse
{
public string Name{Get; private Set;}
public int StorageSystemId{Get; Set;}
public StorageSystem Sotrage System{Get; Set;}
}
I think i should do the following,
Step1. Create a method in StorageSystem class.
public bool WarehouseNameAvailable(string name)
{
//Check List of Warehouses for the name
//if found return false
//else return true
}
Step2. Create a method in the Warehouse
public void UpdateWarehouseName(string name)
{
if(StorageSystem.WarehouseNameAvailable(name))
{
this.name = name;
}
else
{
//Throw Exception
{
}
Is this the "proper and correct" way to do this?
Is this the "proper and correct" way to do this?
This highly depends on your overall application architecture, imho. Ask 5 developers whether your solution is "proper and correct" and you will get 6 opinions.
To get to the point: When purely relating on DDD concepts, your solution seems at least possible. But to be honest, i've never come across an enterprise application of notable size that was able to project its business logic entirely in the domain model in a structured (!) and maintainable (!) way and did not need some kind of service layer upon it. I personally like this approach and would recommend pojecting this requirements in separate classes, that represent business/use cases:
public class RenameAction {
//Some Kind of DbSet, Database Connection, external service,...
//I'll go with an EF - DbSet<Warehouse> in this example
private readonly DbSet<Warehouse>_warehouses;
private readonly DbSet<StorageSystem> _storageSystem;
public void Execute(int storageSystemId, int warehouseId, string name) {
var storageSystem = _storageSystems.Single(system => system.Id == storageSystemId);
if (_storageSystem.Warehouses.Any(wh => wh.Name == name))
throw new BusinessLogicException("Warehouse names must be unique within storage systems!");
var warehouse = storageSystem.Warehouses.Single(wh => wh.Id == warehouseId);
warehouse.Name = name;
//Write back the updated warehouse to whereever, this won't work with an DbSet<Warehouse>.
_warehouses.Update(warehouse);
}
}
But again, this is just how I would deal with that.
Make T_WAREHOUSE.NAME unique (just assumed that your table/columns would have names like this) - database wise and handle the exception if a second entry gets written with the same name.
You could rise that error/exception up to user level too, to show users what went wrong: enter a different name please, "Super Dooper Warehouse" is already taken
Your questions text suggests that this will be a bigger project with many classes that interact with each other.
If you are not using a ORM, think about using one! It does a lot what you are trying to achive via custom methods loke your WarehouseNameAvailable workaround.
If you are using Entity Framework you can do this on your class properties via [Unique] attribute.

REST API Best practice for handling junction data

I am working on a service oriented architecture. I have 3 tables Meeting, Stakeholder and MeetingStakeholder (a junction table).
A simple representation of POCO classes for all 3 tables:
public class Meeting
{
public int Id { get; set; }
public IList<MeetingStakeholder> MeetingStakeholders { get; set; }
}
public class Stakeholder
{
public int Id { get; set; }
}
public class MeetingStakeholder
{
public int Id { get; set; }
public int MeetingId { get; set; }
public Meeting Meeting { get; set; }
public int StakeholderId { get; set; }
public Stakeholder Stakeholder { get; set; }
}
A simple representation of Meeting Dto:
public class MeetingDto
{
public int Id { get; set; }
public IList<int> StakeholderIds { get; set; }
}
In PUT action,
PUT: api/meetings/1
First I removes all existing records from MeetingStakeholder (junction table) then prepares new List<MeetingStakeholder> meetingStakeholders using meetingDto.StakeholderIds and create it.
{
List<MeetingStakeholder> existingMeetingStakeholders = _unitOfWork.MeetingStakeholderRepository.Where(x=> x.MeetingId == meetingDto.Id);
_unitOfWork.MeetingStakeholderRepository.RemoveRange(existingMeetingStakeholders);
List<MeetingStakeholder> meetingStakeholders = ... ;
_unitOfWork.MeetingRepository.Update(meeting);
_unitOfWork.MeetingStakeholderRepository.CreateRange(meetingStakeholders);
_unitOfWork.SaveChanges();
return OK(meetingDto);
}
Everything is fine to me. But my architect told me that i am doing wrong thing.
He said, in PUT action (according to SRP) I should not be removing and re-creating MeetingStakeholder records, I should be responsible for updating meeting object only.
According to him, MeetingStakeholderIds (array of integers) should be send in request body to these routes.
For assigning new stakeholders to meeting.
POST: api/meetings/1/stakeholders
For removing existing stakeholders from meeting.
Delete: api/meetings/1/stakeholders
But the problem is, In meeting edit screen my front-end developer uses multi-select for Stakeholders. He will need to maintain two Arrays of integers.
First Array for those stakeholders Ids which end-user unselect from multi-select.
Second Array for new newly selected stakeholders Ids.
Then he will send these two arrays to their respective routes as I mentioned above.
If my architect is right then I have no problem but how should my front-end developer handle stakeholders selection in edit screen?
One thing I want to clarify that my junction table is very simple, it does not contain additional columns other than MeetingId and StakeholderId ( a very basic junction). So in this scenario, does it make sense to create separate POST/DELETE actions on "api/meetings/1/stakeholders" that receives StakeholderIds (list of integers) instead of receiving StakeholderIds directly in MeetingDto??
First of all, if I am not mistaken:
you have a resource: "Meeting";
you want to update the said resource (using HTTP/PUT).
So updating a meeting by requesting a PUT on "/api/meetings/:id" seems fairly simple, concise, direct and clear. All good traits for designing a good interface. And it still respects the Single Responsibility Principle: You are updating a resource"
Nonetheless, I also agree with you architect in providing, in addition to the previous method, POST/Delete actions on "api/meetings/1/stakeholders" if the requisites justify so. We should be pragmatic at some level not to overengineer something that isn't required to.
Now if your architect just said that because of HOW IT IS PERSISTED, then he is wrong. Interfaces should be clear to the end user (frontend today, another service or app tomorrow ...), but most importantly, in this case, ignorant of its persistence or any implementation for that matter.
Your api should focus on your domain and your business rules, not on how you store the information.
This is just my view. If someone does not agree with me I would like to be called out and so both could grow and learn together.
:) Hope I Could be of some help. Cheers

Pre-processing Form data before Model validation in MVC

I am fairly new to MVC, but have quite a bit of experience in development in general, and am having an issue with MVC request life cycle it seems.
Will try to keep this simple, even tho the project is a bit complex in some areas.
I have a view bound to a view model that has a few complex list properties. These properties are displayed via checkboxes who's IDs are not directly related to any property in the model, but instead related to the IDs of the objects in the List<>. Because of this, the checked values do not automatically get applied to the model on POST.
To get around that, I added code in the Action method in the controller that parses the proper controls (in the Request.Form collection) and assigns the checked/selected value to the proper list items in the model.
This works perfectly up to a point.
Now, I also use Fluent Validation, and the problem is when performing custom validation rules when posting a new model to the server. The Validation routine is firing BEFORE the controller's action method, and thus before my processing of the list objects.
So, my question is, is there a way I can override the initial call to the model validation so I can just call the validation manually after my processing? I know I can do that which will fix the problem without overriding the initial call, but some of the validation takes a bit of time to process since it requires linq queries to a live database, so I do not want the validation to fire 2 times - that will quite literally double the time it takes to return no matter if the model is valid or not.
EDIT: Adding a example:
namespace Models
{
[Validator(typeof(MemberValidator))]
public class ViewMember
{
public int MemberID { get; set; }
public short RegionID { get; set; }
public List<PropTypeInfo> PropTypes { get; set; }
}
}
PropTypeInfo class:
public class PropTypeInfo
{
public byte ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool Selected { get; set; }
public PropTypeInfo(byte i, string n, string d, bool sel)
{
ID = i;
Name = n;
Description = d;
Selected = sel;
}
public static List<PropTypeInfo> GetAll(bool selected = false)
{
List<PropTypeInfo> output = new List<PropTypeInfo>();
OpenAccess.Context context = new OpenAccess.Context();
var list = (from f in context.Prop_Types orderby f.PropType select f).ToList();
foreach (OpenAccess.WebrentzServerPayments.Models.Prop_Type p in list)
output.Add(new PropTypeInfo(p.PropType, p.PropName, p.DisplayText, selected));
return output;
}
}
now here is the code in the view that renders the checkboxes for each item in the list:
<div class="Column Emp-PropTypes">
#foreach (WebrentzServerPayments.Models.PropTypeInfo ptype in Model.PropTypes)
{
<div style="float:right;width:20%;font-weight:bold;">
#Html.CheckBox("ptype_" + ptype.ID, ptype.Selected, new {Value=ptype.ID}) #Html.Raw(" ") #ptype.Name
</div>
}
</div>
And here is the code I use in the Controller Action method to pull that data back in to the List:
foreach (PropTypeInfo info in member.PropTypes)
info.Selected = form[string.Format("ptype_{0}", info.ID)].Contains(info.ID.ToString());
As a little background, a "PropType" is a type of property (house, condo, apartment) - there are about 2 dozen of them, and more can be added/removed at any time. The list in the class called "PropTypes" is first populated with the Name, Description and ID from a table in the database that lists all the available proptypes for that region.
We then will mark the proptypes as "selected" if the user has chosen that particular type. Those are saved to a table called Member.PropTypes (MemberID, ProptypeID).
So, at runtime the list will contain one record for each available proptype and the selected property will be set to yes if that user has selected it. That makes it easy to render the full list in the view...
Its actually quite a bit more complex as there are almost a dozen such lists, but each works the exact same way just with different data, as well as about 200 additional properties that are easier to manage. Only these lists are causing the issue.
Any help appreciated!
Dave

What is a best practice way to define select/dropdown options for view creation or db store

I'm still not yet sure on the best way to store selectlist options for front end display or db storage.
I've been using Enums at the moment, and also using description decorators (How do you create a dropdownlist from an enum in ASP.NET MVC?)
I'm now thinking that I might as well just create a full class for this stuff, so I can store the following information properly with full control:
Item Name
Full description
int for storage in db
order
Any methods to get information in anyway from the list.
Is it right I should be thinking about implementing all this myself by hand? I want a really solid way of doing this, and an enum doesn't really feel like it's going to cut it.
Is it right I should be thinking about implementing all this myself by
hand?
Yes. Enums are often leaky and insufficient abstractions that aren't always suitable for the complex domain model you actually wish to represent.
Rather than roll your own, you may want to consider Headspring's Enumeration class (via github, nuget). We use it all the time instead of enums because it's nearly as simple and is much more flexible.
An example of a "State" enumeration and using it as a select list:
public class State : Enumeration<State>
{
public static State Alabama = new State(1, "AL", "Alabama");
public static State Alaska = new State(2, "AK", "Alaska");
// .. many more
public static State Wyoming = new State(3, "WY", "Wyoming");
public State(int value, string displayName, string description) : base(value, displayName)
{
Description = description;
}
public string Description { get; private set; }
}
public IEnumerable<SelectListItem> Creating_a_select_list(State selected)
{
return State.GetAll().Select(
x => new SelectListItem
{
Selected = x == selected,
Text = x.Description,
Value = x.Value.ToString()
});
}
I'm not trying to sell you on this particular implementation, you could certainly hand code your own (the Enumeration class is only about 100 lines of code). But I definitely think you'd benefit from moving beyond basic enums. It is the right approach given the scenario you described in your question.
The first place where such information shoiuld be is the database...or any "virtual store" such as a web service that offers an interface to you db. In fact if there are other db entiies that use these values THEY MUST be represented in the database, otherwise you will run in big troubles. In fact, suppose one of such values is a string....if you don't define a table containing all possible values+a key and simply write the string as it is in other tables...it will be impossible for you to change the format of the string since it will be "spread" all over your db...On the contrary, if you just use an external key to refer to such strings...you can easily change them since the string is stored in just ONE place in your db.
Also the enumeration solution suffers of the problem that you cannot add or deleted values...so if such operations "conceptually" might make sense you cannot use an enumeration. You can use enumeration when all options "conceptually span" all possibilities, so you are sure you will never add/delete other options, such as in the case of the enumeration (yes, no, unknown).
That said, once you have your options in the db the remainder is easy...you will have DTO entities or Business entities representing them in exactly the same way you do for all other DB entities.
For visualization purposes you may have a ViewModel version of this options that might just contain key and description, and a "Repository method" that your controllers can call to have the list of all options.
Once retrieved you controllers put them in the overall page ViewViewModel...together with all other information to be shown on the page. From the ViewModel...you can access them to put them in a dropdown.
Summing up:
1) You need a DB representation of your options
2) Then you will have DTO, business layer, and View versions of this entities...as needed, exactly as for all other DB entities.
Are you looking for a one-size-fits-all solution for all your select list options? I personally advocate choosing the option that best fits the specific issue.
In a recent project I was introduced to a hybrid of a Smart Enum. Here's an example (I apologize for typos, I'm typing this cold):
public class Priority
{
public enum Types
{
High,
Medium,
Low
}
public Types Type { get; private set; }
public string Name { get { return this.Type.ToString(); } } // ToString() with no arguments is not deprecated
public string Description { get; private set; }
public static High = new Priority{ Type = Types.High, Description = "..."};
public static Medium = new Priority{ Type = Types.Medium, Description = "..."};
public static Low = new Priority{ Type = Types.Low, Description = "..."};
public static IEnumerable<Priority> All = new[]{High, Medium, Low};
public static Priority For(Types priorityType)
{
return All.Single(x => x.Type == priorityType);
}
}
So, in implementation, you could store the Enum value, but you would reference the object itself (Priority.For(entity.priority)) for the additional metadata when rendering your views.
Is that closer to what you're looking for?
Of course, one of the gotchas is if you need to write a query against the database that relies on the metadata on the lookup, this solution is going to create a few tears along the way.
You can use "repository pattern" for data access and use viewmodels between your controllers and views. Example:
//Model
public class CustomerViewModel
{
public Customer customer { get;set; }
public IEnumerable<Village> Villages { get; set; }
}
//Controller
public ActionResult Index()
{
var customerViewModel = new CustomerViewModel
{
Customer = new Customer(),
Villages = _villageService.GetAll()
};
return View(customerViewModel);
}
//View
#model ViewModel.RegisterViewModel
#Html.DropDownListFor(q => q.Customer.VillageId, new SelectList(Model.Villages, "Id", "Title"), "Please Select")
I have written a blog post about repository pattern, you may have a look.
I store my options in the View Models themselves:
public class ViewModel {
[Required]
public int SelectListValue { get; set; }
public IDictionary<String,String> SelectListOptions {
get {
return new Dictionary<String, String>{
{ "0", Resources.Option1},
{ "1", Resources.Option2},
{ "2", Resources.Option3}
};
}
}
}
Then I can just drop the following line into my view to render the select list:
<%= Html.DropDownListFor(m => m.SelectListValue, new SelectList(this.Model.SelectListOptions, "Key", "Value", "")) %>

Categories