ServiceStack URLs for related services - odata

With ServiceStack, I'm looking for ways to access related services by composing the URLs in a manner similar to OData.
An OData example would be a URL like
http://localhost:8080/owind.svc/Categories(2)/Products
This would find all the Products related to Category 2.
An equivalent example with ServiceStack seems to be that you would create a Request DTO for a ProductService and set up Routes something like this:
[Route("/Products")]
[Route("/Products/{Id}")]
[Route("/Categories/{Category}/Products")]
public class Products
{
public string Id { get; set; }
public string Category { get; set; }
}
(Ignore the separations of concerns issues mentioned here, the above attributes at least give a clear idea what I'm asking.)
And then in the ProductService you'd support finding Products either via the primary or foreign key. I see something along these lines used in the Northwind.ServiceModel.Operations.Orders class of the ServiceStack.Northwind.ServiceModel sample project.
So I'm wondering, is this the best and most scalable way that exists to do this sort of thing in ServiceStack, or is there some shortcut I'm missing? Thinking on a scale of creating services supporting hundreds of tables, if there existed some sort of shortcut, and if it didn't come with strings attached, it could be helpful.
I can imagine a system where you could automatically generate routes based on anything in a DTO, though you'd need to do some mapping from DTO property name (usually singular) to route (often plural).
No idea if it would be conceivable to carry this beyond one level either...for example
.../Employee/1/Orders/Customers
which would get you every Customer who has had an Order with Employee #1. The notion of implementing this manually on a large scale seems prohibitive. Not sure if there are SOA arguments to be made for or against, but that would be nice to know as well.
Just to be clear, there should be no assumption of the underlying data store or access libraries.

Related

Best practices with DTOs in ASP.NET MVC Entity Framework

What's the most preferred way to work with Entity Framework and DTOs?
Let's say that after mapping I have objects like:
Author
int id
sting name
List<Book> books
Book
int id
string name
Author author
int authorID
My DTOs
AuthorDTO
int id
sting name
BookDTO
int id
string name
int authorID
Since author can have a lot of books I don't want to retrieve all of them, when for example I'm only interested in authors.
But sometimes I might want to get few authors and filtered books or all books.
I could go with multiple queries AuthorDTO GetAuthor(int id) List<BookDTO> GetBooks(int authorID). But that means several accesses to database.
The ways I see it:
If I had in AuthorDTO field List<BookDTO> books the job could be done. But sometimes I would keep this list empty, if for example I listed only authors. And that means some unconsistency, mess and a lot of details to remember.
Return Tuple<AuthorDTO, List<BookDTO>> it might be a bit confusing.
Define new DTO.
AuthorAndBooksDTO
AuthorDTO author
List<BookDTO> books
The problem with sticking to a sinlge AuthorDTO and selectively filling the List is that you are now forced to keep track of where that DTO came from. Is the list of Books not hydrated, or does this Author simply have no books? Do I have to go back to my controller and call a different method to get a different state of the same DTO? This lacks clarity from the consumer's standpoint.
In my experience, I've leaned the way of more DTOs instead of trying to re-use a set of basic DTOs to represent multiple different sets of data. It requires a bit more "boilerplate", having to set up a whole bunch of similar DTOs and mappings between DTO and Entity, but in the end the specificity and clarity makes the codebase easier to read and manage.
I think some clarification of the issues involved will actually solve your confusion here.
First and most importantly, your entity classes are DTOs. In fact, that's all they are. They're classes that represent a table structure in your database so that data from queries Entity Framework makes can be mapped on to them. In other words, they are literally objects that transfer data. The failing of Microsoft and subsequently far too many MVC developers is to conflate them with big-M Models described by the MVC pattern.
As a result, it makes absolutely zero sense to use Entity Framework to return one or more instances of an entity and then map that to yet another DTO class before finally utilizing it in your code. All you're doing is creating a pointless level of abstraction that adds nothing to your application but yet another thing to maintain.
As far as relationships go, that's where Entity Framework's lazy/eager loading comes in. In order to take advantage of it, though, the property representing the relationship must follow a very specific convention:
public virtual ICollection<Book> Books { get; set; }
If you type it as something like List<Book>, Entity Framework will not touch the relationship at all. It will not ever load the related entities and it will not persist changes made to that property when saving the entity back to the database. The virtual keyword allows Entity Framework to dynamically subclass your entity and override the collection property to add the logic for lazy-loading. Without that, the related entities will only ever be loaded if you explicitly use Load from the EF API.
Assuming your property is defined in that way, then you gain a whole world of abilities. If you want all books belonging to the author you can just interact with author.Books directly (iterate, query, whatever). No queries are made until you do something that requires evaluation of the queryset. EF issues just-in-time queries depending on the information you're requesting from the database. If you do want to load all the related books at the same time you retrieve the author, you can just use Include with your query:
var author = db.Authors.Include(m => m.Books).SingleOrDefault(m => m.Id == id);
My first question would be to ask why you are creating DTO's in the first place? Is there a consumer on the other end that is using this data? Is it a screen? Are you building DTO's just to build DTO's?
Since you tagged the question as MVC i'm going to assume you are sending data to a view. You probably want a ViewModel. This ViewModel should contain all the data that is shown on the View that uses it. Then use entity framework to populate the view model. This may be done with a single query using projections or something complex.
So after all that blathering. I would say you want option 3.
Just like the others said, for clarity reasons, you should avoid creating "generic" DTO's for specific cases.
When you want to sometimes have authors and some of their books then model a DTO for that.
When you need only the authors then create another DTO that is more suited for that.
Or maybe you don't need DTOs, maybe a List containing their names is enough. Or maybe you could in fact use an anonymous type, like new { AuthorId = author.Id, AuthorName = author.Name }. It depends on the situation.
If you're using ASP.NET MVC the DTO you'll want is in fact a ViewModel that best represents your page.
Based on what you've described, you're view model could be something like this
public class BookViewModel{
public int Id {get;set;}
public string Name {get;set;}
}
public class AuthorViewModel{
public int Id {get;set;}
public string Name {get;set;}
public List<BookViewModel> Books {get;set;} = new List<BookViewModel>();
}
public class AuthorsViewModel
{
public List<AuthorViewModel> Authors {get;set;} = new List<AuthorViewModel>();
//add in this class other properties, like the filters used on the page...
public void Load(){
//here you can retrieve the data from your database.
//you could do like this:
//step 1: retrieve data from DB via EF
//step 2: fill in the Authors view models from the data at step 1
}
}
//and in your controller you're calling the Load method to fill you're viewmodel with data from db.
public class AuthorsController{
public ActionResult Index(){
AuthorsViewModel model = new AuthorsViewModel();
model.Load();
return View(model);
}
}

Onion Architecture - Repository Vs Service?

I am learning the well-known Onion Architecture from Jeffrey Palermo.
Not specific to this pattern, but I cannot see clearly the separation between repositories and domain services.
I (mis)understand that repository concerns data access and service are more about business layer (reference one or more repositories).
In many examples, a repository seems to have some kind of business logic behind like GetAllProductsByCategoryId or GetAllXXXBySomeCriteriaYYY.
For lists, it seems that service is just a wrapper on repository without any logic.
For hierarchies (parent/children/children), it is almost the same problem : is it the role of repository to load the complete hierarchy ?
The repository is not a gateway to access Database. It is an abstraction that allow you to store and load domain objects from some form of persistence store. (Database, Cache or even plain Collection). It take or return the domain objects instead of its internal field, hence it is an object oriented interface.
It is not recommended to add some methods like GetAllProductsByCategoryId or GetProductByName to the repository, because you will add more and more methods the repository as your use case/ object field count increase. Instead it is better to have a query method on the repository which takes a Specification. You can pass different implementations of the Specification to retrieve the products.
Overall, the goal of repository pattern is to create a storage abstraction that does not require changes when the use cases changes. This article talks about the Repository pattern in domain modelling in great detail. You may be interested.
For the second question: If I see a ProductRepository in the code, I'd expect that it returns me a list of Product. I also expect that each of the Product instance is complete. For example, if Product has a reference to ProductDetail object, I'd expect that Product.getDetail() returns me a ProductDetail instance rather than null. Maybe the implementation of the repository load ProductDetail together with Product, maybe the getDetail() method invoke ProductDetailRepository on the fly. I don't really care as a user of the repository. It is also possible that the Product only returns a ProductDetail id when I call getDetail(). It is perfect fine from the repository's contract point of view. However it complicates my client code and forces me to call ProductDetailRepository myself.
By the way, I've seen many service classes that solely wrap the repository classes in my past. I think it is an anti-pattern. It is better to have the callers of the services to use the repositories directly.
Repository pattern mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
So, repositories is to provide interface for CRUD operation on domain entities. Remember that Repositories deals with whole Aggregate.
Aggregates are groups of things that belong together. An Aggregate Root is the thing that holds them all together.
Example Order and OrderLines:
OrderLines have no reason to exist without their parent Order, nor can they belong to any other Order. In this case, Order and OrderLines would probably be an Aggregate, and the Order would be the Aggregate Root
Business logic should be in Domain Entities, not in Repository layer , application logic should be in service layer like your mention, services in here play a role as coordinator between repositoies.
While I'm still struggling with this, I want to post as an answer but also I accept (and want) feedback about this.
In the example GetProductsByCategory(int id)
First, let's think from the initial need. We hit a controller, probably the CategoryController so you have something like:
public CategoryController(ICategoryService service) {
// here we inject our service and keep a private variable.
}
public IHttpActionResult Category(int id) {
CategoryViewModel model = something.GetCategoryViewModel(id);
return View()
}
so far, so good. We need to declare 'something' that creates the view model.
Let's simplify and say:
public IHttpActionResult Category(int id) {
var dependencies = service.GetDependenciesForCategory(id);
CategoryViewModel model = new CategoryViewModel(dependencies);
return View()
}
ok, what are dependencies ? We maybe need the category tree, the products, the page, how many total products, etc.
so if we implemented this in a repository way, this could look like more or less like this :
public IHttpActionResult Category(int id) {
var products = repository.GetCategoryProducts(id);
var category = repository.GetCategory(id); // full details of the category
var childs = repository.GetCategoriesSummary(category.childs);
CategoryViewModel model = new CategoryViewModel(products, category, childs); // awouch!
return View()
}
instead, back to services :
public IHttpActionResult Category(int id) {
var category = service.GetCategory(id);
if (category == null) return NotFound(); //
var model = new CategoryViewModel(category);
return View(model);
}
much better, but what is exactly inside service.GetCategory(id) ?
public CategoryService(ICategoryRespository categoryRepository, IProductRepository productRepository) {
// same dependency injection here
public Category GetCategory(int id) {
var category = categoryRepository.Get(id);
var childs = categoryRepository.Get(category.childs) // int[] of ids
var products = productRepository.GetByCategory(id) // this doesn't look that good...
return category;
}
}
Let's try another approach, the unit of work, I will use Entity framework as the UoW and Repositories, so no need to create those.
public CategoryService(DbContext db) {
// same dependency injection here
public Category GetCategory(int id) {
var category = db.Category.Include(c=> c.Childs).Include(c=> c.Products).Find(id);
return category;
}
}
So here we are using the 'query' syntax instead of the method syntax, but instead of implementing our own complex, we can use our ORM. Also, we have access to ALL repositories, so we can still do our Unit of work inside our service.
Now we need to select which data we want, I probably don't want all the fields of my entities.
The best place I can see this is happening is actually on the ViewModel, each ViewModel may need to map it's own data, so let's change the implementation of the service again.
public CategoryService(DbContext db) {
// same dependency injection here
public Category GetCategory(int id) {
var category = db.Category.Find(id);
return category;
}
}
so where are all the products and inner categories?
let's take a look at the ViewModel, remember this will ONLY map data to values, if you are doing something else here, you are probably giving too much responsibility to your ViewModel.
public CategoryViewModel(Category category) {
Name = category.Name;
Id = category.Id;
Products = category.Products.Select(p=> new CategoryProductViewModel(p));
Childs = category.Childs.Select(c => c.Name); // only childs names.
}
you can imagine the CategoryProductViewModel by yourself right now.
BUT (why is there always a but??)
We are doing 3 db hits, and we are fetching all the category fields because of the Find. Also Lazy Loading must be enable. Not a real solution isn't it ?
To improve this, we can change find with where... but this will delegate the Single or Find to the ViewModel, also it will return an IQueryable<Category>, where we know it should be exactly one.
Remember I said "I'm still struggling?" this is mostly why. To fix this, we should return the exact needed data from the service (also know as the ..... you know it .... yes! the ViewModel).
so let's back to our controller :
public IHttpActionResult Category(int id) {
var model = service.GetProductCategoryViewModel(id);
if (category == null) return NotFound(); //
return View(model);
}
inside the GetProductCategoryViewModel method, we can call private methods that return the different pieces and assemble them as the ViewModel.
this is bad, now my services know about viewmodels... let's fix that.
We create an interface, this interface is the actual contract of what this method will return.
ICategoryWithProductsAndChildsIds // quite verbose, i know.
nice, now we only need to declare our ViewModel as
public class CategoryViewModel : ICategoryWithProductsAndChildsIds
and implement it the way we want.
The interface looks like it has too many things, of course it can be splitted with ICategoryBasic, IProducts, IChilds, or whatever you may want to name those.
So when we implement another viewModel, we can choose to do only IProducts.
We can have our services having methods (private or not) to retrieve those contracts, and glue the pieces in the service layer. (Easy to say than done)
When I get into a fully working code, I might create a blog post or a github repo, but for now, I don't have it yet, so this is all for now.
I believe the Repository should be only for CRUD operations.
public interface IRepository<T>
{
Add(T)
Remove(T)
Get(id)
...
}
So IRepository would have: Add, Remove, Update, Get, GetAll and possibly a version of each of those that takes a list, i.e, AddMany, RemoveMany, etc.
For performing search retrieval operations you should have a second interface such as an IFinder. You can either go with a specification, so IFinder could have a Find(criteria) method that takes criterias. Or you can go with things like IPersonFinder which would define custom functions such as: a FindPersonByName, FindPersonByAge etc.
public interface IMyObjectFinder
{
FindByName(name)
FindByEmail(email)
FindAllSmallerThen(amount)
FindAllThatArePartOf(group)
...
}
The alternative would be:
public interface IFinder<T>
{
Find(criterias)
}
This second approach is more complex. You need to define a strategy for the criterias. Are you going to use a query language of some sort, or a more simple key-value association, etc. The full power of the interface is also harder to understand from simply looking at it. It's also easier to leak implementations with this method, because the criterias could be based around a particular type of persistence system, like if you take a SQL query as criteria for example. On the other hand, it might prevent you from having to continuously come back to the IFinder because you've hit a special use case that requires a more specific query. I say it might, because your criteria strategy will not necessarily cover 100% of the querying use cases you might need.
You could also decide to mix both together, and have an IFinder defining a Find method, and IMyObjectFinders that implement IFinder, but also add custom methods such as FindByName.
The service acts as a supervisor. Say you need to retrieve an item but must also process the item before it is returned to the client, and that processing might require information found in other items. So the service would retrieve all appropriate items using the Repositories and the Finders, it would then send the item to be processed to objects that encapsulates the necessary processing logic, and finally it would return the item requested by the client. Sometime, no processing and no extra retrievals will be required, in such cases, you don't need to have a service. You can have clients directly call into the Repositories and the Finders. This is one difference with the Onion and a Layered architecture, in the Onion, everything that is more outside can access everything more inside, not only the layer before it.
It would be the role of the repository to load the full hierarchy of what is needed to properly construct the item that it returns. So if your repository returns an item that has a List of another type of item, it should already resolve that. Personally though, I like to design my objects so that they don't contain references to other items, because it makes the repository more complex. I prefer to have my objects keep the Id of other items, so that if the client really needs that other item, he can query it again with the proper Repository given the Id. This flattens out all items returned by the Repositories, yet still let's you create hierarchies if you need to.
You could, if you really felt the need to, add a restraining mechanism to your Repository, so that you can specify exactly which field of the item you need. Say you have a Person, and only care for his name, you could do Get(id, name) and the Repository would not bother with getting every field of the Person, only it's name field. Doing this though, adds considerable complexity to the repository. And doing this with hierarchical objects is even more complex, especially if you want to restrict fields inside fields of fields. So I don't really recommend it. The only good reason for this, to me, would be cases where performance is critical, and nothing else can be done to improve the performance.
In Domain Driven Design the repository is responsible for retrieving the whole Aggregate.
Onion and Hexagonal Architectures purpose is to invert the dependency from domain->data access.
Rather than having a UI->api->domain->data-access,
you'll have something like UI->api->domain**<-**data-access
To make your most important asset, the domain logic, is in the center and free of external dependencies.
Generally by splitting the Repository into Interface/Implementation and putting the interface along with the business logic.
Now to services, there's more that one type of services:
Application Services: your controller and view model, which are external concerns for UI and display and are not part of the domain
Domain Services: which provide domain logic. In you're case if the logic you're having in application services starts to do more that it's presentation duties. you should look at extracting to a domain service
Infrastructure Services: which would, as with repositories, have an interface within the domain, and an implementation in the outer layers
#Bart Calixto, you may have a look at CQRS, building your view model is too complex when you're trying to use Repositories which you design for domain logic.
you could just rewrite another repo for the ViewModel, using SQL joins for example, and it doesn't have to be in the domain
is it the role of repository to load the complete hierarchy ?
Short answer: yes, if the repository's outcome is a hierarchy
The role of repository is to load whatever you want, in any shape you need, from the datasource (e.g. database, file system, Lucene index, etc).
Let's suppose a repository (interface) has the GetSomeHierarchyOrListBySomeCriteria operation - the operation, its parameters and its outcome are part of the application core!
Let's focus on the outcome: it doesn't matter it's shape (list, hierarchy, etc), the repository implementation is supposed to do everything necessary to return it.
If one is using a NoSql database than GetSomeHierarchyOrListBySomeCriteria implementation might need only one NoSql-database-query with no other conversions or transformations to get the desired outcome (e.g. hierarchy). For a SQL database on the other hand, the same outcome might imply multiple queries and complex conversions or transformations - but that's an implementation detail, the repository interface is the same.
repositories vs domain services
According to The Onion Architecture : part 1, and I'm pointing here about the official page, not someone's else interpretation:
The first layer around the Domain Model is typically where we would
find interfaces that provide object saving and retrieving behavior,
called repository interfaces. [...] Only the interface is in the application core.
Notice the Domain Services layer above Domain Model one.
Starting with the second official page, The Onion Architecture : part 2, the author forgets about Domain Services layer and is depicting IConferenceRepository as part of the Object Services layer which is right above Domain Model, replacing Domain Services layer! The Object Services layer continues in The Onion Architecture : part 3, so I ask: what Domain Services? :)))
It seems to me that author's intent for Object Services or Domain Services is to consist only of repositories, otherwise he leaves no clue for something else.

