Create an API using 2 Models or more - asp.net-mvc

I am new to asp.net API and started figuring out things out of online tutorials and to Stack Overflow as well.
I am into a case where I need to build An API for Member_Product table where the transaction of memberships and other products purchase is registered and in order to extract members with a certain kind of product I have to have engage another table called Product_type.
What I know is you can use one model for a single controller to build API around it. I am still confused about that as I have to use more than on in my case.
Please what is the best practice about that and how to properly implement it and if there is anything I have to read and I miss it out, it's kind of you to provide link about it.
I have used an empty controller and used both models inside with a single LINQ query. Below the code int the member controller:
private readonly dboFFEntities FitnessDbo = new dboFFEntities();
[HttpGet]
[Route("Members/activeMembers/")]
public int GetLiveMembers()
{
using (FitnessDbo)
{
var LiveMemebersCount = (from mp in FitnessDbo.memberproductinfoes
join pt in FitnessDbo.product_type on mp.mepi_prodtype equals pt.prty_typeid.ToString()
where pt.prty_name == "MEMBERSHIP" &&
(mp.mepi_status == "1" || mp.mepi_status == "3" || mp.mepi_status == "6")
select mp.mepi_memberid).Distinct().Count();
return LiveMemebersCount;
}
}

The answer is DTO.
An API controller is not bound to a DB model or any other model. It represents one entity. There is no restriction/convention on how many tables a controller should access as long as the API design is good.
The Member_Product seems to be a Junction/Pivot table.
IMO you don't need a separate API controller for junction tables.
You can create an endpoint in the Members controller to return products for passed members.
For e.g.
api/products - Returns all the products in the DB (You may not want this)
api/products/{productId} - Returns single product with passed id.
api/members - Returns all the members (without products)
api/members/{memberId}/products - Return all the products for the passed member.
Ideally, you should not return DB models in response. Create DTOs that contains all the processed information required by the client.
For e.g.
Product DTO should only contain required info about the Product it should not contain information that is for internal use and will not be used by the client.
Member DTO should only contain member info.
The DTO for Member_Product (api/members/{memberId}/products) endpoint should contain all the info about products + member.
There are many articles on this problem refer
https://medium.com/#factoryhr/how-to-build-a-good-api-relationships-and-endpoints-8b07aa37097c
ViewModels in MVC / MVVM / Separation of layers- best practices?

Related

Best practices with DTOs in ASP.NET MVC Entity Framework

