Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Run Single Page Applications (SPA) Template using AngularJS, Web API, Owin Token Based Authentication and Mediator Design Pattern

0.00/5 (No votes)
23 Mar 2016 2  
This post describes step by step how to run a Single Page Application template using ASP.NET Web API 2 and angularJS and how to use Web Application Project whose name is Dalyan.

Introduction

Dalyan is a single page application project template using AngularJS, ASP.NET & Web API technologies. It is the base of a web application project. It has CRUD operation example with AngularJS. Additionally, WebAPI controllers and CRUD operations are created by T4 templates. You can download it from github source codes. This post describes step by step how to run this project and generate WebAPI CRUD Operations with T4 templates on Dalyan Project. 

Content

What Are We Going to Build

Framework - Tools - Libraries

  • Single Page Application
  • AngularJS
  • ASP.NET MVC 5
  • ASP.NET Web API 2
  • Entity Framework 6
  • Mediator Design Pattern
  • Owin Token Based Authentication
  • Bootstrap 3
  • Simple Injector Dependency Injection (DI)
  • 3rd part libraries
  • T4 Templates
  • Microsoft Sql Server Express

Project Architecture

Configure Application

Open the Dalyan solution (Dalyan.sln) which is located in root directory and build the solution.

Publish Database Project

Database project has base tables and some data to test project.

Open database project and click publish button.

Set your database connection string and create your database.

Set Connection Strings

Change Db project and Web API config files. This connection string is integrated so your IIS user need to permission to login your SQL server. You can change your connection string with username & password from following link. 

http://www.connectionstrings.com/sql-server/

Dalyan.WebApi\Web.Config and Dalyan.Db\App.Config

<connectionStrings>
    <add name="DbEntities" 
    connectionString="metadata=res://*/DbModel.csdl|res://*/DbModel.ssdl|
    res://*/DbModel.msl;provider=System.Data.SqlClient;
    provider connection string=&quot;data source=<code>.\SQLEXPRESS</code>;
    initial catalog=Dalyan.Github;integrated security=True;
    MultipleActiveResultSets=True;App=EntityFramework&quot;" 
    providerName="System.Data.EntityClient" />
  </connectionStrings>

Ready to Run

It is ready to run. You can open the project in this link.

http://localhost/Dalyan.SPA/

Also web API link:

http://localhost/Dalyan.WebApi/

Default authentication:

admin@admin.com
Password: 1

 

Generate Web API CRUD Operations Automatic With T4 Template on Dalyan Project

Step by step how to generate Web API CRUD Operations automatic With T4 Templates on Dalyan Project. First of all you have to create a sample table on your database. After T4 code generation you can call these web api methods;

  • Add
  • Edit
  • Retrieve
  • Delete
  • GetAll

Lets do it

  1. Create a "product" table on SQL Server Database
  2. Add "product" table to Dalyan.Db Entity Framework Edmx model
  3. Add "product" table to defination xml file
  4. Generate DbModel with T4 template
  5. Generate ServiceQuery with T4 template
  6. Generate Service with T4 template
  7. Generate WebAPI controller with T4 template
  8. Check WebAPI actions

1. Create a "product" table on SQL Server Database

You have to add these columns to your new table. There is no delete operation on database. It is only update Isdeleted column to true. Also userid and date columns will bind Automatic.

[Id] [int] IDENTITY(1,1) NOT NULL, ----> For IDENTITY
[CreatedDate] [datetime] NULL, ----> For Logging Created Date automatic
[CreatedIpAddress] [nvarchar](50) NULL, ----> For Logging Created Ip Address automatic
[CreatedUserId] [int] NULL, ----> For Logging Created UserId automatic
[UpdatedDate] [datetime] NULL, ----> For Logging Updated Date automatic
[UpdatedIpAddress] [nvarchar](50) NULL, ----> For Logging Updated Ip Address automatic
[UpdatedUserId] [int] NULL, ----> For Logging Updated UserId automatic
[IsDeleted] [bit] NULL, ----> For Deleting operation automatic

Create a test table for testing t4 templates which name is "Product"

t4_1

