What is the best way to write data via MVC into database? - c#

I am working on a homework project using MVC with EF Core.
I am looking for the best way to write data into the database. (I am beginner)
There are two tables. Predbilježba(Enrollment) and Seminari(Seminars)
public class Predbilježba
{
[Key]
public int PredbilježbeID { get; set; }
public string Ime { get; set; }
public string Prezime { get; set; }
public string Adresa { get; set; }
public string Email { get; set; }
public string Telefon { get; set; }
public bool Status { get; set; }
[DataType(DataType.Date)]
public DateTime DatumUpisa { get; set; }
public int SeminarID { get; set; }
public Seminar Seminar { get; set; }
}
public class Seminar
{
public int SeminarID { get; set; }
public string Naziv { get; set; }
public string Opis { get; set; }
[DataType(DataType.Date)]
public DateTime Datum { get; set; }
public bool Popunjen { get; set; }
public ICollection<Predbilježba> Predbilježba { get; set; }
}
I need to insert a sort of Enrollment (Named: Predbilježba) into the database.
Enrollment is connected to a table called Seminars (Named: Seminari).
So when a person is "enrolling" into a "seminar", he/she needs to insert basic data into form (name, phone number, etc.) and they need to choose a "seminar" from a list of given seminars which are in "Seminar" table.
So when they click "Save", their basic data is written into Predbilježba / (eng. Enrollment)" along with chosen "seminar"
So I already have controllers for these 2 models, and appropriate views to create, edit, and so on..
My question is: Do I create a separate controller/model/view to insert data into tables? Can someone give me some example of how it is done?
To clarify further, I need to make user side page where user can "enroll" to "seminar" by writing name, last name, etc.. and by choosing the desired seminar. For now I have functional database, Identity (which will be used later in project), controllers of both models, and appropriate views where I can edit Prebilježbe(eng. Enrollments) and Seminars.
Images of page follow:
So when user clicks Upiši se (eng. enroll) as shown in image number 3. , that selected Seminar, along with basic info that opens after the click (image 4 ) needs to be written into database "Predbilježbe" (eng Enrollments)
This "Upis" page would be a user input page, and "Seminari" and "Predbilježbe" would be admin pages..