What is meant by "convention" in this context?

I recently read this blog entry by Hadi Hariri: That dreaded M in ASP.NET MVC. Hadi surveyed fellow ASP.NET MVC developers about the types of models they use in the applications. One of his survey questions read:
If you bind to Domain Model, how do you deal with extra data such as country list?
And one person wrote select Other and wrote in: "conventions." Following that, Hadi wrote:
I've actually found another way to solve this problem, partially based on conventions.
And then later says:
Maybe we should take the concept of conventions more seriously than just what folders our Views, Controllers and Models reside in. Maybe we should push conventions to the limit and see if we actually reduce this friction.
What does he mean by using "conventions" to solve this problem? I'm not familiar with the term in this context.
Thanks
Convention in this context could mean many things. Loosely it is just a solution to the problem that is not built in but looked up using names.
An example of this already in MVC is that a route to a controller named "Home" is mapped to a class named "HomeController". Extending this idea to the selected country and country list problem you can think of many solutions.
One example would be given a model:
public class UploadModel
{
public string Country {get; set;}
}
We may define options for this model via a convention on the naming where it looks for a model with the word "Options" after its name and then matches the property on the model with a like named property on the options model.
public class UploadModelOptions
{
public IList<string> Country {get;set;}
}
This may not be a great convention but is an acceptable example of what the author may be talking about.

