I'm just starting to learn the MVC design pattern, and I was wondering where should my SQL code go.
For example, lets say I have a register form structure that looks like this
type Form struct {
Username string
Password string
}
I assume that the form structure is part of the model, so I have some function that goes with the form that after a user submits the form, the data gets put into the database, so my function would look something like this
func (f *Form) registerUser() {
// SQL code goes here
}
Is this the best way of doing it? I have been searching around for open source Golang web apps that utilizes the MVC pattern, but I have not be able to find one which I completely understand.
In model-view-controller pattern...
Model is for entities all your classes represent real world objects.
View is the forms and all the graphic things user can see and interact with.
Controller is for controller classes, is all the logic of the program, for the sql code as you said you can implement a dao pattern and have all the sql code in the controller package and the database class in the entities package(i leave it in the Controller class).
I assume that the form structure is part of the model, so I have some function that goes with the form that after a user submits the form, the data gets put into the database, so my function would look something like this
Another use of Model in MVC application architecture is to store reusable code. So, yes, you can store the form in Model (for example, if you reuse it multiple in views) but this makes less sense than storing form in a View and reuse it later on.
The execution backtrace would be something like
Controller processes the request - personally, I do the business logic here and also (if necessary) invoke ...
Model that handles all the data retrieval from DBMS, validation, etc. and returns processed data to Controller and ...
The View is then displayed with the respective parameters (user data, template, validator result, etc.).
User fills in the form and submits the input to Controller and ...
GOTO 1. point
Related
How to create a TextField is explained very well in a tutorial. But I am wondering how to store and retrieve the entered strings in a persistant way, that survives application termination and restart (something like a Bash history).
I will try to give you a very briefly answer
You need
a viewmodel class
a repository class
a database (room database is ideal)
an entity data class
a dao class
You should find more info about room database from jetpack libraries.
Of course are uncounted ways to implement this feature but it is in general the following way recommended.
You capture from your view the query string, may on submit.
In viewmodel you implement a method captureSearchQuery(query: String)
Also in viewmodel you implement a method for example retrieveSearchHistory() : Flow<List>
The repository class is your single source of true, is the layer between the data layer and the view layer, you implement also this two methods you need, captureSearchQuery and retrieveSearchHistory. In repository class you can may transform your data, for example is a good practice to have a separate data model for the data you display on the view from your room entity. There you can do this transformation for exmaple.
Now you have setup your room database you can insert and get the data you need.
The data should go this way:
View -> Viewmodel -> Repository -> Room database
View <- Viewmodel <- Repository <- Room database
The layer should never communicate otherway, (clean architecture) for example:
View -> Room database.
The above is my simplest explanation, I hope I help you
Just wondering really if there's a consensus on the 'right' way to do this, for MVVM, DDD, and other philosophies . . .
So I've got a login screen, represented by a ViewModel, LoginViewModel. It can take a name and password. It also takes in through dependency injection a LoginService, that implements the logic of taking the username and password, and retrieving the Employee object.
My question is what's the 'right' way to get this information to the next view model? Let's say it's AccountSettings, which needs to know about the logged in employee. How do we encapsulate that? I've got an AccountSettingsViewModel, but should it require
a) An instance of the LoginViewModel?
b) An instance of the LoginService, which keeps a reference to the logged in employee
c) A shared object or field on a global object, like App or something?
Thanks in advance!
Personally all my view models in DDD or otherwise are simple data containers, used to restrict the data that gets sent from the application to the UI/view. I might include some code in my view models that's specific to transforming data for that view. I also consider my view models to be coupled to my views (I only mention this because I've seen 2 teams put them in their own separate project/assembly away from the views!).
If I have anything copying data, or performing actions to get the data needed for the view model, this would live in either my domain model or my application layer, probably in a service. I wouldn't ever inject a service into a view model.
It appears that all the existing breezejs examples are passing entity models to and from the BreezeController.
But almost all our pages built are using some form of view models. In the days we have no BreezeJs, we retrieve the data (domain model) from a repository to populate (using AutoMapper or manually) a view model, which contains only the necessary data for that view. The WebAPI sends only the view model data over to the browser where we can populate a client-side view model (usually a knockout observable).
When saving data, we collect data from a <form> to populate an input view model, send only that data over to the server, where data in the input view model is mapped to the domain model. The update is saved by calling SaveChanges() on the DbContext entity in the repository.
Now, BreezeJs is to take over all our repository code by creating an EFContextProvider. The examples I have seen usually retrieve the domain model data and then pass it all to the client side.
[HttpGet]
public IQueryable<Item> Items() {
return _contextProvider.Context.Items;
}
It is the client-side javascript's job to build a view model.
Of course it is possible for us to build the view model at the server side:
[HttpGet]
public List<ItemViewModel> Items() {
var items = _contextProvider.Context.Items
.Include("RelatedEntity")
.ToList();
var model = new List<ItemViewModel>();
.... some code to build model from items ....
return model;
}
The benefit is that less data is transferred across the network, and we can do many manipulations on the server side. But I don't know if it is a good practice to modify this BreezeController like that. But at least, it returns data needed to list all the items.
The real trouble came when I tried to POST data back.
In the BreezeJs examples I found, they use a ko.observableArray() to store all the domain model data, let's say vm.items. Then the new record newItem is build by manager.createEntity into a domain model. After validating the data, item.entityAspect.validateEntity(), the newItem is pushed into vm.items and manager.saveChanges() is called, which somehow invokes SaveChanges() on the BreezeController.
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle) {
return _contextProvider.SaveChanges(saveBundle);
}
I find too many things have been taken over! (Laugh at me if you disagree.) My questions are:
Can I just createEntity and then saveChanges?
I only have an empty form to fill in and submit. There is certainly no need to build a whole items array on the client-side.
Can I pass an input view model as a JObject and do some server-side processing before calling _contextProvider.SaveChanges()?
It turns out to be a super long post again. Thank you for reading it all through. Really appreciate it!
Good questions. Unfortunately, our demo code seems to have obscured the real capabilities of Breeze on both client and server. Breeze is not constrained in the ways that your fear.
I don't want to repeat everything that is in our documentation. We really do talk about these issues. We need more examples to be sure.
You are describing a CQRS design. I think it over-complicates most applications. But it's your prerogative.
If you want to send ItemViewModel instead of Item, you can. If you want that to be treated as an entity on the Breeze client - have the EntityManager turn it into a KO observable and manage it in cache, change track it, validate it -, you'll have to provide metadata for it ... either on server or client. That's true for Breeze ... and every other system you can name (Ember, Backbone, etc). Soon we will make it easier to create metadata on the server for an arbitrary CLR model; that may help.
You have complete control over the query on the server, btw, whether Item or ItemViewModel. You don't have to expose an open-ended query for either. You seem to know that by virtue of your 2nd example query.
On to the Command side.
You wrote: "[the examples] use a ko.observableArray() to store all the domain model data, let's say vm.items"
That is not precisely true. The items array that you see in examples exists for presentation. The items array isn't storing anything from a Breeze perspective. In fact, after a query, the entities returned in the query response (if they are entities) are already in the manager's cache no matter what you do with the query result, whether you put them in an array or throw them away. An array plays no role whatsoever in the manager's tracking of the entities.
You wrote: "Can I just createEntity and then saveChanges?"
Of course! The EntityManager.createEntity method puts a new entity in cache. Again, the reason you see it being pushed into the items array is for presentation to the user. That array has no bearing on what the manager will save.
You wrote: "Can I pass an input view model ... and do some server-side processing before calling _contextProvider.SaveChanges()?"
I don't know what you mean by "an input viewmodel". The Breeze EntityManager tracks entities. If your "input viewmodel" is an entity, the EntityManager will track it. If it has changed and you call saveChanges, the manager will send it to the controller's SaveChanges method.
You own the implementation of the controller's SaveChanges method. You can do anything you want with that JObject which is simply a JSON.NET representation of the change-set data. I think you'll benefit from the work that the ContextProvider does to parse that object into a SaveMap. Read the topic on Customizing the EFContextProvider. Most people feel this provides what they need for validating and manipulating the client change-set data before passing those data onto the data access layer ... whether that is EF or something else.
If instead you want to create your own, custom DTO to POST to your own custom controller method ... go right ahead. Don't call EntityManager.saveChanges though. Call EntityManager.getChanges() and manipulate that change array of entities into your DTO. You'll be doing everything by hand. But you can. Personally, I'd have better things to do.
If you have a decent layered ASP.NET MVC 3 web application with a data service class pumping out view models pulled from a repository, sending JSON to an Ajax client,
[taking a breath]
what's a good way to add data filtering based on ASP.NET logins and roles without really messing up our data service class with these concerns?
We have a repository that kicks out Entity Framework 4.1 POCOs which accepts Lambda Expressions for where clauses (or specification objects.)
The data service class creates query objects (like IQueryable) then returns them with .ToList() in the return statement.
I'm thinking maybe a specification that handles security roles passed to the data service class, or somehow essentially injecting a Lambda Expression in just the right place in the data service class?
I am sure there is a fairly standardized pattern to implement something like this. Links to examples or books on the subject would be most appreciated.
If you've got a single-tiered application (as in, your web layer and service/data layer all run in the same process) then it's common to use a custom principal to achieve what you want.
You can use a custom principal to store extra data about a user (have a watch of this: http://www.asp.net/security/videos/use-custom-principal-objects), but the trick is to set this custom principal into the current thread's principal also, by doing Thread.CurrentPrincipal = myPrincipal
This effectively means that you can get access to your user/role information from deep into your service layer without creating extra parameters on your methods (which is bad design). You can do this by querying Thread.CurrentPrincipal and cast it to your own implementation.
If your service/data layer exists in a different process (perhaps you're using web services) then you can still pass your user information separately from your method calls, by passing custom data headers along with the service request and leave this kind of data out of your method calls.
Edit: to relate back to your querying of data, obviously any queries you write which are influence by some aspect of the currently logged-in user or their role can be picked up by looking at the data in your custom principal, but without passing special data through your method calls.
Hopefully this at least points you in the right direction.
It is not clear from your question if you are using DI, as you mentioned you have your layers split up properly I am presuming so, then again this should be possible without DI I think...
Create an interface called IUserSession or something similar, Implement that inside your asp.net mvc application, the interface can contain something like GetUser(); from this info I am sure you can filter data inside your middle tier, otherwise you can simply use this IUserSession inside your web application and do the filtering inside that tier...
See: https://gist.github.com/1042173
I've got this Silverlight Prism application that is using MVVM. The model calls a WCF service and a list of data is returned.
The ViewModel is bound to the View, so the ViewModel should have a List property.
Were should I keep data returned by a WCF service in MVVM?
Should the List property be calling into the Model using its getter? Where the model has a ReturnListOfData() method that returns the data stored in the model.
Or does the ViewModel stores the data after the Model is done with calling the server?
This is a follow up on Where to put the calls to WCF or other webservices in MVVM?
Generally if I need to keep the Model objects around (I consider most things coming back from a WCF service a Model object) I will store it in my ViewModel in a "Model" property.
I've seen people go so far as to create a standard Model property on their base ViewModel type, like this (I don't do this, but it's nice):
public class ViewModel<ModelType> : INotifyPropertyChanged ...
{
//Model Property
public ModelType Model
{
...
}
}
It's really up to you. Keeping them as close to their related ViewModels is probably the thing to take away here.
It really depends on other aspects of your application. E.g. how's the data returned by ReturnListOfData() used? Are there other components interested in it? Does user update elements in the list? Can it create new elements that he'll want to save later? etc.
In the simplest case you'd just have a List property exposed by your viewmodel to view, and you'd reset that list to whatever ReturnListOfData() returned. It will probably work for a case when user simply performs a search, doesn't do anything to the data later on, and there's only one view that is interested in that data.
But suppose a user wants to be able to modify elements of that list. Clearly, you'll have to somehow track the changes in that original list, so then when user clicks save (or cancel), you'd send to the server only elements that were changed (or added) or restore the original elements if user clicks cancel. In this case you'd need a Model object, that would keep the original data, so then your viewmodel contains only its copy.