If I understand your question correctly, you are asking about good architectural design. Aren't you? (if not please let me know to edit the answer).
You have many architectural choices and possibilities. The easiest one for you to start with is the Service-Repository architectural pattern. I would omit the Repository word here because EF is already (in my opinion) a Repository pattern implementation (at least partially).
So to keep it simple, you would like to start with Service architectural pattern. Which is about creating a class, which injects the DbContext in its construction (let's name it PredbilježbaService). And in this class, you handle all operations of your logic (including database EF queries).
Then you inject this class to your controller and call the required functions from that service class (which deals with the database) in your controller.
The same process can be applied to the other entity Seminar.
P.S. by injecting I mean using any IoC design pattern (in ASP.Net Core, dependency injection is already built-in).
So after these brief words, to answer your question directly, yes, a good software design would be by creating a separate class which handles database operations (adding rows, editing rows, etc.)

It all depends on what your application is supposed to do.
If this is nothing more than a few views around a few tables, then it is perfectly fine to save these objects directly from the controller. The best design is usually the simplest one and there is no need to overcomplicate things with layers, architectural patterns and so on. These are relevant when the size of the project is much larger than in your case.
Good design is all about communication. If someone else is supposed to maintain your project, will it be clear to them where to find the functionality?
I would expect two controllers: one for seminars (called SeminarController) and one for enrollments (called EnrollmentController). These will have methods for viewing, inserting, modifying and deleting data. I would be able to extend your project easily because I know where (and how) to find the code. So your suggestion seems like a good fit.
Response to comment
In the list of seminars has a link pointing to the screen where someone can register for a seminar. That action needs to know which seminar has been selected. The way to do it is to pass the id of the seminar with the request, e.g. /Enrollment/Register/{seminar id}. This results in a GET-request. The form in the enrollment view will POST the inputted data back to the controller.
In the EnrollmentController you would have something like this:
private readonly MyDbContext context;
// Constructor and other methods omitted
[HttpGet]
public ActionResult Register(int seminarId)
{
var seminar = context.Seminars.Single(x => x.Id == seminarId);
return View(seminar);
}
[HttpPost]
public ActionResult Register(Enrollment enrollment)
{
context.Enrollment.Add(enrollment);
return RedirectToAction("index", "Seminar");
}
Depending on the requirements, you might need to insert some validation etc.

You need to study about software architectures a bit to clarify this. Try reading about Layered Architecture for basic structures, and I am assuming you already understand how the MVC architecture works. These will clarify where to perform which task. One of my favorites is the Onion architecture. So basically when you implement an architecture in your code, it becomes much more easy to read, control and track all activities performed within the code.
At the simplest, it is better to split the tasks as below:
1. You define your model classes
2. You create a database class/layer, where you will implement the logic to perform data base queries into your database with respect to the models and return the formatted data (This is where you perform the EF core queries).
3. You create your controllers, where you handle tasks by sending appropriate requests to the database layer and fetch the formatted data.
4. You create your views based on the expected model, and setup the controllers to send the formatted model data to the appropriate view.
A good place to start is here: Tutorial on EF core with MVC

The best way to achieve this in MVC is tu use the nuget package EntityFrameworkCore
Here is a step by step documentation: https://learn.microsoft.com/en-us/ef/core/get-started/
For any further questions, feel free to ask.

Related

Updating DDD Aggregates with Collections

So, I've got an aggregate( Project ) that has a collection of entities (ProjectVariables) in it. The variables do not have Ids on them because they have no identity outside of the Project Aggregate Root.
public class Project
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<ProjectVariable> ProjectVariables { get; set; }
}
public class ProjectVariable
{
public string Key { get; set; }
public string Value { get; set; }
public List<string> Scopes { get; set; }
}
The user interface for the project is an Angular web app. A user visits the details for the project, and can add/remove/edit the project variables. He can change the name. No changes persist to the database until the user clicks save and the web app posts some json to the backend, which in turns passes it down to the domain.
In accordance to DDD, it's proper practice to have small, succinct methods on the Aggregate roots that make atomic changes to them. Examples in this domain could be a method Project.AddProjectVariable(projectVariable).
In order to keep this practice, that means that the front end app needs to track changes and submit them something like this:
public class SaveProjectCommand
{
public string NewName { get; set; }
public List<ProjectVariable> AddedProjectVariables { get; set; }
public List<ProjectVariable> RemovedProjectVariables { get; set; }
public List<ProjectVariable> EditedProjectVariables { get; set; }
}
I suppose it's also possible to post the now edited Project, retrieve the original Project from the repo, and diff them, but that seems a little ridiculous.
This object would get translated into Service Layer methods, which would call methods on the Aggregate root to accomplish the intended behaviors.
So, here's where my questions come...
ProjectVariables have no Id. They are transient objects. If I need to remove them, as passed in from the UI tracking changes, how do identify the ones that need to be removed on the Aggregate? Again, they have no identification. I could add surrogate Ids to the ProjectVariables entity, but that seems wrong and dirty.
Does change tracking in my UI seem like it's making the UI do too much?
Are there alternatives mechanisms? One thought was to just replace all of the ProjectVariables in the Project Aggregate Root every time it's saved. Wouldn't that have me adding a Project.ClearVariables() and the using Project.AddProjectVariable() to the replace them? Project.ReplaceProjectVariables(List) seems to be very "CRUDish"
Am I missing something a key component? It seems to me that DDD atomic methods don't mesh well with a pattern where you can make a number of different changes to an entity before committing it.
In accordance to DDD, it's proper practice to have small, succinct
methods on the Aggregate roots that make atomic changes to them.
I wouldn't phrase it that way. The methods should, as much as possible, reflect cohesive operations that have a domain meaning and correspond with a verb or noun in the ubiquitous language. But the state transitions that happen as a consequence are not necessarily small, they can change vast swaths of Aggregate data.
I agree that it is not always feasible though. Sometimes, you'll just want to change some entities field by field. If it happens too much, maybe it's time to consider changing from a rich domain model approach to a CRUD one.
ProjectVariables have no Id. They are transient objects.
So they are probably Value Objects instead of Entities.
You usually don't modify Value Objects but replace them (especially if they're immutable). Project.ReplaceProjectVariables(List) or some equivalent is probably your best option here. I don't see it as being too CRUDish. Pure CRUD here would mean that you only have a setter on the Variables property and not even allowed to create a method and name it as you want.

How to access data when a viewModel depends on several models

I'm a novice trying to wrap my head around MVVM. I'm trying to build something and have not found an answer on how to deal with this:
I have several models/entities, some of which have logical connections and I am wondering where/when to bring it all together nicely.
Assume we have a PersonModel:
public class PersonModel
{
public int Id { get; set; }
public string Name { get; set; }
...
}
And a ClubModel:
public class ClubModel
{
public int Id { get; set; }
public string Name { get; set; }
...
}
And we have MembershipModel (a Person can have several Club memberships):
public class MembershipModel
{
public int Id { get; set; }
public PersonId { get; set; }
public ClubId { get; set; }
}
All these models are stored somewhere, and the models are persisted "as in" in that data storage.
Assume we have separate repositories in place for each of these models that supplies the standard CRUD operations.
Now I want to create a view model to manage all Persons, e.g. renaming, adding memberships, etc. -> PersonMangementViewModel.
In order to nicely bind a Person with all its properties and memberships, I would also create a PersonView(?)Model that can be used in the PersonManagementViewModel. It could contain e.g. view relevant properties and also the memberships:
public class PersonViewModel : PersonModel
{
public Color BkgnColor { get return SomeLogic(); }
public IEnumerable<MembershipModel> { get; set; }
...
}
My question here is, how would I smartly go about getting the Membership info into the PersionViewModel? I could of course create an instance of the MemberShipRepo directly in the PersionViewModel but that seems not nice, especially if you have a lot of Persons. I could also create all repositories in the PersonManagementViewModel and then pass references into the PersonViewModel.
Or does it make more sense to create another layer (e.g. "service" layer) that returns primarily the PersonViewModel, therefore uses the individual repositories and is called from the PersonManagementViewModel (thus removing the burden from it and allowing for re-use of the service elsewhere)?
Happy to have pointed out conceptional mistakes or some further reading.
Thanks
You are creating separate model for each table I guess. Does not matter, but your models are fragmented. You can consider putting related data together using Aggregate Root and Repository per Aggregate root instead of per model. This concept is discussed under DDD. But as you said you are new to MVVM, there is already lot much to learn. Involving DDD at this stage will only complicate the things.
If you decide to keep the things as is, best and quick thing I can guess is what you are doing now. Get instance of model from data store in View Model (or whatever your location) and map somehow. Tools like Automapper are good but they does not fit each situation. Do not hesitate to map by hand if needed. You can also use mix approach (Automapper + map by hand) to simplify the things.
About service layer, sure... why not. Totally depends on you. If used, this layer typically contain your business logic, mapping, formatting of data, validations etc. Again, each of that thing is up to you.
My suggestions:
Focus on your business objectives first.
Design patterns are good and helpful. Those are extract of many exceptionally capable developers to solve specific problem. Do use them. But, do not unnecessarily stick to it. Read above suggestion. In short, avoid over-engineering. Design patterns are created to solve specific problem. If you do not have that problem, then do not mess-up your code with unnecessary pattern.
Read about Aggregate Root, DDD, Repository etc.
Try your best to avoid Generic Repository.

ViewModel concept still exists in ASP.NET MVC Core?