What's the most preferred way to work with Entity Framework and DTOs?
Let's say that after mapping I have objects like:
Author
int id
sting name
List<Book> books
Book
int id
string name
Author author
int authorID
My DTOs
AuthorDTO
int id
sting name
BookDTO
int id
string name
int authorID
Since author can have a lot of books I don't want to retrieve all of them, when for example I'm only interested in authors.
But sometimes I might want to get few authors and filtered books or all books.
I could go with multiple queries AuthorDTO GetAuthor(int id) List<BookDTO> GetBooks(int authorID). But that means several accesses to database.
The ways I see it:
If I had in AuthorDTO field List<BookDTO> books the job could be done. But sometimes I would keep this list empty, if for example I listed only authors. And that means some unconsistency, mess and a lot of details to remember.
Return Tuple<AuthorDTO, List<BookDTO>> it might be a bit confusing.
Define new DTO.
AuthorAndBooksDTO
AuthorDTO author
List<BookDTO> books
The problem with sticking to a sinlge AuthorDTO and selectively filling the List is that you are now forced to keep track of where that DTO came from. Is the list of Books not hydrated, or does this Author simply have no books? Do I have to go back to my controller and call a different method to get a different state of the same DTO? This lacks clarity from the consumer's standpoint.
In my experience, I've leaned the way of more DTOs instead of trying to re-use a set of basic DTOs to represent multiple different sets of data. It requires a bit more "boilerplate", having to set up a whole bunch of similar DTOs and mappings between DTO and Entity, but in the end the specificity and clarity makes the codebase easier to read and manage.
I think some clarification of the issues involved will actually solve your confusion here.
First and most importantly, your entity classes are DTOs. In fact, that's all they are. They're classes that represent a table structure in your database so that data from queries Entity Framework makes can be mapped on to them. In other words, they are literally objects that transfer data. The failing of Microsoft and subsequently far too many MVC developers is to conflate them with big-M Models described by the MVC pattern.
As a result, it makes absolutely zero sense to use Entity Framework to return one or more instances of an entity and then map that to yet another DTO class before finally utilizing it in your code. All you're doing is creating a pointless level of abstraction that adds nothing to your application but yet another thing to maintain.
As far as relationships go, that's where Entity Framework's lazy/eager loading comes in. In order to take advantage of it, though, the property representing the relationship must follow a very specific convention:
public virtual ICollection<Book> Books { get; set; }
If you type it as something like List<Book>, Entity Framework will not touch the relationship at all. It will not ever load the related entities and it will not persist changes made to that property when saving the entity back to the database. The virtual keyword allows Entity Framework to dynamically subclass your entity and override the collection property to add the logic for lazy-loading. Without that, the related entities will only ever be loaded if you explicitly use Load from the EF API.
Assuming your property is defined in that way, then you gain a whole world of abilities. If you want all books belonging to the author you can just interact with author.Books directly (iterate, query, whatever). No queries are made until you do something that requires evaluation of the queryset. EF issues just-in-time queries depending on the information you're requesting from the database. If you do want to load all the related books at the same time you retrieve the author, you can just use Include with your query:
var author = db.Authors.Include(m => m.Books).SingleOrDefault(m => m.Id == id);
My first question would be to ask why you are creating DTO's in the first place? Is there a consumer on the other end that is using this data? Is it a screen? Are you building DTO's just to build DTO's?
Since you tagged the question as MVC i'm going to assume you are sending data to a view. You probably want a ViewModel. This ViewModel should contain all the data that is shown on the View that uses it. Then use entity framework to populate the view model. This may be done with a single query using projections or something complex.
So after all that blathering. I would say you want option 3.
Just like the others said, for clarity reasons, you should avoid creating "generic" DTO's for specific cases.
When you want to sometimes have authors and some of their books then model a DTO for that.
When you need only the authors then create another DTO that is more suited for that.
Or maybe you don't need DTOs, maybe a List containing their names is enough. Or maybe you could in fact use an anonymous type, like new { AuthorId = author.Id, AuthorName = author.Name }. It depends on the situation.
If you're using ASP.NET MVC the DTO you'll want is in fact a ViewModel that best represents your page.
Based on what you've described, you're view model could be something like this
public class BookViewModel{
public int Id {get;set;}
public string Name {get;set;}
}
public class AuthorViewModel{
public int Id {get;set;}
public string Name {get;set;}
public List<BookViewModel> Books {get;set;} = new List<BookViewModel>();
}
public class AuthorsViewModel
{
public List<AuthorViewModel> Authors {get;set;} = new List<AuthorViewModel>();
//add in this class other properties, like the filters used on the page...
public void Load(){
//here you can retrieve the data from your database.
//you could do like this:
//step 1: retrieve data from DB via EF
//step 2: fill in the Authors view models from the data at step 1
}
}
//and in your controller you're calling the Load method to fill you're viewmodel with data from db.
public class AuthorsController{
public ActionResult Index(){
AuthorsViewModel model = new AuthorsViewModel();
model.Load();
return View(model);
}
}

Creating Data Access Layer methods for Domain Models with extra data

I am currently building a blog posting web application using MVC 4 in C# mostly for the purpose of honing my knowledge of application architecture.
Currently it is in a tiered structure as:
View > View Model > Controller > Data Access Layer > Data Store
There may be a Service Layer added between the Controller and Data Access Layer later but that is not the reason for this particular question.
What should the parameters and return types of Data Access Layer methods be?
My current understanding is the View Models exist to provide the View with data that may be more or less than the Domain Model's structure exposes.
In my application, a Post consists of the PostId, Description, Content & UserId. There is also a Users table that has a UserId and UserFullName.
The Post Model mirrors the Posts table in that it stores the UserId but not the UserFullName. As such, when I need to retrieve the Post details along with the UserFullName to pass to the View, what should be returned by the DAL method? I have created a new Domain Model which contains all the data required by the View, but this goes against the fact that the Domain Models be de-coupled from its implementation. I'm of the thinking that just an Object can be returned when I query the database for the Post data, plus whatever else is needed by the View.
Is a wholly generic data access layer required here or is it overkill?
In EF exists the method Include which let you to preload records from related tables.
public ActionResult Index()
{
var model = context.Posts.Include("Users");
return View(model);
}
In .cshtml:
#model IEnumerable<Post>
#foreach(var post in Model)
{
<p>#post.Description</p>
#Html.Raw(post.Content)
<p>By #post.Users.UserFullName</p>
}
See http://msdn.microsoft.com/en-us/data/jj574232.aspx for more details.

How to use roles to segment ViewModels/Controllers/Views

I'm working on an ASP.NET project for a school. In one area I want to be able to serve up almost identical views for staff and students - the only real difference is the data that gets shown.
For a user with a student role they should see only their own data whereas a teacher should be able to see the combined data of their class (plus dive into see a single students data). Both users are able to flip between a couple of partial views that represent the data differently (line graph, table, etc.)
What is the best practice for structuring this using the MVC pattern?
Essentially it will be the same view for all of them, only the info I'm fetching will be different. I've read some other questions on here about two controllers and one view but they don't seem to have the same permission requirements I have.
Looks like there is a pretty good answer on SO already asp.net mvc - dynamic controller based on authenticated user. This basically allows you to create different controllers based on authentication. You can make this even easier by separating the visual representation of data into different partial views stored in the shared directory so that the different controllers' views can use the same partial views to serve up html.
If I understand your question corectly, you want to use one view, but send different data.
I am not sure if this is the best solution. In your situation I would create two different controllers, one for student and one for teacher, but if you want to use what you propose I would use a membership provider from Microsoft. Here is a sample.
here is a tutorial and some sample
http://theintegrity.co.uk/2010/11/asp-net-mvc-2-custom-membership-provider-tutorial-part-1/
public ActionResult Index()
{
if (User.Identity.IsAuthenticated)
{
MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
if (currentUser != null && currentUser.ProviderUserKey != null && currentUser.IsApproved)
{
var currentUserId = (Guid)currentUser.ProviderUserKey;
// get user data maybe somethink like that ....
Usser result = (from userdata in b.users
where userdata.Id == currentUserId
select userdata).FirstOrDefault();
return View(result);
}
}
return View();
}

Creating custom model using other models in ASP.NET MVC

As the title suggests I have two models Products And Orders which are actually two table in my database and I have used a LINQ to SQL class to create there models. Now I wan to create a model named "OrderDetails" which will have properties from both the model like product name and id from product and Order number from orders something like this. An then I want to create a view from this custom model and from which I want to add "CRUD" operation. What should be my approach. And in many scenarios I may have to use data from more than 4 models. Please help. I'm wondering helplessly and I have only two days experience in ASP.NET MVC.
I'd go this route:
namespace Models
{
public class OrderDetails
{
private Products _products;
private Order _order;
public OrderDetails(Order order, Products products)
{
_order = order;
_products = products;
}
// now expose whatever fields or logic you need.
// for instance:
public Customer OrderCustomer()
{
return order.Customer();
}
}
}
However, before you go around making all of these new models, are you sure you need them? Can you simply use two instances, either passed around separately or in a Tuple? You can get some useful abstraction here, but if you don't need it, keep it simple.
Linq to SQL does not support custom mapping to the extent that you're looking to do. What you'll want to look at is a full ORM. I highly recommend nHibernate, but Entity Framework, if you must, will do what you want.

MVC Partial Views, Models and more

I am pretty new to ASP.NET MVC and I am trying to get my head around some of the design concepts at the moment. One thing I am currently stuck on is how (best) to handle a situation such as that described below.
Suppose I have a page that needs to render a number of "sections". For example, on the left hand side there is a list that is data driven and then the selected item in the list displays a further list in another section on the page. For better understanding lets suggest the left hand list is a list of movie categories and the other list displays a list of movies that are contained within that category, along with the various movie details.
Now, I have some form of ORM such as Entity Framework, LINQ to SQL or whatever that maps the tblCategory and tblMovie database tables into Category and Movie entities respectively. These entities live in the MyMVCApp.Data.Entities namespace. I then use a repository pattern located in the MyMVCApp.Data namespace to encapsulate the queries (via LINQ) against these entities to return our model entities.
This is where my first question lies. Should the repository be returning view model entities or domain entities which are then extended to produce view model entities? In my naive mind I see the entities returned from the ORM as simply containers for the data with domain entities containing the business logic. So surely there should be an abstration here?
Anyway, back to my scenario. Now lets assume I wish to present the two sections described at the beginning of this. I am assuming that what should be happening here is my domain entity model would contain a list of categories and their associated movies. So something like a List each of which contains a List.
This model would have been populated somewhere. This is my second question. Say my assumption above is correct and it is simply data entities are returned from the ORM. Now I have a namespace/project called MyMVCApp.Core.Model (or the like) with some domain entities such as the Movie and Category entities mentioned in the previous paragraph. Do these entities have methods on them to retrieve the data from the ORM and populate themselves? Or does the repository retrieve these populated entity models? And another question on this part, if I have a Movie and Customer entity in my ORM is it acceptable to be having domain entities named the same?
Finally, I assume the controller now has this populated list of Category and Movie objects and passes it back to the view. I am guessing it is best to have each of the sections described at the beginning as partial views and passing the populated model to each? So, it may be the IndexController which retrieves the populated CategoryMovies entity, passing this to the Categories partial view and the Movies partial view. I would then need to somehow determine the selected Category (quesrystring?) and display the appropriate list of Movies in that category within the view.
OK, so if anyone has got to this point in my ramblings I will take a deep bow. I hope I have explained my mixed up thoughts and questions in sufficient detail for someone to provide some kind of enlightenment.
Thanks for listening! :-)
Since you didn't mention it, I will assume you are new to DDD concepts. DDD compliments the "M" in MVC by placing logic where it belongs. And, I think a good amount could be applied here.
In strict DDD form, I would use your Movie example as an Aggregate Root (a DDD concept). Within Movie, you would have business logic (methods) that obtain the categories and related entities directly related to Movie (i.e. Categories-this-movie-belongs-in). This assumes the "category" list you want to display is a list of categories this movie is in.
public class Movie
{
private IList<Category> _categories;
public IList<Category> FetchCategories()
{
// you can lazy-load here, use Linq-to-Sql, etc.
return _categories;
}
public void AddCategory(Category c)
{
_categories.Add(c);
}
}
Of course, you can treat Categories as a Value Object (VO, a DDD concept) here if you don't have an identity on them.
Now, what gets more interesting is if you do want to keep an identity on your Categories, treating them as Aggregate Roots with multiple entities and relations to other VOs and alike. In this case, you would want to utilize the DDD concept of Services to combine the two aggregates into your requested Model you want to pass to your Controller. This allows you to create business rules around loading the categories.
public class Movie
{...}
public class Category
{...}
public class MovieCategory : Movie
{
private IList<Category> _categories;
public IList<Category> Categories
{
get
{
return _categories;
}
internal set
{
_categories = value;
}
}
}
public class MovieCategoryService
{
public MovieCategory FetchMovieCategoryByMovieId(int id)
{
MovieCategory mc = _movieRepository.FetchMovie(id);
// do some logic here, some checks, etc
// to obtain your Categories list. Maybe querystring?
IList<Category> cats = ...;
mc.Categories = cats;
return mc;
}
}
The concept is that you now have logic in the domain layer, in this MovieCategoryService, to handle the complex creation of these relationships, or using Factories to create complex types as well.
This gives you a model you can pass around to different View and PartialViews.
The final step in your original post is how to get this into the View. I've been playing with the ViewModel approach to this issue. Creating ViewModels either dynamically, or as a class, and hanging all of the entities on this ViewModel. A recent StackOverflow question hits on this concept. ViewModel Best Practices
I've passed the Model directly into Views, and I am now trying this approach. It does clean things up, as your DOmain Model really should be disconnected from the "logic" on your page. I find myself thinking, "Dang it. I need to get this partialview populated based on this ID. Guess that means another method on the entity." Going the ViewModel approach removes the logic/thinking from the Domain Model, and puts it where it belong - in the Application/UI layer of where you are fine-tuning your view/partialview.
First of all, I think you should just get started with a simple project and try the various scenarios out you pictured in your long question :). There is nothing written in stone, you can use whatever architecture with datalayers and services or whatever, you like !
Or does the repository retrieve these populated entity models?
I would say yes. Your controller graps these from the service and gets them, populated and all and just moves them to the view in order to be displayed.
I am guessing it is best to have each of the sections described at the beginning as partial views and passing the populated model to each?
And again i think you're on the right track ;).
It is a nice idea to give a view model entity to the view instead of the whole domain entity itself thereby providing the view only the required stuffs to work on
First of all return a List of Categories from your Domain, then construct a Movie view which takes the category name as a parameter something like this
- <Host>/Movies/Comedy
- <Host>/Movies/Horror
which would in turn display the movies which belongs to that particular category

Resources