Flattened and derived properties with Automapper

I'm working on an ASP.NET MVC site, using EF4 and Automapper. I'm making good progress, and feel fairly good for the design (considering this is my first stab at a true DDD architecture). But I'm starting to see some things that I'm not too comfortable with.
The questions I have probably relate more to my lack of experience with Automapper and DDD, so they may be fairly easy for some of you to answer and point me in the right direction. There's also a very good chance I'm going about this completely wrong, but my direction is based on what I'm reading on here, some from searching, and some from asking my own questions. But I'm also starting to realize that some of the "advice" I'm seeing is contradictory to each other.
Quick background, my domain model is simply the generated POCOs from EF4 POCO template (anemic). These are used in my service layer, and they are also exposed to my application via the service layer. I don't have any sort of DTO, just my anemic domain model, view models, and Automapper to map the two, per the advice I was given. This is all fine and dandy assuming they can be mapped one-to-one.
My problems come in when I have to flatten my domain models into one view model, or when I need some business logic to define a view model property.
Two examples:
Flattening
I have two models, User and UserProfile. This is a one-to-one mapping, so it already is logically flat -- it's just in two separate models. My view model needs properties of both User and UserProfile in one object. From what I've seen, Automapper has no easy way to do this, so what I did was extend my User POCO, adding the needed UserProfile properties to it:
public string UserName
{
get { return UserProfile.UserName; }
}
I'm not a big fan of this as it seems to violate DRY, and may become a bit of a pain the more I have to do this.
Encapsulating business logic
I have another case where a User property isn't stored, but rather derived, and needs to do some logic before returning a value. For example, a profile image URL will depend on whether they registered with Facebook or Twitter. So I have something like this:
public string ProfileImageUrl
{
get
{
if (User.TwitterId != null)
{
// return Twitter profile image URL
}
if (User.FacebookId != null)
{
// return Facebook profile image URL
}
}
}
I'm pretty sure this isn't something that Automapper is responsible for, but I'm not sure if this should be done with a domain model extension if I want to keep it anemic. So I'm not sure where this belongs.
I'm not completely stuck on having my domain model be anemic (I know that's its own debate), but I do anticipate this domain model being used by multiple applications with different view models and validation.
Thank in advance.
UPDATE: In response to #jfar, my main issue with the flattening example is that it seems like this should be something Automapper should be able to do. If not, then I can live with this option. I was just looking for someone to double check my design to make sure there wasn't a better way to do this.
My issue with the encapsulating business logic example, is that I'm violating the anemia of my domain model. In some cases, this may even need to hit the repositories to pull certain data for business logic, and this seems like a bad design to me.
The other thing I'm starting to wonder, is if I shouldn't have a DTO layer, but I honestly don't want to go that route either (and per the question I linked above, it seems to be more accepted not to use DTOs w/ DDD).
Flattening: You can chain your mappings together using Automapper's ability to map to an existing object.
Chain Example
Encapsulatng Business Logic: I don't really see your problem. However, if you want Automapper to be responsible, take a look at before and after maps or custom resolvers. Custom Resolver Example
Why are you so intent on keeping your domain model anemic? It looks to me like your domain objects are nothing more than DTOs.
The ProfileImageUrl belongs on your domain class that has the necessary information to return the correct URL. I'd imagine this is UserProfile. If a single class doesn't have the needed information thats what a service is for. You either create a method on your service that returns the URL or a composite object like Darin Dimitrov suggested.
Firestrand and Darin Dimitrov's answers are both good ways to accomplish flattening.
Define a model that regroups those two models:
public class UserWithProfile
{
public User User { get; set; }
public UserProfile Profile { get; set; }
}
then have your service layer return this model. Another possibility if there is a 1-to-1 mapping between User and UserProfile is to define the following model:
public class UserWithProfile: User
{
public UserProfile Profile { get; set; }
}
Then define a view model containing only what is needed by the given view:
public class SomeUserViewModel
{
... only properties needed by the given view
}
next define a mapping between your model and your view model:
Mapper.CreateMap<UserWithProfile, SomeUserViewModel>()
...
and finally in your controller use the service layer to fetch the model, map it to a view model and pass this view model to the view for rendering, pretty standard stuff.
I searched and read about flattening more, and the more I searched, to more it looked like Automapper should be handling this automagically. After playing around a bit, I found a way to get this to work, though I still can't find any examples of doing this, even with Automapper's documentation.
The key is to name the property on the destination object with the fully qualified name of the source object graph.
Source objects:
class User
{
int Id { get; set; }
FacebookUser FacebookUser { get; set; }
}
class FacebookUser
{
string UserName { get; set; }
}
Destination objects:
class UserViewModel
{
int Id { get; set; }
string FacebookUserUserName { get; set; }
}
So:
UserViewModel.Id -> User.Id
UserViewModel.FacebookUserUserName -> User.FacebookUser.UserName
Maybe this should have been obvious to me, and maybe it is for most people. And now that I think about it, it makes sense -- it's really the only way it could work. I just didn't figure it out until now.

