Here are some guidelines for your framework.
Entity Framework
For each of your models returned from EF, Retrieve the EF model interface and use the interface as a data source, rather than an implemented EF class. The reason for this is that if you decide to use a different data source for any one or more models (or the entire Entity Framework), you can just make sure that your new data layer returns the same interfaces, without having to change your entire network code . The downside is that your interfaces are updated when the model changes.
It also allows your view models to implement the EF model interface (with additional logic of your choice). This is beneficial if all your calls for inserts / updates to the Data Layer accept the same interface models that were returned. This allows you to create several models with different requirements that correspond to what is required to enter / update the data level. The disadvantage is that in your Data Layer you need to [create a new EF model] / [Get the model to update] and map the fields from the interface to the model.
Browse Models
I highly recommend that each presentation model is not the actual model (s) to be displayed, but a class that contains the model (s). Examples:
public class Car //Not what I recommend passing to a view { public string Make { get; set; } public string Model { get; set; } } //Pass this to the view, i'll explain why... public class CarViewModel : IPartialViewCar { public Car Car { get; set; } public ColorCollection { get; set; } }
By running the CarViewModel example, you can separate partial views from views. Here's how (using the above models):
public interface IPartialViewCar { public Car { get; } } [BuildCar.cshtml] @Model MyNameSpace.Models.Car @Html.EditorFor(model) [PartialViewCar.cshtml] @Model MyNameSpace.Models.IPartialViewCar @Html.EditorFor(model)
Now anytime you want to use a PartialViewCar , you just need to create a model that implements the IPartialViewCar interface, basically separating the partial view from the view.
Check
I would recommend creating interfaces (classes if you really want, but really don't need there) that have all of your validation logic.
Suppose we want anonymous users to enter both make and model, but registered users only need to enter Make. How this can be done easily, here's how: (in more detail about the previous code)
public interface IAnonymouseCarValidation { [required] public string Make { get; set; } [required] public string Model { get; set; } } public interface IRegisteredCarValidation { [required] public string Make { get; set; } } public interface ICar { public string Make { get; set;} public string Model { get; set; } } [updating the Car model to abstract and use an interface now] public abstract class Car : ICar {
Now you can create either AnonymouseCar or RegisteredCar , transfer it to CarViewModel, and let MVC take care of the verification. When you need to update validation, you update one interface. The disadvantage of this is that it feels rather complicated.
Injection Requests and Data
My preference is to try to simplify the actions of the controller as much as possible and not include the code for data extraction there. The reason I donโt want to do this is because I donโt like repeating code. For instance:
public class AccountControllers { DataServer _Service; public AccountControllers(DataServer Service) { this._Service = Service; } public ActionResult ShowProfiles() { ProfileViewModel model = new ProfileViewModel(); model.Profiles = this._Service.Profiles(); return View(model); } public ActionResult UpdateProfile(ProfileViewModel updatedModel) { service.UpdateProfile(updatedModel); ProfileViewModel model = new ProfileViewModel(); model.Profiles = this._Service.Profiles(); return View(model); } }
Instead, I would do something like: (not fully)
public ActionResult ShowProfile(Guid ID) { ProfileViewModel model = new ProfileViewModel(this._service); return View(model); } public ActionResult UpdateProfile(ProfileViewModel updatedModel) { // pass in the service, or use a property or have SetService method updatedModel.Update(this._service) ProfileViewModel model = new ProfileViewModel(this._service); return View(model); } public class ProfileViewModel() { DataServer _Service; Profile _Profile public ProfileViewModel() { } public ProfileViewModel(DataServer Service) { this._Service = Service; } public Profile Profiles() { get { if (this._service == null) { throw new InvalidOperationException("Service was not set."); } return = Service.Profiles(ID); }
This means that the profiles are listed ONLY when they are requested, I do not have to fill it out myself. As a rule, these are fewer errors if I use this code to my advantage, instead of requiring me or other programmers to manually fill in the models.