You can add relationship to your columns. I added CompanyId column relationship with Company table. On WebAPI response you can reach Company table with this relationship.

t4_2

Table Create Script

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Product](
[Id] [int] IDENTITY(1,1) NOT NULL,
[CompanyId] [int] NULL,
[Name] [nvarchar](50) NULL,
[Description] [nvarchar](1000) NULL,
[Price] [float] NULL,
[CreatedDate] [datetime] NULL,
[CreatedIpAddress] [nvarchar](50) NULL,
[CreatedUserId] [int] NULL,
[UpdatedDate] [datetime] NULL,
[UpdatedIpAddress] [nvarchar](50) NULL,
[UpdatedUserId] [int] NULL,
[IsDeleted] [bit] NULL,
CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Product] WITH CHECK ADD CONSTRAINT [FK_Product_Company] FOREIGN KEY([CompanyId])
REFERENCES [dbo].[Company] ([Id])
GO
 
ALTER TABLE [dbo].[Product] CHECK CONSTRAINT [FK_Product_Company]
GO

// Create Table Script

2. Add "product" table to Dalyan.Db Entity Framework Edmx model

Open Dalyan.Db project -> DalyanModel.edmx file and update your model from database. 

t4_3

On DalyanModel.edmx file right click and Update Model From Database

t4_4 Add

Select Product table and click finish

t4_5

Now product table is added to edmx file.

3. Add "product" table to defination xml file

Code generation runs with edmx file but you have to add table name to "defination.xml" file. Open Dalyan.Entities -> Defination -> Tables.xml file

t4_6

Add Product node to xml

<?xml version="1.0" encoding="utf-8" ?>
<Tables>
<Table Name="Product"></Table>
</Tables>

4. Generate DbModel with T4 template

Models are generated by this T4 template. Open Dalyan.Entities -> Models -> DbModel.tt file and set you file location to absolutePath

public bool ControlTable(string tableName)
 {
 XmlDocument doc = new XmlDocument();
 string absolutePath = Path.GetFullPath(@"D:\Temp\Dalyan-master\Dalyan-master\Dalyan.Entities\Defination\Tables.xml");
 doc.Load(absolutePath);
 XmlNodeList xnList = doc.SelectNodes("/Tables/Table[@Name='" + tableName +"']");
 foreach (XmlNode xn in xnList)
 {
 return true;
 }
 return false;
 }

 

Run Custom Tool to generate models 

t4_7

t4_8

Your model is ready

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from the Dalyan T4 template.
// Do not change
//
// </auto-generated>
//------------------------------------------------------------------------------
namespace Dalyan.Entities.Models
{
using System;
using System.Collections.Generic;

public partial class Product
{

public int Id { get; set; }

public Nullable<int> CompanyId { get; set; }

public string Name { get; set; }

public string Description { get; set; }

public Nullable<double> Price { get; set; }

public Nullable<system.datetime> CreatedDate { get; set; }

public string CreatedIpAddress { get; set; }

public Nullable<int> CreatedUserId { get; set; }

public Nullable<system.datetime> UpdatedDate { get; set; }

public string UpdatedIpAddress { get; set; }

public Nullable<int> UpdatedUserId { get; set; }

public Nullable<bool> IsDeleted { get; set; }

public virtual Company Company { get; set; }

}

}

5. Generate ServiceQuery with T4 template

ServiceQuery is base layer to access database. It has CRUD operations and mapping operations in this layer. Open Dalyan.Domain -> Query -> ServiceQuery.tt file Right click and "Run Custom Tools"

t4_9  

t4_10

