You've got a lot of moving parts in your question, touching on a lot of concepts, but here's my basic advice when it comes to how to think about a mid-to-large scale MVC application:
Presentation <---> Business Logic <---> Data Access
Firstly, it's best to not think of the the app as "an MVC application". It's an application that uses the MVC pattern as its presentation component. Thinking about it this way will help you separate out your business logic concerns from your presentation concerns. Perhaps it's ok for small applications to pile everything down to database access into the MVC structure, but it'll quickly become untenable for a mid-to-large application.
MVC (Presentation)
In your app, the ASP.NET MVC component should deal with transforming business data for display purposes (Models), displaying the user interface (Views), and communication issues such as routing, authentication, authorization, request validation, response handling, and the like (Controllers). If you have code that does something else, then it doesn't belong in the MVC component.
Repository/ORM (Data Access)
Also in your app, the data access layer should be concerned with retrieving and storing persistent data. Commonly that's in the form of a relational database, but there are many other ways data can be persisted. If you have code that isn't reading or storing persistent data, then it doesn't belong in the data layer. I shared my thoughts on the ORM/Repository discussion previously on SO, but to recap, I don't consider an ORM to be the same thing as a Repository, for several reasons.
Business Logic
So now you have your presentation layer (MVC), and your data layer (repository or ORM) ... Everything else is your business logic layer (BLL). All of your code that decides which data to retrieve, or performs complicated calculations, or makes business decisions, should be here. I usually organize my business logic in the form of 'services', which my presentation layer can call upon to do the work requested. All of my domain models exist here.
Your Approach
This is where your approach breaks down a little for me. You describe your MVC controller as the place you would get data from the repository, and call upon the MPGCalculator to do some work, etc. I would not have my controller do any of this, but instead would delegate all of this off to a service in the BLL.
In other words, I would not inject a repository and MPGCalculator into the controller, that's giving the controller too much responsibility (it's already handling all of the controller stuff I mentioned above). Instead, I would have a service in the BLL handle all of that, and pass the results back to the controller. The controller can then transform the results to the correct model, and pass that on to the correct view. The controller doesn't have any business logic in it, and the only things injected into the controller would be the appropriate BLL services.
Doing it this way means your business logic (for example, given a set of vehicles, calculate the MPG and sort best to worst) is independent from presentation and persistence concerns. It'll usually be in a library that doesn't know or care about the data persistence strategy nor the presentation strategy.
I know it may seem like you are converting objects back and forth all the time between your database objects, your data transfer objects, your client objects with validation logic and so on but I'd say that no, you're not doing anything wrong.
Each of these objects may represent the same unit of information, but they have very different responsibilities. The database object is your communication interface with the database and should be kept in the database layer since it may or may not have different database metadata annotations and/or unnecessary details about the database implementation in it.
Your data transfer object is the communication interface with your API consumers. These should be as clean as possible to facilitate easy consumption from different languages/platforms. This might impose certain restrictions on how these look and behave depending on what API consumers you wish to support.
Your client objects with validation logic is really not a part of your API project, they're part of your consumer project. These cannot be the same as the data transfer objects in this case since you are adding extra client-specific logic (in this case validation attributes) on them which the server knows nothing about (and should not know anything about!) You shouldn't count these objects as part of your API, because they're really not. They're highly consumer application specific and some applications that consume your API might actually not even need to create these object and could just as well survive on just your data transfer objects. For example, if you didn't have any need of validation you wouldn't need an extra layer of objects that are completely identical to your data transfer objects. Generally my strategy here is to evolve the project in stages, I start off by plainly using the data transfer objects as my consumer application objects and when I see the need for application specific handling of data (validation, implementing INotifyPropertyChanged, etc..) I do a quick refactoring and add in the new layer as needed.
To me, it seems like each of the three object types map very nicely to a single responsibility which is clean coding and good practice. Sadly, clean code and good practices sometimes means that you are writing a lot of extra code and jumping through extra hoops "just because". And while coding, it may be hard to appreciate the value that this is giving you - but as soon as you release your application and begin supporting it or adding new features for the next version then you will probably start appreciating that you took the time to separate these concerns properly in the first place. (Not to mention that you'll avoid certain problems that might occur due to improper separation of concerns - and since you have avoided these problems it might be hard to appreciate the mess that you can find yourself in when you have not separated your concerns.)
I also hate writing conversion code between different object types like this, but my solution is usually one of the following:
- Use a library that does most of the object conversion heavy lifting for you - for example, if you use C# you can use the fantastic AutoMapper library (http://automapper.org/). I believe that there's a couple of other libraries like this, but AutoMapper is the most powerful one I've seen so far.
- If you can't find a library help you with your object conversions, write a set of utility methods for converting between them. This might suck, but it's worth it in the long run, write the conversion method the first time you need to convert something - don't wait.
Best Answer
Your website should have a separate set of ViewModels which wrap the domain models and any other data/logic required by the page.
Because these view models belong to the website rather than the domain its ok to stick on any validation or extra logic which is only required by the website/View for the particular process you are implementing.
I think the best example is say you have some process 'Sign Up' the domain model for which includes a ton of data about the person signing up. Your design teams comes up with two designs.
Design 1: A large single page form with all the fields on
Design 2: A 'Wizard' approach with multiple separate forms
Although both designs use the same underling logic for signing up. each will have very different view models.
update ---
Entity Framework data annotations allow EF to correctly map your object to a database table. There are some conventions which will allow you to get away with not using some of them of your properties are named as expected.
However, you are correct in that if you want to separate your domain objects from the persistence logic you will need to implement an Entity Object which mirrors the properties on your domain object and to which you can add the data annotations.
You can wrap all this in a repository object which can get the Entity objects back from the DB, convert them to your Domain objects and return them to the calling code. However if you do all these things you will find that you have lost the time saving benefits of EF and might as well have just used SqlClient
In the ideal world you solution structure might look like this: