Using Specification Methods in Controllers
In this lesson, we're going to implement our Specification methods inside Controllers
Using Specification methods inside our Controllers#
We have created our Specification Interface. We have created the methods. Now we have to simply inject it to our Controllers. If we go to our CoursesController, we are simply returning the list and a single Entity without any navigation properties. By just looking at ListAllAsync name, we don't know what kind of a list we're getting or which navigation properties it will have. Creating Specifications gives us an opportunity to create some meaningful specification which we can pass to our generic methods. For example, I want to retrieve my Categories with Courses, so what I can do is, inside our Entity project, inside Specifications, I can create a new specification with the name, CoursesWithCategoriesSpecification. You can make it shorter as well, but the whole point is to make things easier to understand.
We will no longer pass the dynamic type T here because we know we want our Courses, so let's give it type Course. We see an error because inside our BaseSpecification class, we don't have an empty constructor. We have one with the criteria, but not an empty one. Let me create an empty one which will remove the error. I will create an empty constructor here as well. Since we're deriving from BaseSpecification, we have access to the Include method which we created. And if you remember, our Include method wants an expression which returns an object. Since we have used product type Course here, if we use an expression, we will have access to all our navigation properties. If I write c which is our entity c, you see I have access to all the properties. Since I want to include Category, I can write c.Category.
Now we can simply use this specification inside our controller. Let's go back to the CoursesController, and inside GetCourseMethod, we need a new variable which will store our specification; let's call it spec and it's going to be equal to new CoursesWithCategoriesSpecification(). Let's import it. To use it, we will have to create a new instance of it, which we're doing right now. We can pass spec to our ListAllAsync method, but we will see an error because this method doesn't accept any specs. For this, we have created ListWithSpec, so let's use that instead.
We can use the same Specification for our GetCourse method. In GetCourse method, we will have to use an expression which will check the id. Let's go to our specification, and this time, generate a constructor which takes a criteria. For this one, we can take this criteria from here and pass the parameter which we want to provide; so, we will pass Guid id, and inside base, we will provide the expression which checks if x.Id is equal to the id that we're providing. If we go to our BaseSpecification, we have two constructors. One is the empty one which we just created. We can use it when we just want to use our IncludeMethod; second one takes an expression, the expression which we provided right now. We can also pass Include statement in here. we would also like to include the Requirements and Learnings, so let's copy it and replace Category with Requirements and Learnings.
Entity/Specifications/BaseSpecification.cs
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace Entity.Specifications
{
public class BaseSpecification<T> : ISpecification<T>
{
public BaseSpecification()
{
}
public BaseSpecification(Expression<Func<T, bool>> criteria)
{
Criteria = criteria;
}
public Expression<Func<T, bool>> Criteria {get;}
public List<Expression<Func<T, object>>> Include {get;} = new List<Expression<Func<T, object>>>();
protected void IncludeMethod(Expression<Func<T, object>> expression)
{
Include.Add(expression);
}
}
}
Entity/Specifications/CoursesWithCategoriesSpecification.cs
This page is a preview of The newline Guide to Fullstack ASP.NET Core and React