ProductAddQuery

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Dalyan.Domain.Query
{

using System;
using Dalyan.Domain;
using System.Linq;
using System.Text;
using Dalyan.Domain.Query;
using System.Data;
using System.Xml;
using Dalyan.Db;
using Entities.Models;
using Dalyan.Entities.Enumerations;
using AutoMapper;
using System.Threading.Tasks;
using System.Collections.Generic;

public class ProductAddQuery : IQuery<dalyan.entities.models.product>
{
public Dalyan.Entities.Models.Product Product{ get; set; }
}

public class ProductAddQueryHandler : IQueryHandler<productaddquery,dalyan.entities.models.product>
{
private readonly DbEntities _db;
public ProductAddQueryHandler()
{
_db = new DbEntities();
}

public Dalyan.Entities.Models.Product Handler(ProductAddQuery query)
{
try
{
var obj = new Dalyan.Db.Product();
obj.Id = query.Product.Id;
obj.CompanyId = query.Product.CompanyId;
obj.Name = query.Product.Name;
obj.Description = query.Product.Description;
obj.Price = query.Product.Price;
obj.CreatedDate = query.Product.CreatedDate;
obj.CreatedIpAddress = query.Product.CreatedIpAddress;
obj.CreatedUserId = query.Product.CreatedUserId;
obj.UpdatedDate = query.Product.UpdatedDate;
obj.UpdatedIpAddress = query.Product.UpdatedIpAddress;
obj.UpdatedUserId = query.Product.UpdatedUserId;
obj.IsDeleted = query.Product.IsDeleted;
_db.Product.Add(obj);
_db.SaveChanges();
query.Product.Id = obj.Id;
return query.Product;

}
catch (Exception ex)
{
throw new ExceptionLog(LogType.DATABASE_INSERT, LogLevel.ERROR, ex, "AddQueryHandler");
}
}
}

}

ProductDeleteQuery

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Dalyan.Domain.Query
{

using System;
using Dalyan.Domain;
using System.Linq;
using System.Text;
using Dalyan.Domain.Query;
using System.Data;
using System.Xml;
using Dalyan.Db;
using Entities.Models;
using Dalyan.Entities.Enumerations;
using AutoMapper;
using System.Threading.Tasks;
using System.Collections.Generic;

public class ProductDeleteQuery : IQuery<bool>
{
public int Id { get; set; }
}

public class ProductDeleteQueryHandler : IQueryHandler<dalyan.domain.query.productdeletequery, bool="">
{
private readonly DbEntities _db;
public ProductDeleteQueryHandler()
{
_db = new DbEntities();
}

public bool Handler(Dalyan.Domain.Query.ProductDeleteQuery query)
{
try
{
var obj = new Dalyan.Db.Product();
obj = _db.Product.FirstOrDefault(x => x.Id == query.Id);

obj.IsDeleted = true;
_db.SaveChanges();
return true;
}
catch (Exception ex)
{
throw new ExceptionLog(LogType.DATABASE_DELETE, LogLevel.ERROR, ex, "DeleteQueryHandler");
}
}
}
}

ProductEditQuery

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Dalyan.Domain.Query
{

using System;
using Dalyan.Domain;
using System.Linq;
using System.Text;
using Dalyan.Domain.Query;
using System.Data;
using System.Xml;
using Dalyan.Db;
using Entities.Models;
using Dalyan.Entities.Enumerations;
using AutoMapper;
using System.Threading.Tasks;
using System.Collections.Generic;

public class ProductEditQuery : IQuery<dalyan.entities.models.product>
{
public Dalyan.Entities.Models.Product Product{ get; set; }
}

public class ProductEditQueryHandler : IQueryHandler<producteditquery, dalyan.entities.models.product="">
{
private readonly DbEntities _db;
public ProductEditQueryHandler()
{
_db = new DbEntities();
}

public Dalyan.Entities.Models.Product Handler(ProductEditQuery query)
{
try
{
var obj = new Dalyan.Db.Product();
obj = _db.Product.FirstOrDefault(x => x.Id == query.Product.Id);
obj.Id = query.Product.Id;
obj.CompanyId = query.Product.CompanyId;
obj.Name = query.Product.Name;
obj.Description = query.Product.Description;
obj.Price = query.Product.Price;
obj.CreatedDate = query.Product.CreatedDate;
obj.CreatedIpAddress = query.Product.CreatedIpAddress;
obj.CreatedUserId = query.Product.CreatedUserId;
obj.UpdatedDate = query.Product.UpdatedDate;
obj.UpdatedIpAddress = query.Product.UpdatedIpAddress;
obj.UpdatedUserId = query.Product.UpdatedUserId;
obj.IsDeleted = query.Product.IsDeleted;
_db.SaveChanges();
return query.Product;

}
catch (Exception ex)
{
throw new ExceptionLog(LogType.DATABASE_UPDATE, LogLevel.ERROR, ex, "EditQueryHandler");
}
}
}
}

ProductGetAllQuery

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Dalyan.Domain.Query
{

using System;
using Dalyan.Domain;
using System.Linq;
using System.Text;
using Dalyan.Domain.Query;
using System.Data;
using System.Xml;
using Dalyan.Db;
using Entities.Models;
using Dalyan.Entities.Enumerations;
using AutoMapper;
using System.Threading.Tasks;
using System.Collections.Generic;

public class ProductGetAllQuery : IQuery<ilist<dalyan.entities.models.product>>
{

}

public class ProductGetAllQueryHandler : IQueryHandler<productgetallquery, dalyan.entities.models.product="">>
{
private readonly DbEntities _db;
public ProductGetAllQueryHandler()
{
_db = new DbEntities();
}

public IList<dalyan.entities.models.product> Handler(ProductGetAllQuery query)
{
try
{
var result = _db.Product.Include("Company").Where(x => x.IsDeleted == false).AsEnumerable().ToList();
Mapper.CreateMap<dalyan.db.company, dalyan.entities.models.company="">();
Mapper.CreateMap<dalyan.db.product, dalyan.entities.models.product="">().ForMember(c => c.Company, d => d.MapFrom(s => s.Company));
return Mapper.Map<ienumerable<dalyan.db.product>, IEnumerable<dalyan.entities.models.product>>(result).ToList();

}
catch (Exception ex)
{
throw new ExceptionLog(LogType.DATABASE_SELECT, LogLevel.ERROR, ex, "GetAllQueryHandler");
}
}
}
}

ProductRetrieveQuery

---------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Dalyan.Domain.Query
{

using System;
using Dalyan.Domain;
using System.Linq;
using System.Text;
using Dalyan.Domain.Query;
using System.Data;
using System.Xml;
using Dalyan.Db;
using Entities.Models;
using Dalyan.Entities.Enumerations;
using AutoMapper;
using System.Threading.Tasks;
using System.Collections.Generic;

public class ProductRetrieveQuery : IQuery<dalyan.entities.models.product>
{
public int Id { get; set; }
}

public class ProductRetrieveQueryHandler : IQueryHandler<productretrievequery, dalyan.entities.models.product="">
{
private readonly DbEntities _db;
public ProductRetrieveQueryHandler()
{
_db = new DbEntities();
}

public Dalyan.Entities.Models.Product Handler(ProductRetrieveQuery query)
{
try
{
var result = _db.Product.Include("Company").Where(x => x.IsDeleted == false && x.Id == query.Id).FirstOrDefault();
Mapper.CreateMap<dalyan.db.company, dalyan.entities.models.company="">();
Mapper.CreateMap<dalyan.db.product, dalyan.entities.models.product="">().ForMember(c => c.Company, d => d.MapFrom(s => s.Company));
return Mapper.Map<dalyan.db.product, dalyan.entities.models.product="">(result);

}
catch (Exception ex)
{
throw new ExceptionLog(LogType.DATABASE_SELECT, LogLevel.ERROR, ex, "RetrieveQueryHandler");
}
}
}

}

6. Generate Service with T4 template

Service Layer is your business side. It calls the Domain layer to access database.

Open Dalyan.Service -> Services -> ServiceQueryHandler.tt file and "run custom tools"

t4_11

