I am trying to implement a web API. Trying to learn best practices and I came across using DTO's. I wonder if you know any tutorials about web API DTO usage/samples.
Best Regards.
Keep your friends close and your enemies even closer
You can use a Data Access Layer that's using the DAO pattern the WebAPI references. All DTO(s) are kept in a classlib project called Entities you can called it whatever you want, abut all projects that need to know about the DTO(s) have project reference
to Entities.
Example ASP.NET MVC project, the presentation layer making calls to WebAPI that using DAO and DTO pattern in the DAL. It happens to be in VB.NET and it's using Unity IoC and dependency injection in the MVC and WebAPI projects. You can use HTTPClient() instead
of WebClinet().
<copied>
When looking at code to evaluate its coupling, remember the phrase “new is glue.” That is, anywhere you see the “new” keyword instantiating a class, realize you’re gluing your implementation to that specific implementation code. The Dependency Inversion Principle
(bit.ly/DI-Principle) states: “Abstractions should not depend on details; details should depend on abstractions.”
<end>
Public Interface IProjectModel
Function GetProjectsByUserId(userid As String) As ProjectViewModels
Function GetProjectById(id As Int32) As ProjectViewModels.Project
function Create() As ProjectViewModels.Project
sub Create(project As ProjectViewModels.Project, userid As string)
Function Edit(id As int32)As ProjectViewModels.Project
Sub Edit(project As ProjectViewModels.Project, userid as string)
sub Delete(id As int32)
Function PopulateSelectedList(project As ProjectViewModels.Project ) As ProjectViewModels.Project
End Interface
======================================================
Imports ProgMgmntVB.WebApi
Imports Entities
Namespace Models
Public Class ProjectModel
Implements IProjectModel
Private ReadOnly _webapi As IWebApi
public sub New (webapi As IWebApi)
_webapi = webapi
End sub
public Function GetProjectsByUserId(userid As String) As ProjectViewModels Implements IProjectModel.GetProjectsByUserId
dim vm = new ProjectViewModels With {.Projects = new List(of ProjectViewModels.Project)}
dim dtos = _webApi.GetProjsByUserIdApi(userid).ToList()
vm.Projects.AddRange(dtos.Select(Function(dto) New ProjectViewModels.Project() With{.ProjectId = dto.ProjectId,
.ClientName = dto.ClientName,
.ProjectName = dto.ProjectName,
.Technology = dto.Technology,
.ProjectType = dto.ProjectType,
.StartDate = dto.StartDate,
.EndDate = dto.EndDate,
.Cost = dto.Cost}).ToList())
Return vm
End Function
public Function GetProjectById(id As Int32) As ProjectViewModels.Project Implements IProjectModel.GetProjectById
dim responseDto = _webApi.GetProjByIdApi(id)
dim project = New ProjectViewModels.Project With {.ProjectId = responseDto.ProjectId,
.ClientName = responseDto.ClientName,
.ProjectName = responseDto.ProjectName,
.Technology = responseDto.Technology,
.ProjectType = responseDto.ProjectType,
.StartDate = responseDto.StartDate,
.EndDate = responseDto.EndDate,
.Cost = responseDto.Cost}
Return project
End Function
public function Create() As ProjectViewModels.Project Implements IProjectModel.Create
Dim project = new ProjectViewModels.Project
return PopulateSelectedList(project)
End function
public sub Create(project As ProjectViewModels.Project, userid As string) Implements IProjectModel.Create
dim dto = New DtoProject With{.ProjectId = project.ProjectId,
.ClientName = project.ClientName,
.ProjectName = project.ProjectName,
.ProjectType = project.ProjectType,
.Technology = project.Technology,
.UserId = userid,
.StartDate = project.StartDate,
.EndDate = project.EndDate,
.Cost = project.Cost}
_webApi.CreateProjectApi(dto)
End sub
public Function Edit(id As int32)As ProjectViewModels.Project Implements IProjectModel.Edit
dim responseDto = _webApi.GetProjByIdApi(id)
dim project = New ProjectViewModels.Project with {.ProjectId = responseDto.ProjectId,
.ClientName = responseDto.ClientName,
.ProjectName = responseDto.ProjectName,
.Technology = responseDto.Technology,
.ProjectType = responseDto.ProjectType,
.StartDate = responseDto.StartDate,
.EndDate = responseDto.EndDate,
.Cost = responseDto.Cost}
project = PopulateSelectedList(project)
Return project
End Function
public Sub Edit(project As ProjectViewModels.Project, userid as string) Implements IProjectModel.Edit
dim dto = New DtoProject With {.ProjectId = project.ProjectId,
.ClientName = project.ClientName,
.ProjectName = project.ProjectName,
.ProjectType = project.ProjectType,
.Technology = project.Technology,
.UserId = userid,
.StartDate = project.StartDate,
.EndDate = project.EndDate,
.Cost = project.Cost}
_webApi.UpdateProjectApi(dto)
end Sub
public sub Delete(id As int32) Implements IProjectModel.Delete
_webApi.DeleteProjectApi(new DtoId With {.Id = id})
End sub
public Function PopulateSelectedList(project As ProjectViewModels.Project ) As ProjectViewModels.Project Implements IProjectModel.PopulateSelectedList
dim dtocache as DtoCache = HttpContext.Current.Cache.Get("DtoCache")
if IsNothing(dtocache) Then
dtocache = _webapi.GetCacheApi()
HttpContext.Current.Cache.Insert("DtoCache", dtocache, nothing, _
DateTime.Now.AddMinutes(1), Cache.NoSlidingExpiration)
End If
project.ProjectTypes = new List(Of SelectListItem)
for each pt as DtoProjectType in dtocache.ProjectTypes
Dim sli = new SelectListItem With {.Value = pt.Value, .Text = pt.Text}
project.ProjectTypes.Add(sli)
Next
dim selected = (from a in project.ProjectTypes.Where(Function (a) a.Value = _
project.ProjectType) select a).SingleOrDefault()
if Not IsNothing(selected) then
selected.Selected = true
End If
return project
End Function
End Class
End NameSpace
Imports Entities
Namespace WebApi
Public Interface IWebApi
Function GetProjsByUserIdApi(userid As String) as List(of DtoProject)
Function GetProjByIdApi(id As int32) as DtoProject
sub CreateProjectApi(dto As DtoProject)
sub UpdateProjectApi(dto As DtoProject)
sub DeleteProjectApi(dto As DtoId)
End Interface
End Namespace
====================================================
Imports System.Net
Imports Entities
Imports Newtonsoft.Json
Namespace WebApi
Public Class WebApi
Implements IWebApi
#Region "Project"
public Function GetProjsByUserIdApi(userid As String) as List(of DtoProject) Implements IWebApi.GetProjsByUserIdApi
dim dtoprojects = new List(Of DtoProject)
dim url = "http://localhost/WebApiVB/api/project/GetProjectsByUserId?userid=" & userid
Using webclient As New WebClient
dim json = webclient.DownloadString(url)
Dim projects = JsonConvert.DeserializeObject(of List(Of DtoProject))(json)
dtoprojects = projects
End Using
Return dtoprojects
End Function
public Function GetProjByIdApi(id As int32) as DtoProject Implements IWebApi.GetProjByIdApi
dim dto as DtoProject
dim url = "http://localhost/WebApiVB/api/project/GetProjectById?id=" & id
Using webclient As New WebClient
dim json = webclient.DownloadString(url)
Dim project = JsonConvert.DeserializeObject(of DtoProject)(json)
dto = project
End Using
Return dto
End Function
public sub CreateProjectApi(dto As DtoProject) Implements IWebApi.CreateProjectApi
Dim reqString As byte()
Using webclient As New WebClient
dim url as string = "http://localhost/WebApiVB/api/project/CreateProject"
webClient.Headers("content-type") = "application/json"
reqString = Encoding.Default.GetBytes(JsonConvert.SerializeObject(dto, Formatting.Indented))
webClient.UploadData(url, "post", reqString)
End Using
End sub
public sub UpdateProjectApi(dto As DtoProject) Implements IWebApi.UpdateProjectApi
Dim reqString As byte()
Using webclient As New WebClient
dim url as string = "http://localhost/WebApiVB/api/project/UpdateProject"
webClient.Headers("content-type") = "application/json"
reqString = Encoding.Default.GetBytes(JsonConvert.SerializeObject(dto, Formatting.Indented))
webClient.UploadData(url, "post", reqString)
End Using
End sub
public sub DeleteProjectApi(dto As DtoId) Implements IWebApi.DeleteProjectApi
Dim reqString As byte()
Using webclient As New WebClient
dim url as string = "http://localhost/WebApiVB/api/project/DeleteProject"
webClient.Headers("content-type") = "application/json"
reqString = Encoding.Default.GetBytes(JsonConvert.SerializeObject(dto, Formatting.Indented))
webClient.UploadData(url, "post", reqString)
End Using
End sub
#End Region
End Class
End Namespace
Imports System.Web.Http
Imports DAL
Imports Entities
Namespace Controllers
<CustomExceptionFilter>
Public Class ProjectController
Inherits ApiController
Private ReadOnly _daoproject As IDaoProject
public sub New (daoproject As IDaoProject)
_daoproject = daoproject
End sub
<HttpGet>
<ActionName("GetProjectById")>
public Function GetProjectById(ByVal id As Int32) As DtoProject
return _daoproject.GetProjectById(id)
End Function
<HttpGet>
<ActionName("GetProjectsByUserId")>
public Function GetProjectsByUserId(ByVal userid As String) As List(Of DtoProject)
return _daoproject.GetProjectsByUserId(userid)
End Function
<HttpPost>
<ActionName("CreateProject")>
public sub CreateProject(ByVal dto As DtoProject)
Call _daoproject.CreateProject(dto)
End sub
<HttpPost>
<ActionName("UpdateProject")>
public sub UpdateProject(ByVal dto As DtoProject)
Call _daoproject.UpdateProject(dto)
End sub
<HttpPost>
<ActionName("DeleteProject")>
public sub DeleteProject(ByVal dto As DtoId)
Call _daoproject.DeleteProject(dto.Id)
End sub
End Class
End Namespace
Imports Entities
Public Interface IDaoProject
Function GetProjectById(ByVal id As Int32) As DtoProject
Function GetProjectsByUserId(ByVal userid As String) As List(Of DtoProject)
Sub CreateProject(ByVal dto As DtoProject)
Sub UpdateProject(ByVal dto As DtoProject)
Sub DeleteProject(ByVal id As Int32)
End Interface
=======================================================================
Imports System.Data.Entity
Imports Entities
Public Class DaoProject
Implements IDaoProject
Private ReadOnly context As ProjectManagementEntities
public sub New (dbcontext As ProjectManagementEntities)
context = dbcontext
End sub
Public Function GetProjectById(ByVal id As Int32) As DtoProject Implements IDaoProject.GetProjectById
Dim dto = New DtoProject()
Dim project = (context.Projects.Where(Function(a) a.ProjectId = id)).SingleOrDefault()
If IsNothing(project) Then
Return dto
End If
dto.ProjectId = project.ProjectId
dto.ClientName = project.ClientName
dto.ProjectName = project.ProjectName
dto.Technology = project.Technology
dto.ProjectType = project.ProjectType
dto.UserId = project.UserId
dto.StartDate = project.StartDate
dto.EndDate = project.EndDate
dto.Cost = project.Cost
Return dto
End Function
Public Function GetProjectsByUserId(ByVal userid As String) As List(Of DtoProject) Implements IDaoProject.GetProjectsByUserId
Dim dtos = New List(Of DtoProject)
dtos = (From a In context.Projects.Where(Function(a) a.UserId.Contains(userid))
Select New DtoProject With {.ProjectId = a.ProjectId,
.ClientName = a.ClientName,
.ProjectName = a.ProjectName,
.Technology = a.Technology,
.ProjectType = a.ProjectType,
.UserId = a.UserId,
.StartDate = a.StartDate,
.EndDate = a.EndDate,
.Cost = a.Cost}).ToList()
Return dtos
End Function
Public Sub CreateProject(ByVal dto As DtoProject) Implements IDaoProject.CreateProject
Dim project = New Project() With {.ClientName = dto.ClientName,
.ProjectName = dto.ProjectName,
.Technology = dto.Technology,
.ProjectType = dto.ProjectType,
.UserId = dto.UserId,
.StartDate = dto.StartDate,
.EndDate = dto.EndDate,
.Cost = dto.Cost}
context.Projects.Add(project)
context.SaveChanges()
End Sub
Public Sub UpdateProject(ByVal dto As DtoProject) Implements IDaoProject.UpdateProject
Dim project = New Project()
project = (context.Projects.Where(Function(a) a.ProjectId = dto.ProjectId)).SingleOrDefault()
If Not IsNothing(project) Then
project.ClientName = dto.ClientName
project.ProjectName = dto.ProjectName
project.Technology = dto.Technology
project.ProjectType = dto.ProjectType
project.UserId = dto.UserId
project.StartDate = dto.StartDate
project.EndDate = dto.EndDate
project.Cost = dto.Cost
End If
If IsNothing(project) Then
Exit Sub
End If
context.Entry(project).State = EntityState.Modified
context.SaveChanges()
End Sub
Public Sub DeleteProject(ByVal id As Int32) Implements IDaoProject.DeleteProject
Dim project As Project
project = (context.Projects.Where(Function(a) a.ProjectId = id)).Include("Tasks").SingleOrDefault()
If IsNothing(project) Then
Exit Sub
End If
For i As Integer = 0 To project.Tasks.Count - 1
Dim task = project.Tasks(i)
context.Entry(task).State = EntityState.Deleted
Next
context.Entry(project).State = EntityState.Deleted
context.SaveChanges()
End Sub
End Class
Public Class DtoProject
Public Property ProjectId As Int32
Public Property ClientName As String
Public Property ProjectName As String
Public Property Technology As String
Public Property ProjectType As String
Public Property UserId As String
Public Property StartDate As DateTime
Public Property EndDate As DateTime?
Public Property Cost As Decimal
End Class
If you find the post has answered your issue, then please mark post as 'answered'.
Member
527 Points
2729 Posts
DTO how to implement & use
Jan 29, 2019 12:29 PM|cenk1536|LINK
Hello guys,
I am trying to implement a web API. Trying to learn best practices and I came across using DTO's. I wonder if you know any tutorials about web API DTO usage/samples.
Best Regards.
Contributor
4963 Points
4218 Posts
Re: DTO how to implement & use
Jan 29, 2019 04:03 PM|DA924|LINK
https://docs.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5
https://www.codeproject.com/articles/1050468/data-transfer-object-design-pattern-in-csharp
You can use a Data Access Layer that's using the DAO pattern the WebAPI references. All DTO(s) are kept in a classlib project called Entities you can called it whatever you want, abut all projects that need to know about the DTO(s) have project reference to Entities.
Example ASP.NET MVC project, the presentation layer making calls to WebAPI that using DAO and DTO pattern in the DAL. It happens to be in VB.NET and it's using Unity IoC and dependency injection in the MVC and WebAPI projects. You can use HTTPClient() instead of WebClinet().
https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm
https://www.c-sharpcorner.com/blogs/understanding-interfaces-via-loose-coupling-and-tight-coupling
https://msdn.microsoft.com/en-us/magazine/mt703433.aspx
<copied>
When looking at code to evaluate its coupling, remember the phrase “new is glue.” That is, anywhere you see the “new” keyword instantiating a class, realize you’re gluing your implementation to that specific implementation code. The Dependency Inversion Principle (bit.ly/DI-Principle) states: “Abstractions should not depend on details; details should depend on abstractions.”
<end>