In previous versions of ASP.NET MVC you find some informations about ViewModels and how to use them in this version.
I'm wondering why I can't find any information about this topic in ASP.NET Core MVC? Does the concept still exist and if so where i need to put them?
The question comes up because i want to make a dashboard for projects. Projects are the main entry point in my web app. They have many relationships e.g with milestones.
Models:
public class Project
{
public int ProjectId { get; set; }
public string Name { get; set; }
public ICollection<Milestone> Milestones { get; set; }
...
}
public class Milestone
{
public int MilestoneId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime Deadline { get; set; }
public int? ParentId { get; set; }
public Milestone Parent { get; set; }
public ICollection<Milestone> Childrens { get; set; }
...
}
Before ASP.NET Core I created a ProjectDashboardViewModel for getting information to the view. Can I use the same approach?
"Does the concept still exist?" "Can I use the same approach?"
Yes, the ViewModel concept is still applicable in .NET Core and you would still use them as before, i.e. to assemble a selection of data into a 'shape' that matches the needs of a particular view.
"I can't find any information about this topic in ASP.NET Core MVC"
The official documentation discusses view models extensively. The Overview of ASP.NET Core MVC section has this to say:
Model Responsibilities
The Model in an MVC application represents the state of the
application and any business logic or operations that should be
performed by it. Business logic should be encapsulated in the model,
along with any implementation logic for persisting the state of the
application. Strongly-typed views will typically use ViewModel types
specifically designed to contain the data to display on that view; the
controller will create and populate these ViewModel instances from the
model.
In the Rendering HTML with views section:
You can pass data to views using several mechanisms. The most robust
approach is to specify a model type in the view (commonly referred to
as a viewmodel, to distinguish it from business domain model types),
and then pass an instance of this type to the view from the action. We
recommend you use a model or view model to pass data to a view.
The MVC/Advanced/Application Parts section also discusses View Models, the sample code there shows how you can assemble a number of different objects together for consumption by the view with a view model.
They also mention them in the section on Partial Views. There is some sample code that goes along with that here, but those examples don't actually really highlight the difference between a model and a view model.
A search through the docs as follows highlights some more too: https://learn.microsoft.com/en-us/search/index?search=viewmodel&scope=ASP.NET+Core
"..i want to make a dashboard for projects"
In your case the data you've provided just shows a single domain object (the 'Project') which has some child objects. If that's all the data you want to show then you probably don't need a view model as it would simply be a mirror of your Project model.
However, if you want to show other info on the Project dashboard, e.g. some data aggregated data about the number of projects in progress, a list of which projects are behind etc. then you might assemble a view model with properties for: Project, NumberInProgressPrjects, OverdueProjectsList etc.
public class ProjectDashboardViewModel
{
public Project Project { get; set; }
public int NumberInProgressProjects { get; set; }
public ICollection<OverdueProjectInfo> OverdueProjectsList { get; set; }
}
That's just an example, the point is you can use the view model to encapsulate all of the data needed by your view, rather than your controller returning a model object that matches a single domain object (often a table from your database) and then lots of additional data that's needed to make the rest of the page function in the ViewData collection (e.g. the data needed to populate the drop down lists). There are many excellent articles on view models, this previous question covers them exhaustively for example, and is just as relevant in .NET MVC Core as other versions of MVC.
"..where i need to put them?"
You can put them where you choose, just make sure you use a using statement if needed. The typical convention in smaller projects is to put them in a folder called 'ViewModels'.
ViewModel / MVVM (Model-View-ViewModel) is an architectural pattern and not tied to any framework or stack.
Means you can still use it, it is just an additional abstraction layer on top of the MVC pattern which brings the data in a form that makes it easy to consume for the view.
You can use the relationsships from the dbcontext
https://learn.microsoft.com/en-us/ef/core/modeling/relationships

DDD: guidance on updating multiple properties of entities