Your service code is ready.

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Dalyan.Service.Services
{

using System;
using SimpleInjector;
using Dalyan.Domain;
using Entities.Contracts;
using System.Linq;
using System.Text;
using Dalyan.Entities.Interfaces;
using Dalyan.Domain.Query;
using System.Data;
using System.Xml;
using Dalyan.Entities.Models;
using Dalyan.Entities.Enumerations;
using System.Threading.Tasks;
using System.Collections.Generic;

public class ProductService
{
private readonly Container _container;
public ProductService(Container container)
{
_container = container;
}

public ServiceResult<product> Add(Product obj)
{
try
{
IMediator service = _container.GetInstance<imediator>();
IUserContext currentUser = _container.GetInstance<iusercontext>();
obj.CreatedDate = DateTime.Now;
obj.CreatedUserId = currentUser.CurrentUserIdentity.UserID;
obj.CreatedIpAddress = currentUser.CurrentUserIdentity.IpAddress;
obj.UpdatedDate = DateTime.Now;
obj.UpdatedUserId = currentUser.CurrentUserIdentity.UserID;
obj.UpdatedIpAddress = currentUser.CurrentUserIdentity.IpAddress;
obj.IsDeleted = false;
var query = new ProductAddQuery();
query.Product = obj;
return new ServiceResult<product>(service.Proccess(query), message: ClientErrorMessage.Success(), state: ServiceResultStates.SUCCESS);
}
catch(ExceptionLog ex)
{
LoggerService.Logger.Log(_container, ex);
return new ServiceResult<product>(result: null, message: ClientErrorMessage.Error(), state: ServiceResultStates.ERROR);
}
}
public ServiceResult<product> Edit(Product obj)
{
try
{
IMediator service = _container.GetInstance<imediator>();
IUserContext currentUser = _container.GetInstance<iusercontext>();
var query = new ProductEditQuery();
obj.UpdatedDate = DateTime.Now;
obj.UpdatedUserId = currentUser.CurrentUserIdentity.UserID;
obj.UpdatedIpAddress = currentUser.CurrentUserIdentity.IpAddress;
query.Product = obj;
return new ServiceResult<product>(service.Proccess(query), message: ClientErrorMessage.Success(), state: ServiceResultStates.SUCCESS);
}
catch(ExceptionLog ex)
{
LoggerService.Logger.Log(_container, ex);
return new ServiceResult<product>(result: null, message: ClientErrorMessage.Error(), state: ServiceResultStates.ERROR);
}
}
public ServiceResult<product> Retrieve(int Id)
{
try
{
IMediator service = _container.GetInstance<imediator>();
var query = new ProductRetrieveQuery{ Id = Id };
return new ServiceResult<product>(service.Proccess(query), message: ClientErrorMessage.Success(), state: ServiceResultStates.SUCCESS);
}
catch(ExceptionLog ex)
{
LoggerService.Logger.Log(_container, ex);
return new ServiceResult<product>(result: null, message: ClientErrorMessage.Error(), state: ServiceResultStates.ERROR);
}
}
public ServiceResult<ilist<product>> GetAll()
{
try
{
IMediator service = _container.GetInstance<imediator>();
var query = new ProductGetAllQuery();
return new ServiceResult<ilist<product>>(service.Proccess(query), message: ClientErrorMessage.Success(), state: ServiceResultStates.SUCCESS);
}
catch(ExceptionLog ex)
{
LoggerService.Logger.Log(_container, ex);
return new ServiceResult<ilist<product>>(result: null, message: ClientErrorMessage.Error(), state: ServiceResultStates.ERROR);
}
}
public ServiceResult<string> Delete(int Id)
{
try
{
IMediator service = _container.GetInstance<imediator>();
var query = new ProductDeleteQuery{ Id = Id };
return new ServiceResult<string>(service.Proccess(query).ToString(), message: ClientErrorMessage.Success(), state: ServiceResultStates.SUCCESS);
}
catch(ExceptionLog ex)
{
LoggerService.Logger.Log(_container, ex);
return new ServiceResult<string>(result: null, message: ClientErrorMessage.Error(), state: ServiceResultStates.ERROR);
}
}
}

}

7. Generate WebAPI controller with T4 template

The last one is WebAPI controller layer. Your SPA access this layer to CRUD operations. For authentication add [UserAuthorize] Attributes to your action. [UserAuthorize] authentication is default.

Open Dalyan.WebApi project -> Controllers -> ControllerService.tt file

t4_12