MVC Custom Model - Where is a simple example?

I need to make a web application and I want to use MVC. However, my Model can't be one of the standard Models -- the data is not stored in a database but instead in an external application accessible only via a API. Since this is the first MVC application I've implemented I'm relying on examples to understand how to go about it. I can't find any examples of a non-DB based Model. An example of a custom Model would be fine too. Can anyone point me to such a beast? Maybe MVC is just to new and none exist.
It seems like I might be able to get away with the DataSet Model, however I've not seen any examples of how to use this object. I expect an example of DataSet could help me also. (Maybe it is the same thing?)
Please note: I've seen countless examples of custom bindings. This is NOT what I want. I need an example of a custom Model which is not tied to a specific database/table.
UPDATE
I found a good example from MS located here:
http://msdn.microsoft.com/en-us/library/dd405231.aspx
While this is the "answer" to my question, I don't really like it because it ties me to MS's view of the world. #Aaronaught, #jeroenh, and #tvanfosson give much better answers from a meta perspective of moving my understanding (and yours?) forward with respect to using MVC.
I'm giving the check to #Aaronaught because he actually has example code (which I asked for.) Thanks all and feel free to add even better answers if you have one.
In most cases it shouldn't matter what the backing source is for the actual application data; the model should be exactly the same. In fact, one of the main reasons for using something like a repository is so that you can easily change the underlying storage.
For example, I have an MVC app that uses a lot of web services - rarely does it have access to a local database, except for simple things like authentication and user profiles. A typical model class might look like this:
[DataContract(Namespace = "http://services.acme.com")]
public class Customer
{
[DataMember(Name = "CustomerID")]
public Guid ID { get; set; }
[DataMember(Name = "CustomerName")]
public string Name { get; set; }
}
Then I will have a repository interface that looks like this:
public interface ICustomerRepository
{
Customer GetCustomerByID(Guid id);
IList<Customer> List();
}
The "API" is all encapsulated within the concrete repository:
public class AcmeWSCustomerRepository : ICustomerRepository, IDisposable
{
private Acme.Services.CrmServiceSoapClient client;
public AcmeWSCustomerRepository()
: this(new Acme.Services.CrmServiceSoapClient())
public AcmeWSCustomerRepository(Acme.Services.CrmServiceSoapClient client)
{
if (client == null)
throw new ArgumentNullException("client");
this.client = client;
}
public void Dispose()
{
client.SafeClose(); // Extension method to close WCF proxies
}
public Customer GetCustomerByID(Guid id)
{
return client.GetCustomerByID(id);
}
public IList<Customer> List()
{
return client.GetAllCustomers();
}
}
Then I'll also probably have a local testing repository with just a few customers that reads from something like an XML file:
public class LocalCustomerRepository : ICustomerRepository, IDisposable
{
private XDocument doc;
public LocalCustomerRepository(string fileName)
{
doc = XDocument.Load(fileName);
}
public void Dispose()
{
}
public Customer GetCustomerByID(Guid id)
{
return
(from c in doc.Descendants("Customer")
select new Customer(c.Element("ID").Value, c.Element("Name").Value))
.FirstOrDefault();
}
// etc.
}
The point I'm trying to make here is, well, this isn't tied to any particular database. One possible source in this case is a WCF service; another is a file on disk. Neither one necessarily has a compatible "model". In this case I've assumed that the WCF service exposes a model that I can map to directly with DataContract attributes, but the Linq-to-XML version is pure API; there is no model, it's all custom mapping.
A really good domain model should actually be completely independent of the true data source. I'm always a bit skeptical when people tell me that a Linq to SQL or Entity Framework model is good enough to use throughout the entire application/site. Very often these simply don't match the "human" model and simply creating a bunch of ViewModel classes isn't necessarily the answer.
In a sense, it's actually better if you're not handed an existing relational model. It forces you to really think about the best domain model for your application, and not necessarily the easiest one to map to some database. So if you don't already have a model from a database - build one! Just use POCO classes and decorate with attributes if necessary, then create repositories or services that map this domain model to/from the API.
I think what you are looking for is really a non-DB service layer. Models, typically, are relatively simple containers for data, though they may also contain business logic. It really sounds like what you have is a service to communicate with and need a layer to mediate between the service and your application, producing the appropriate model classes from the data returned by the service.
This tutorial may be helpful, but you'd need to replace the repository with your class that interacts with the service (instead of the DB).
There is no fixed prescription of what a "Model" in MVC should be, just that it should contain the data that needs to be shown on screen, and probably also manipulated.
In a well-designed MVC application, data access is abstracted away somehow anyway, typically using some form of the Repository pattern: you define an abstraction layer (say, an IRepository interface) that defines the contract needed to get and persist data. The actual implementation will usually call a database, but in your case should call your 'service API'.
Here is an example of an MVC application that calls out to a WCF service.

Resources