So, i decided to learn DDD as it seems to solve some architectural problems i have been facing. While there are lots of videos and sample blogs, i have not encountered one that guides me to solve the following scenario:
Suppose i have the entity
public class EventOrganizer : IEntity
{
public Guid Id { get; }
public string Name { get; }
public PhoneNumber PrimaryPhone { get; }
public PhoneNumber AlternatePhone { get; private set; }
public Email Email { get; private set; }
public EventOrganizer(string name, PhoneNumber primaryPhoneNr)
{
#region validations
if (primaryPhoneNr == null) throw new ArgumentNullException(nameof(primaryPhoneNr));
//validates minimum length, nullity and special characters
Validator.AsPersonName(name);
#endregion
Id = new Guid();
Name = name;
PrimaryPhone = primaryPhoneNr;
}
}
My problem is: suppose this will be converted and fed to a MVC view and the user wants to update the AlternatePhone, the Email and a lot of other properties that make sense to exist within this entity for the given bounded context (not shown for brevity)
I understand that the correct guidance is to have a method for each operation, but (AND I KNOW ITS KINDA OF ANTI-PATTERN) i cant help but wonder if this wont end up triggering multiple update calls on the database.
How is this handled ? somewhere down the line, will there be something that maps my EventOrganizer to something - say DbEventOrganizer and gathers all changes made to the domain entity and apply those in a single go?
DDD is better suited for task-based UIs. What you describe is very CRUD-oriented. In your case, individual properties are treated as independent data fields where one or many of these can be updated by a single generic business operation (update).
You will have to perform a deeper analysis of your domain than this if you want to be successfull with DDD.
Why would someone update all those fields together? What implicit business operation is the user trying to achieve by doing that? Is there a more concrete business process that is expressed by changing PrimaryPhone, AlternatePhone and Email together?
Perhaps that is changing the ContactInformation of an EventOrganizer? If that's the case then you could model a single ChangeContactInformation operation on EventOrganizer. Your UI would then send a ChangeContactInformation command rather than an update command.
As for the persistence of your aggregate roots (AR), this is usually handled by an ORM like NHibernate if you are using a RDBMS. However, there are other ways to persist your ARs like Event Sourcing, NoSQL DBs and even storing JSON or any other data inter-change formats in a RDBMS.
You question is quite broad!
EventOrganizer itself should not be updating anything. You should keep your update code quite separate from the entity. A different class would take an EventOrganizer object and update the DB. This is called 'persistence ignorance' and makes the code a lot more modular and cohesive.
It would be common to create a View Model - a class whose purpose is to provide the View with the exact data it needs in the exact form it needs. You would need to create the View Model from your EventOrganizer, after which the View can update it - programmatically or with binding. When you're ready to save the changes, you'll need to update your EventOrganizer from the View Model and pass it onto the updater. This seems like a layer you don't need when the project is small and simple, but it is becomes invaluable as the complexity builds.

MVP - How to expose specific properties of my Model

I am using the MVP pattern in a C# winforms application and came across the following design issue. I have a User class in my domain and a UserCollectionDAO class that essentially loads all users with some other bits of information from a database. When I am presenting a collection of users to my view via the presenter I do not want to show all their properties. For example my User has the following properties:
class User
{
public User(int id)
{
Id = id;
}
public int Id { get; private set; }
public string Name { get; set; }
public LocationId { get; set; }
}
What I want to show in my Listview of users is the Name and the name of the Location which I can get from another data structure in my system. At the same time I want to use the LocationId and the Id in other areas of my application. I have read about another layer that one might need to use, that of DTO objects. What is your opinion on that and can you see another way of achieving what I want? How can I pass information from the View to the DTO User instance to the domain User instance?
Any ideas would be much appreciated.
Usually you would have your domain class/model get converted to a ViewModel (a model specific to a particular view, hiding particular properties of your model).
At the domain services layer create a method that converts your model to a view model or use a library like AutoMapper to autoconvert it to you. Some of the properties on your domain user class might need to be public (why aren't they?) to be copied over automatically by AutoMapper.
Further reading: MVVM pattern

Categories

Resources