Your Controller is ready

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Dalyan.WebApi.Controllers
{

using System;
using SimpleInjector;
using Dalyan.Entities;
using System.Linq;
using System.Net;
using System.Web.Http;
using System.Net.Http;
using Dalyan.Entities.Models;
using Dalyan.Service;
using Entities.Contracts;
using Dalyan.WebApi.Attributes;
using Dalyan.Service.Services;
using System.Collections.Generic;

public class ProductController : ApiController
{
private readonly Container _container;
public ProductController(Container container)
: base()
{
_container = container;
}

[UserAuthorize]
[HttpPost]
public ServiceResult<product> Add(Product obj)
{
ProductService service = new ProductService(_container);
return service.Add(obj);
}
[UserAuthorize]
[HttpPost]
public ServiceResult<product> Edit(Product obj)
{
ProductService service = new ProductService(_container);
return service.Edit(obj);
}
[UserAuthorize]
[HttpPost]
public ServiceResult<product> Retrieve(int Id)
{
ProductService service = new ProductService(_container);
return service.Retrieve(Id);
}
[UserAuthorize]
[HttpPost]
public ServiceResult<ilist<product>> GetAll()
{
ProductService service = new ProductService(_container);
return service.GetAll();
}
[UserAuthorize]
[HttpPost]
public ServiceResult<string> Delete(int Id)
{
ProductService service = new ProductService(_container);
return service.Delete(Id);
}
}

}

8. Check WebAPI actions

For testing add some records to database

GO
SET IDENTITY_INSERT [dbo].[Company] ON

GO
INSERT [dbo].[Company] ([Id], [Name], [IsDeleted]) VALUES (1, N'Apple', 0)
GO
INSERT [dbo].[Company] ([Id], [Name], [IsDeleted]) VALUES (2, N'Samsung', 0)
GO
SET IDENTITY_INSERT [dbo].[Company] OFF
GO
SET IDENTITY_INSERT [dbo].[Product] ON
GO
INSERT [dbo].[Product] ([Id], [CompanyId], [Name], [Description], [Price], [CreatedDate], [CreatedIpAddress], [CreatedUserId], [UpdatedDate], [UpdatedIpAddress], [UpdatedUserId], [IsDeleted]) VALUES (1, 1, N'IPhone 6s', N'The only thing that&rsquo;s changed is everything.', 350, CAST(N'2016-01-22 00:00:00.000' AS DateTime), N'192.1681.1', 1, CAST(N'2016-01-22 00:00:00.000' AS DateTime), N'192.1681.1', 1, 0)
GO
INSERT [dbo].[Product] ([Id], [CompanyId], [Name], [Description], [Price], [CreatedDate], [CreatedIpAddress], [CreatedUserId], [UpdatedDate], [UpdatedIpAddress], [UpdatedUserId], [IsDeleted]) VALUES (2, 2, N'Samsung Galaxy S6 edge', N'Big screen. Big entertainment.', 300, CAST(N'2016-01-22 00:00:00.000' AS DateTime), N'192.1681.1', 1, CAST(N'2016-01-22 00:00:00.000' AS DateTime), N'192.1681.1', 1, 0)
GO
SET IDENTITY_INSERT [dbo].[Product] OFF
GO

 

You can test you api from SPA code or postman chrome extension https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop

The result of out call

http://localhost/Dalyan.WebApi/Product/GetAll

t4_13

 

{
"Result": [
{
"Id": 1,
"CompanyId": 1,
"Name": "IPhone 6s",
"Description": "The only thing that&rsquo;s changed is everything.",
"Price": 350,
"CreatedDate": "2016-01-22T00:00:00",
"CreatedIpAddress": "192.1681.1",
"CreatedUserId": 1,
"UpdatedDate": "2016-01-22T00:00:00",
"UpdatedIpAddress": "192.1681.1",
"UpdatedUserId": 1,
"IsDeleted": false,
"Company": {
"Id": 1,
"Name": "Apple",
"IsDeleted": false
}
},
{
"Id": 2,
"CompanyId": 2,
"Name": "Samsung Galaxy S6 edge",
"Description": "Big screen. Big entertainment.",
"Price": 300,
"CreatedDate": "2016-01-22T00:00:00",
"CreatedIpAddress": "192.1681.1",
"CreatedUserId": 1,
"UpdatedDate": "2016-01-22T00:00:00",
"UpdatedIpAddress": "192.1681.1",
"UpdatedUserId": 1,
"IsDeleted": false,
"Company": {
"Id": 2,
"Name": "Samsung",
"IsDeleted": false
}
}
],
"ResultList": null,
"State": 0,
"Message": "Your transaction has been completed successfully.",
"PortalTask": null
}

