I'm having some trouble with deciding on a solution for my mvc application.
Background.
We have an EF model which we perform operations on via WCF Services (not data services).
I have an MVC application which has a number of Repositories that talk directly to the Services and return WCF types back to a controller which is calling the repository method, a type called for example WCFUserEntity (it's not actually prefixed with WCF).
Inside the controller I plan to automap the WCFUserEntity to a ViewModel entity.
What is bugging me about this solution is that because i'm returning WCFUserEntity to the controller I have to have a reference to the WebService proxy in my controller which doesn't sit well with me, i'd like my controllers to know nothing of where the repository has got the data from. So another option for me is to do the automapping inside of the repository and return the ViewModel entity to the controller, i can't find much around which supports this idea though, so really what i'm looking for is validation of this 2nd solution or help with a 3rd.
thanks, Dom
You may want to consider a third option.
The use of ViewModelBuilders.
in your controller they would work like this:
var myViewModel = myViewModelBuilder.WithX().WithY().Build();
WithX and WithY would be methods that would add stuff to your viewmodel internally (within the builder, for example WithCountriesList() if you want to add a dropdown showing the countries in your view) and the Build method would return the internal viewmodel after adding all the bits with the WithXXX methods. This is so because most of the time you may want to add lists for dropdowns and things that are not part of your original model (your userEntity in this case).
This way, your controller doesn't know anything about how to build the viewmodel, your repository is also agnostic of viewmodels. All the work is done in the Builder. On the downside, you need to create a ViewModelBuilder for each ViewModel.
I hope this helps.
How I would approach this might require some architecture changes, but I would suggest you approach your WCF API to return ViewModels instead of entities.
For starters, think about bandwidth issues (which would be an issue if you are hosting the WCF in Azure or the cloud). If your ViewModel is only using a few specific properties, why waste the bandwidth returning the other data? In high traffic scenarios, this could cause a waste of traffic that could end up costing money. For example, if your view is only display a user and his questions, there's no reason to send his email, answers, point count, etc.. over the wire.
Another issue to think about is eager loading. By having the WCF service return a ViewModel, you know you have all the data (even when it pertains to related entities) required from the view in one trip to the WCF service. You do not need to get the WCFUserEntity and then ask WCF for WCFDocumentEntities that are related to that specific user.
Finally, if your WCF API is built around ViewModels then you have a MUCH clearer understanding of the business processes involved. You know that this specific request (and view in the system) will give you this specific information, and if you need different information for a different view then you know that it's a completely different business request that has different business requirements. Using stack overflow as an example, it makes it trivial to see that this business process is asking for the current user with his related questions, while this business process is requesting the current user with his related answers.
Using ViewModels in your data retrieval WCF API means that your frontend layers do not necessarily know where the data came from, it just knows that it called a business process and got the data it needs. As far as it knows the data layer connected to the database directly instead of WCF.
Edit:
After re-reading, this actually looks like your 3rd option. Most research on the net don't talk about this option, and I don't know why, but after having some similar frustrations you are having (plus others listed in this post) this is the way I have gone with my business layer. It makes more sense and is actually (imho) easier to manage.
Related
I'm aware that in model-view-controller, the Model is the class part.
If I have a User class and instantiate an object, the object must refer to a single user from the database.
So I'll have the CRUD methods on the user, for that specific user.
But if I need a function to run a SELECT * FROM Users, should I create a function within the User class? Or a function in a helper file? Or in the controller? Where should it go, in order to respect the MVC pattern?
I mean, it makes no sense to instantiate a User object just to run a function to display the Users table.
I'm not sure if this will raise "primarily opinion based" flags. I just don't know where those functions should go. If you guys consider the question worth closing, it's ok. But tell me in the comments in which stack community I should ask this.
Back up a bit. Let's go foundational for a moment.
In the MVC pattern
The model is your state (in simple terms), meaning a representation of the data important to the business functionality you are working with
The view is a way of presenting the state to the user (NOTE user here could be another system, as you can use MVC patterns for service endpoints)
The controller ensures the model gets to the view and back out of the view
In a system designed with good separation of state, business functions are not present in the model, the view or the controller. You segregate business functionality into its own class library. Why? You never know when the application will require a mobile (native, not web) implementation or a desktop implementation or maybe even become part of a windows service.
As for getting at data, proper separation of concerns states the data access is separate not only from the model, view and controller, but also from the business functionality. This is why DALs are created.
Before going on, let's go to your questions.
should I create a function within the User class? This is an "active record" pattern, which is largely deprecated today, as it closely couples behavior and state. I am sure there are still some instances where it applies, but I would not use it.
Or a function in a helper file? Better option, as you can separate it out. But I am not fond of "everything in a single project" approach, personally.
Or in the controller? Never, despite Scott Gu's first MVC examples where he put LINQ to SQL (another groan?) in the controller.
Where should it go, in order to respect the MVC pattern?
Here is my suggestion:
Create a DAL project to access the data. One possible pattern that works nicely here is the repository pattern. If you utilize the same data type for your keys in all/most tables, you can create a generic repository and then derive individual versions for specific data. Okay, so this one is really old, but looking over it, it still has the high level concepts (https://gregorybeamer.wordpress.com/2010/08/10/generics-on-the-data-access-layer)
Create a core project for the business logic, if needed. I do this every time, as it allows me to test the ideas on the DAL through unit tests. Yes, I can test directly in the MVC project (and do), but I like a clean separation as you rarely find 0% business rules in a solution.
Have the core pull the data from the DAL project and the MVC project use the core project. Nice flow. Easy to unit test. etc.
If you want this in a single project, then separate out the bits into different folders so you can make individual projects, if needed, in the future.
For the love of all things good and holy, don't use the repository pattern. #GregoryABeamer has a great answer in all respects, except recommending you create repository instances to access your entities. Your ORM (most likely Entity Framework) covers this, and completely replaces the concepts of repositories and unit of work.
Simply, if you need something from your database, hit your ORM directly in your controller. If you prefer, you can still add a level of abstraction to hide the use of the ORM itself, such that you could more easily switch out the data access with another ORM, Web Api, etc. Just don't do a traditional unit of work with tens or hundreds of repository instances. If you're interested, you can read a series of posts I wrote about that on my blog. I use the term "repository" with my approach, but mostly just to contrast with the typical "generic" repository approach you find scattered all over the interwebs.
I'd use some kind of 'Repository' layer. Then, my controller calls the UserRepository GetAll method and sends the data to View layer.
I'd like to create a good app in ASP.NET MVC 5 using EF 6 Code first concept. I want it to be well-designed i.e. having generally speaking: Presentation, Logic and Data layers separated. I want it to be testable :)
Here's my idea and some issues related with creating application
Presentation layer: It's my whole MVC - view models(not models), views, controllers
I believe that's validation should be done somewhere else (in my opinion - it's a part of business logic) but it's quite convenient to use attributes from the DataAnnotations namespace in ViewModelds and check validation in controller.
Logic layer: Services - classes with their interfaces to rule business logic.
I put there functions like: AddNewPerson(PersonViewModel Person), SendMessageToPerson(...).
They will use DB context to make their actions (there's a chance that not all of them will be relying on context). There's a direct connection between service and db - I mean the service class have reference do context.
Where should I do mapping between ViewModel and Model? I've heard that service is a bad place for it - so maybe in controllers. I've heard that service should do the work related with db exclusively.
Is it right? Is my picture of service layer is good?
Data layer: I've read about Repository and UoW patterns a lot. There're some articles which suggest that EF6 implements these two things. I don't want to create extra code if there's no need for such a behavior. The question is: am i right to assume that i don't need them?
Here's my flow:
View<->Controllers(using ViewModels)<->Services(using Models)<->DB.
**I'm gonna use DI in my project.
What do you think about my project structure?
There is no reason to use a Unit of Work pattern with Entity Framework if you have no need to create a generic data access mechanism. You would only do this if you were:
using a data access technology that did not natively support a Unit of work pattern (EF does)
Wanted to be able to swap out data providers sometime in the future.. however, this is not as easy as it might seem as it's very hard NOT to introduce dependencies on specific data technologies even when using an Unit of Work (maybe even BECAUSE you are)... or
You need to have a way of unifying disparate data sources into an atomic transaction.
If none of those are the case, you most likely don't need a custom Unit of Work. A Repository, on the other hand can be useful... but with EF6 many of the benefits of a Repository are also available since EF6 provides mocking interfaces for testing. Regardless, stay away from a generic repository unless it's simply an implementation detail of your concrete repositories. Exposing generic repositories to your other layers is a huge abstraction leak...
I always use a Repository/Service/Façade pattern though to create a separation between my data and business (and UI and business for that matter) layers. It provides a convenient way to mock without having to mock your data access itself and it decouples your logic from the specific that are introduced by the Linq layer used by EF (Linq is relatively generic, but there are things that are specific to EF), a façade/repository/server interface decouples that).
In general, you're on the right path... However, let me point out that using Data Attributes on your view models is a good thing. This centralizes your validation on your model, rather than making you put validation logic all over the place.
You're correct that you need validation in your business logic as well, but your mistake is the assumption that you should only have it on the business logic. You need validation at all layers of your application.. And in particular, your UI validation may have different requirements than your business logic validation.
For instance, you may implement creating a new account as a multi-step wizard in your UI, this would require different validation than your business layer because each step has only a subset of the validation of the total object. Or you might require that your mobile interface has different validation requirements from your web site (one might use a captcha, while the other might use a touch based human validation for instance).
Either way, it's important to keep in mind that validation is important both at the client, server, and various layers...
Ok, let’s clarify a few things...
The notion of ViewModel (or the actual wording of ViewModel) is something introduced by Microsoft Martin Fowler. In fact, a ViewModel is nothing more than a simple class.
In reality, your Views are strongly typed to classes. Period. To avoid confusion, the wording ViewModel came up to help people understand that
“this class, will be used by your View”
hence why we call them ViewModel.
In addition, although many books, articles and examples use the word ViewModel, let's not forget that it's nothing more than just a Model.
In fact, did you ever noticed why there is a Models folder inside an MVC application and not a ViewModels folder?
Also, ever noticed how at the top of a View you have #model directive and not # viewmodel directive?
That's because everything could be a model.
By the way, for clarity, you are more than welcomed to delete (or rename) the Models folder and create a new one called ViewModels if that helps.
Regardless of what you do, you’ll ultimately call #model and not #viewmodel at the top of your pages.
Another similar example would be DTO classes. DTO classes are nothing more than regular classes but they are suffixed with DTO to help people (programmers) differentiate between all the other classes (including View Models).
In a recent project I’ve worked on, that notion wasn’t fully grasped by the team so instead of having their Views strongly typed to Models, they would have their Views strongly typed to DTO classes. In theory and in practice everything was working but they soon found out that they had properties such as IsVisible inside their DTO’s when in fact; these kind of properties should belongs to your ViewModel classes since they are used for UI logic.
So far, I haven’t answered your question but I do have a similar post regarding a quick architecture. You can read the post here
Another thing I’d like to point out is that if and only if your Service Layer plans on servicing other things such as a Winform application, Mobile web site, etc...then your Service Layer should not be receiving ViewModels.
Your Service Layer should not have the notion of what is a ViewModel. It should only accept, receive, send, etc... POCO classes.
This means that from your Controller, inside your ActionResult, once the ModelState is Valid, you need to transform your ViewModel into a POCO which in turn, will be sent to the method inside your Service Layer.
In other words, I’d use/install the Automapper nugget package and create some extension methods that would convert a ViewModel into a POCO and vice-versa (POCO into a ViewModel).
This way, your AddNewPerson() method would receive a Person object for its parameter instead of receiving a PersonViewModel parameter.
Remember, this is only valid if and only if your Service Layer plans on servicing other things...
If that's not the case, then feel free to have your Service Layer receive, send, add, etc...ViewModels instead of POCOs. This is up to you and your team.
Remember, there are many ways to skin a cat.
Hope this helps.
I'm writting an application that has many Ajax widgets (Kendo-UI to be percise). It's starting to get messy to have all those Ajax responses without the standard controllers so I was starting to consider making each entities their own controller. If I'm taking the time to do this, I figured I might as well go foward and do those as WebAPIs since I was planning to do this in a not so close future, but hey, it would be done already...
So my question is: Is it a good practice to use an MVC application's own Web API as a Ajax Widget feeds or is there any reason to stick with standard Controllers?
I've seen some arguments about performance, but I don't think this applies to this situation. I believe it was more of a "Controller calling WebAPI" situation which has obvious performance hits. But since it's already a client side Ajax call, weither it goes into a standard MVC Controller or a WebAPI controller shouldn't change a thing, would it?
Edit
Additional information regarding the project:
I am using Entity Framework for the data access.
I have a repository pattern going on with UnitOfWork.
I am using proper a MVC structure (EF POCOs AutoMapped to DTO POCOs in the repository and fed into View Models by the controllers)
This is a MVC 4 project on .NET 4.0
There is a lot of database relationships (specially for the object I'm working with at the moment)
I don't know about "good practice", but it's certainly not "bad practice". I see no difference whether you do it in the app or a different one.
I think its a good thing but only if what you are doing in the API is kept as generic as possible to other applications and services can reuse the API.
Both the applications I have written and continue to maintain use pretty much the exact same stack as your app.
I have recently re-factored one of the applications to use the API for all the common things like lists that I'm binding to Kendo ComboBoxes etc. in my views. Its a fairly large application that re-uses a lot of the same lists such as states, priorities, complexities across various Entities and views so it makes sense to put those in the API.
I haven't gone as far as going the whole hog through. I draw the line with things like this:
public ActionResult GetAjaxProjectsList([DataSourceRequest]DataSourceRequest request)
{
return Json((DataSourceResult)GetProjectsList().ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
That is very specific to how the Kendo Grid wants the data back. Nothing else I have connecting to this app will use this data in this format so I keep it in the controller.
In short... I use the API for common things within the same MVC app and things that I allow to be used by other applications or services, like Excel.
most of the time in the service code I would have something like this:
public SomeService : ISomeService
{
ISomeRepository someRepository;
public Do(int id)
{
someRepository.Do(id);
}
}
so it's kinda redundant
so I started to use the repositories directly in the controller
is this ok ? is there some architecture that is doing like this ?
You lose the ability to have business logic in between.
I disagree with this one.
If business logic is where it should be - in domain model, then calling repo in controller (or better - use model binder for that) to get aggregate root and call method on it seems perfectly fine to me.
Application services should be used when there's too much technical details involved what would mess up controllers.
I've seen several people mention using model binders to call into a repo lately. Where is this crazy idea coming from?
I believe we are talking about 2 different things here. I suspect that Your 'model binder' means using model simultaneously as a view model too and binding changed values from UI directly right back to it (which is not a bad thing per se and in some cases I would go that road).
My 'model binder' is a class that implements 'IModelBinder', that takes repository in constructor (which is injected and therefore - can be extended if we need caching with some basic composition) and uses it before action is called to retrieve aggregate root and replace int id or Guid id or string slug or whatever action argument with real domain object. Combining that with input view model argument lets us to write less code. Something like this:
public ActionResult ChangeCustomerAddress
(Customer c, ChangeCustomerAddressInput inp){
c.ChangeCustomerAddress(inp.NewAddress);
return RedirectToAction("Details", new{inp.Id});
}
In my actual code it's a bit more complex cause it includes ModelState validation and some exception handling that might be thrown from inside of domain model (extracted into Controller extension method for reuse). But not much more. So far - longest controller action is ~10 lines long.
You can see working implementation (quite sophisticated and (for me) unnecessary complex) here.
Are you just doing CRUD apps with Linq To Sql or trying something with real domain logic?
As You can (hopefully) see, this kind of approach actually almost forces us to move towards task based app instead of CRUD based one.
By doing all data access in your service layer and using IOC you can gain lots of benefits of AOP like invisible caching, transaction management, and easy composition of components that I can't imagine you get with model binders.
...and having new abstraction layer that invites us to mix infrastructure with domain logic and lose isolation of domain model.
Please enlighten me.
I'm not sure if I did. I don't think that I'm enlightened myself. :)
Here is my current model binder base class. Here's one of controller actions from my current project. And here's "lack" of business logic.
If you use repositories in your controllers, you are going straight from the Data Layer to the Presentation Layer. You lose the ability to have business logic in between.
Now, if you say you will only use Services when you need business logic, and use Repositories everywhere else, your code becomes a nightmare. The Presentation Layer is now calling both the Business and Data Layer, and you don't have a nice separation of concerns.
I would always go this route: Repositories -> Services -> UI. As soon as you don't think you need a business layer, the requirements change, and you will have to rewrite EVERYTHING.
My own rough practices for DDD/MVC:
controllers are application-specific, hence they should only contain application-specific methods, and call Services methods.
all public Service methods are usually atomic transactions or queries
only Services instantiate & call Repositories
my Domain defines an IContextFactory and an IContext (massive leaky abstraction as IContext members are IDBSet)
each application has a sort-of Composition Root, which is mainly instantiating a Context Factory to pass to the Services (you could use DI container but not a big deal)
This forces me to keep my business code, and data-access out of my controllers. I find it a good discipline, given how loose I am when I don't follow the above!
Here is the thing.
"Business Logic" should reside in your entities and value objects.
Repositories deal with AggregateRoots only. So, using your repositories directly in your Controllers kinda feels like you are treating that action as your "service". Also, since your AggregateRoot may only refer to other ARs by its ID, you may have to call one more than one repo. It really gets nasty very quickly.
If you are going to have services, make sure you expose POCOs and not the actual AggregateRoot and its members.
Your repo shouldn't have to do any operations other than creating, retrieving, updating and deleting stuff. You may have some customized retrieve based on specific conditions, but that's about it. Therefore, having a method in your repo that matches one in your service... code smell right there.
Your service are API oriented. Think about this... if you were to pack that service in a .dll for me to use, how would you create your methods in a way that is easy for me to know what your service can do? Service.Update(object) doesn't make much sense.
And I haven't even talked about CQRS... where things get even more interesting.
Your Web Api is just a CLIENT of your Service. Your Service can be used by another service, right? So, think about it. You most likely will need a Service to encapsulate operations on AggregateRoots, usually by creating them, or retrieving them from a repo, do something about it, then returning a result. Usually.
Makes sense?
Even with "rich domain model" you will still need a domain service for handling business logic which involves several entities. I have also never seen CRUD without some business logic, but in simple sample code. I'd always like to go Martin's route to keep my code straightforward.
Say you have an ASP.NET MVC project and are using a service layer, such as in this contact manager tutorial on the asp.net site: http://www.asp.net/mvc/tutorials/iteration-4-make-the-application-loosely-coupled-cs
If you have viewmodels for your views, is the service layer the appropriate place to provide each viewmodel? For instance, in the service layer code sample there is a method
public IEnumerable<Contact> ListContacts()
{
return _repository.ListContacts();
}
If instead you wanted a IEnumerable, should it go in the service layer, or is there somewhere else that is the "correct" place?
Perhaps more appropriately, if you have a separate viewmodel for each view associated with ContactController, should ContactManagerService have a separate method to return each viewmodel? If the service layer is not the proper place, where should viewmodel objects be initialized for use by the controller?
Generally, no.
View models are intended to provide information to and from views and should be specific to the application, as opposed to the general domain. Controllers should orchestrate interaction with repositories, services (I am making some assumptions of the definition of service here), etc and handle building and validating view models, and also contain the logic of determining views to render.
By leaking view models into a "service" layer, you are blurring your layers and now have possible application and presentation specific mixed in with what should focused with domain-level responsibilities.
No, I don't think so. Services should care only about the problem domain, not the view that renders results. Return values should be expressed in terms of domain objects, not views.
As per the traditional approach or theory wise, ViewModel should be part of User interface layer. At least the name says so.
But when you get down to implementing it yourself with Entity Framework, MVC, Repository etc, then you realise something else.
Someone has to map Entity/DB Models with ViewModels(DTO mentioned in the end). Should this be done in [A] the UI layer (by the Controller), or in [B] the Service layer?
I go with Option B. Option A is a no no because of the simple fact that several entity models combine together to form a ViewModel. We may not pass unnecessary data to UI layer, whereas in option B, the service can play with data and pass only the required/minimum to the UI layer after mapping (to the ViewModel).
But still, let us go with option A, put ViewModel in the UI layer(and entity model in Service layer).
If the Service layer needs to map to the ViewModel, then the Service layer need to access ViewModel in UI layer. Which library/project? The Viewmodel should be in a separate project in the UI layer, and this project needs to be referenced by Service Layer. If the ViewModel is not in a separate project, then there is circular reference, so no go. It looks awkward to have Service layer accessing UI layer but still we could cope with it.
But what if there is another UI app using this service? What if there is a mobile app? How different can the ViewModel be? Should the Service access the same view model project? Will all UI projects access the same ViewModel project or they have their own?
After these considerations my answer would be to put the Viewmodel project in Service Layer. Every UI layer has to access the Service layer anyways! And there could be a lot of similar ViewModels that they all could use (hence mapping becomes easier for service layer). Mappings are done through linq these days, which is another plus.
Lastly, there is this discussion about DTO. And also about data annotation in ViewModels. ViewModels with data annotations(Microsoft.Web.Mvc.DataAnnotations.dll) cannot reside in service layer instead they reside in UI layer(but ComponentModel.DataAnnotations.dll can reside in service layer). If all projects are in one solution(.sln), then it doesn't matter which layer you put it. In enterprise applications, each layer will have its own solution.
So DTO actually is a ViewModel because mostly there will be one on one mapping between the two(say with AutoMapper). Again DTO still has the logic needed for the UI(or multiple applications) and resides in Service Layer. And the UI layer ViewModel(if we use Microsoft.Web.Mvc.DataAnnotations.dll) is just to copy the data from DTO, with some 'behavior'/attributes added to it.
[Now this discussion is about to take an interesting turn read on...:I]
And don't think data-annotation attributes are just for UI. If you limit the validation using System.ComponentModel.DataAnnotations.dll
then the same ViewModel can also be used for front-end & backend validation(thus removing UI-residing-ViewModel-copy-of-DTO). Moreover attributes can also be used in entity models. Eg: using .tt, Entity Framework data models can be autogenerated with validation attributes to do some DB validations like max-length before sending to the back end. This saves round-trips from UI to backend for validation. It also enables back-end to re-validate for security reasons. So a model is a self-reliant validator and you can pass it around easily. Another advantage is that if backend validation changes in DB then .tt (reads DB specifics and create the attribute for entity class) will automatically pick that up. This can force UI validation unit tests to fail as well, which is a big plus(so we can correct it and inform all UIs/consumers instead of accidentally forgetting and failing). Yes, the discussion is moving towards a good framework design. As you can see it is all related: tier-wise validation, unit test strategy, caching strategy, etc.
Although not directly related to the question. 'ViewModel Façade' mentioned in this must watch channel 9 link is also worth exploring. It starts exactly at 11 minutes 49 seconds in the video. Because this would be the next step/thought once your current question given above is sorted out: 'How to organize ViewModels?'
And Lastly, many of these model vs logic issues could be resolved with REST. Because every client can have the intelligence to query the data and get only the data that it needs. And it keeps the model in UI, there is no server/service layer model/logic. The only duplication then will be on the automated tests that each client need to perform. Also if there are changes in data then some clients fail if they do not adapt to the change. The question then is, are you removing service layer altogether(and the models they carry) or pushing the service layer up to your UI project(so model issue still persists) which calls the REST API. But in terms of the responsibility of Service layer, they are the same regardless.
Also in your example "_repository.ListContacts()" is returning a ViewModel from repository. This is not a mature way. Repositories should provide entity models or DB models. This gets converted to view models and it is this view model that is returned by the service layer.
This has come a bit of an "it depends" where I work - we have generally had a controller consuming some service(s) - then combining returned DTO's into a 'ViewModel' that would then get passed to the client - either via JSON result, or bound in the Razor Template.
Thing is, about 80% of the time - the mapping of DTO to ViewModel has been 1-1. We are starting to move towards 'Where needed, just consume the DTO directly, but when the DTO and what we need in our client/view don't match up - then we create a ViewModel and do the mapping between objects as needed'.
Although I'm still not convinced that this is the best or right solution - as it ends up leading to some heated discussions of 'are we just adding X to the DTO to meet the needs of the view?'
I suppose that depends on what you consider the "services" to be. I've never really liked the term service in the context of a single class; it's incredibly vague and doesn't tell you much about the actual purpose of the class.
If the "service layer" is a physical layer, such as a web service, then absolutely not; services in an SOA context should expose domain/business operations, not data and not presentation logic. But if service is just being used as an abstract concept for a further level of encapsulation, I don't see any problem with using it the way you desribe.
Just don't mix concepts. If your service deals with view models then it should be a presentation service and be layered over top of the actual Model, never directly touching the database or any business logic.
Hi I see very good answers here.
And for myself I do an other aproach.
I have to kinds of models , one is viewmodel and the other is shared models. The viewmodels stays on the UI layer and the shared models stays on a separate project.
The shared models can theoretically be used anyware because those are standalone.
This models provides some abstraction if you want to return specific data from your service layer or if you need something specific from your repository.
I don't really know if this is a good aproach but it works so well on my projects. For example
When I need to provide some information to create new objects to the database i can use the shared models directly to the service layer it saves me some complexity.
The shared models needs to be mapped sometimes , but you can ensure that your service is not leaking inesssary data to the UI.
You can see shared models as an extension but not to build your UI logic with it, you should have viewmodels to do that.
You can combine viewmodels with this shared models to save you time you can use inheritance.
The shared models has to be neutral and should not have any kind of logic.