I am working on a project(asp.net mvc-5 with jQuery) in which whole validation is happening in front-end and we are executing APIs using $.ajax call, now as there are no validations on API level or not even in stored procedures of sql server, a user can easily access the the APIs with wrong values, so we decided to add a logic layer in our application.
So before that our structure looks like the below
jQuery -> Api layer -> Db layer
Now I want to add a layer between Api layer
and Db layer
which will be called as Logic layer
.
The new structure will look like below
jQuery -> Api layer -> Logic layer -> Db layer
Note:
So we have 4 class library 1 api and 1 front end. interfaces are inherited in the class files. The class library is like below
db.Interface (class library project)
db.Class (class library project)
Logic.Interface (class library project)
Logic.Class (class library project)
We have already added dependencies for db layer the code for which looks like below,
Set of code In global.asax.cs
//Helps to find all the classes of Dblayer
string dbName = ConfigurationManager.AppSettings["DB"];
string dbDAL = Path.Combine(Server.MapPath("./DAL"), "DocPro.DMS.BusinessLayer." + dbName + ".dll");
AssemblyName an = AssemblyName.GetAssemblyName(dbDAL);
Assembly assembly = Assembly.Load(an);
Type[] assemblyTypes = assembly.GetTypes();
DALFinder.Initialize(assemblyTypes);
class file in api project called DalFinder
public static class DALFinder
{
private static List<Type> TypeList { get; set; } = new List<Type>();
public static void Initialize(Type[] typelist)
{
TypeList.Clear();
TypeList = typelist.ToList<Type>();
}
public static object GetInstance(Type plugin)
{
foreach (Type type in TypeList)
{
if (type.IsInterface || type.IsAbstract)
{
continue;
}
else
{
if (type.GetInterface(plugin.FullName) != null)
{
return Activator.CreateInstance(type, new object[] { Program.GetConnectionString() });
}
}
}
return null;
}
}
and while executing a particular function I needed to do the below in my Api layer
BusinessLayer.IAdmin.IFolderRole a = (BusinessLayer.IAdmin.IFolderRole)DALFinder.GetInstance(typeof(BusinessLayer.IAdmin.IFolderRole));
response = a.SaveFolderRole(item);
now for my current scenario I want to call db layer from my logic layer but since it is a class library file I failed to understand what should I do, for now I did something like below
public class DocTemplateController : ApiController
{
private LogicLayer.IAdmin.IDocTemplate _LogicLayer;
private BusinessLayer.IAdmin.IDocTemplate _Businesslayer;
public DocTemplateController()
{
_LogicLayer = (LogicLayer.IAdmin.IDocTemplate)BusinessLayerFinder.GetInstance(typeof(LogicLayer.IAdmin.IDocTemplate));
_Businesslayer = (BusinessLayer.IAdmin.IDocTemplate)DALFinder.GetInstance(typeof(BusinessLayer.IAdmin.IDocTemplate));
}
[HttpPost]
[Route("api/Admin/DocTemplate/GetDocTemplates")]
[Authorize]
[Filters.AuthorizeLoginApi()]
public async Task<GetTemplatesList> GetDocTemplates(DocTemplate request)
{
var response = new GetTemplatesList() { LogicLayerValidation = false };
try
{
response = _LogicLayer.GetDocTemplates(request);
if (response.LogicLayerValidation != false)
response.GetTemplates = await _Businesslayer.GetDocTemplates(request.TemplateName, request.AccountId);
}
catch (Exception ex)
{
Utils.Logger.Instance.LogException(ex);
response.LogicLayerValidation = false;
response.LogicLayerMessage = ex.Message;
}
return response;
}
}
And as I understand (I might be wrong) that this is a bad way of coding, I want to follow the structure of
jQuery -> API layer -> Logic layer -> Db layer
How can I do this?
I think I need to edit this question and provide more details. All the answers are good and can be very helpful for many but unfortunately I have failed to get what I wanted.
This is how my controller looks like:
[RateLimitApi]
public class UserController : ApiController
{
private readonly LogicLayer.IAdmin.IUsers _LogicLayer;//Logic layer
private readonly LogicLayer.IGlobalValidation _CommonLogicLayer; //common logic layer
private readonly BusinessLayer.IAdmin.IUsers _Businesslayer;// business layer
private readonly BusinessLayer.IAccess.IUser _IAccessBusinesslayer;//business layer which is being used in another api
private BusinessEntities.Response.LogicLayerValidationResult _Llv; //entity for logiclayer
private SPResponse _Sp; //response entity for add/edit
private readonly ErrorLogger _Er; error log class
private readonly BusinessEntities.Response.Admin.GetUsersList _UserList; //user list
private readonly BusinessEntities.Response.Admin.GetUsersSingle _UserSingle; //single user
public UserController()
{
_LogicLayer = (LogicLayer.IAdmin.IUsers)BusinessLayerFinder.GetInstance(typeof(LogicLayer.IAdmin.IUsers));
_Businesslayer = (BusinessLayer.IAdmin.IUsers)DALFinder.GetInstance(typeof(BusinessLayer.IAdmin.IUsers));
_IAccessBusinesslayer = (BusinessLayer.IAccess.IUser)DALFinder.GetInstance(typeof(BusinessLayer.IAccess.IUser));
_CommonLogicLayer = (LogicLayer.IGlobalValidation)BusinessLayerFinder.GetInstance(typeof(LogicLayer.IGlobalValidation));
_Llv = new BusinessEntities.Response.LogicLayerValidationResult() { LogicLayerValidation = false };
_Sp = new SPResponse();
_Er = new ErrorLogger();
_UserList = new BusinessEntities.Response.Admin.GetUsersList();
_UserSingle = new BusinessEntities.Response.Admin.GetUsersSingle();
}
// GET: Admin/Users
[HttpPost]
[Authorize]
[ActionName("GetList")]
[Filters.AuthorizeLoginApi()]
public async Task<BusinessEntities.Response.Admin.GetUsersList> GetList(DocPro.DMS.BusinessEntities.Request.Admin.UsersRequest request)
{
try
{
// had to call logic layer and then call the business layer like below
_Llv = _LogicLayer.GetList(request);
if (_Llv.LogicLayerValidation)
{
_UserList.GetUsers = await _Businesslayer.GetList(request.LoginText, request.Name, request.Email, request.UserTypeId, request.IsActive, Convert.ToInt32(request.LoggedInUserId));
}
}
catch (Exception ex)
{
_Llv = _Er.LogExceptionWithLogicLayerValidations(ex, _Llv);
}
_UserList.LogicLayerValidation = _Llv;
return _UserList;
}
}
how can I do this?
is quite a general question (which is frown upon in this community).
I don't see any issue with the structure:
jQuery -> Api layer -> Logic layer -> Db layer
It is very common structure: frontend -> api-> business (logic) layer-> db
If it is a new project, I might recommend to do it with .net core and use the microsoft dependency injections or maybe use Autofac, since the topic is complex. If you really want to do it, then you can also browse their (ms or autofuc) code on github to familiarize yourself on the topic.