Generate Custom Database Operations

You can add CRUD operations with T4 template automaticly. Also you can add custom database operations to your project.

I will axplain the step by step how to add a new database operations.

The example is password change operation.

  1. Create ChangePassword Query and Query Handler
  2. Create ChangePassword Service
  3. Create ChangePassword WebAPI method

Create ChangePassword Query and Query Handler

Open Dalyan.Domain -> Query -> CustomQuery All db operations are in Dalyan.Domain project. Create a query class.

namespace Dalyan.Domain.Query
{
    using System;
    using Dalyan.Domain;
    using System.Linq;
    using System.Text;
    using Dalyan.Domain.Query;
    using System.Data;
    using System.Xml;
    using Dalyan.Db;
    using Entities.Models;
    using Dalyan.Entities.Enumerations;
    using AutoMapper;
    using System.Threading.Tasks;
    using System.Collections.Generic;

    public class ChangePasswordQuery : IQuery<bool>
    {
        public int Id { get; set; }
        public string Password { get; set; }
    }

    public class ChangePasswordQueryHandler : IQueryHandler<changepasswordquery, bool="">
    {
        private readonly DbEntities _db;
        public ChangePasswordQueryHandler()
        {
            _db = new DbEntities();
        }


        public bool Handler(ChangePasswordQuery query)
        {
            try
            {
                var obj = new Dalyan.Db.User();
                obj = _db.User.FirstOrDefault(x => x.Id == query.Id);
                obj.Password = query.Password;
                obj.UpdatedDate = DateTime.Now;
                _db.SaveChanges();
                return true;

            }
            catch (Exception ex)
            {
                throw new ExceptionLog(LogType.DATABASE_UPDATE, LogLevel.ERROR, ex, "ChangePasswordQuery");
            }
        }
    }

}

ChangePasswordQuery class have your parameters and used in handler method. The parameter values pass with query class to handler.

Create ChangePassword Service

WebAPI use service layer to access database so you have to add a service class to Dalyan.Service solution.

namespace Dalyan.Service.Services
{
    using System;
    using SimpleInjector;
    using Dalyan.Domain;
    using System.Linq;
    using System.Text;
    using Dalyan.Domain.Query;
    using System.Data;
    using System.Xml;
    using Dalyan.Entities.Models;
    using Dalyan.Entities.Enumerations;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    using Entities.Interfaces;
    using Entities.Contracts;

    public class ChangePasswordService
    {
        private readonly Container _container;
        public ChangePasswordService(Container container)
        {
            _container = container;
        }


        public ServiceResult<string> ChangePassword(int Id, string Password)
        {
            try
            {
                IMediator service = _container.GetInstance<imediator>();
                var query = new ChangePasswordQuery { Id = Id, Password=Password };
                return new ServiceResult<string>(service.Proccess(query).ToString(), message: ClientErrorMessage.Success(), state: ServiceResultStates.SUCCESS);
            }
            catch (ExceptionLog ex)
            {
                LoggerService.Logger.Log(_container, ex);
                return new ServiceResult<string>(result: "false", message: ClientErrorMessage.Error(), state: ServiceResultStates.ERROR);
            }
        }
    }
}

We use mediator pattern and our handlers execute automaticly with mediator class with IoC.

Create ChangePassword WebAPI method

The last step is create WebAPI method. SPA project uses WebAPI methods to access database. You can add the method any controller.

[ClientAuthorize]
[HttpPost]
public ServiceResult<string> ChangePassword(string password)
{
    ChangePasswordService service = new ChangePasswordService(_container);
    IUserContext currentUser = _container.GetInstance<iusercontext>();
    return service.ChangePassword(currentUser.CurrentUserIdentity.UserID, password);
}
-- Thank you
-- Ahmet AYDIN

Points of Interest

You can develop your project on Dalyan Web Application Template.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here