Skip to content

Commit 300e303

Browse files
committed
Added REST API and used them on the users component
1 parent cd4c168 commit 300e303

File tree

7 files changed

+245
-78
lines changed

7 files changed

+245
-78
lines changed

Client/app/app.module.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import { NgModule } from '@angular/core';
22
import { RouterModule } from '@angular/router';
33
import { CommonModule } from '@angular/common';
44
import { HttpModule } from '@angular/http';
5+
import { FormsModule } from '@angular/forms';
56

67
import { AppComponent } from './app.component';
78
import { NavMenuComponent } from './containers/navmenu/navmenu.component';
89
import { HomeComponent } from './containers/home/home.component';
9-
import { FetchDataComponent } from './containers/fetchdata/fetchdata.component';
10+
import { UsersComponent } from './containers/users/users.component';
1011
import { CounterComponent } from './containers/counter/counter.component';
1112
import { ChatComponent } from './containers/chat/chat.component';
1213

@@ -18,13 +19,14 @@ import { ConnectionResolver } from './shared/route.resolver';
1819
AppComponent,
1920
NavMenuComponent,
2021
CounterComponent,
21-
FetchDataComponent,
22+
UsersComponent,
2223
HomeComponent,
2324
ChatComponent
2425
],
2526
imports: [
2627
CommonModule,
2728
HttpModule,
29+
FormsModule,
2830
// App Routing
2931
RouterModule.forRoot([
3032
{
@@ -61,13 +63,13 @@ import { ConnectionResolver } from './shared/route.resolver';
6163
}
6264
},
6365
{
64-
path: 'fetch-data', component: FetchDataComponent,
66+
path: 'users', component: UsersComponent,
6567
data: {
66-
title: 'REST demo',
67-
meta: [{ name: 'description', content: `We're hitting REST in this Demo!` }],
68+
title: 'Users REST example',
69+
meta: [{ name: 'description', content: 'This is User REST API example page Description!' }],
6870
links: [
69-
{ rel: 'canonical', href: 'http://blogs.example.com/%3Cspan%20class="x x-first x-last">fetch-data/canonicaldemo' },
70-
{ rel: 'alternate', hreflang: 'es', href: 'http://es.example.com/%3Cspan%20class="x x-first x-last">fetchstuff' }
71+
{ rel: 'canonical', href: 'http://blogs.example.com/%3Cspan%20class="x x-first x-last">chat/something' },
72+
{ rel: 'alternate', hreflang: 'es', href: 'http://es.example.com/%3Cspan%20class="x x-first x-last">users' }
7173
]
7274
}
7375
},

Client/app/containers/fetchdata/fetchdata.component.html

Lines changed: 0 additions & 23 deletions
This file was deleted.

Client/app/containers/fetchdata/fetchdata.component.ts

Lines changed: 0 additions & 46 deletions
This file was deleted.

Client/app/containers/navmenu/navmenu.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
</a>
2424
</li>
2525
<li [routerLinkActive]="['link-active']">
26-
<a [routerLink]="['/fetch-data']">
27-
<span class='glyphicon glyphicon-th-list'></span> Fetch data
26+
<a [routerLink]="['/users']">
27+
<span class='glyphicon glyphicon-user'></span> Users
2828
</a>
2929
</li>
3030
<li [routerLinkActive]="['link-active']">
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<h1>This is a RestAPI Example (hitting WebAPI in our case)</h1>
2+
3+
<blockquote>
4+
Let's get some fake users from Rest:<br>
5+
You can find the Web API Routes in <code>{{ "/Server/RestAPI/ ... "}}</code>
6+
</blockquote>
7+
8+
<p *ngIf="!users"><em>Loading...</em></p>
9+
10+
<table class="table" *ngIf="users">
11+
<thead>
12+
<tr>
13+
<th>User ID</th>
14+
<th>Name</th>
15+
<th></th>
16+
<th></th>
17+
</tr>
18+
</thead>
19+
<tbody>
20+
<tr *ngFor="let user of users" [@flyInOut]>
21+
<td>{{ user.id }}</td>
22+
<td>
23+
<input class="form-control" [(ngModel)]="user.name" #name="ngModel" />
24+
</td>
25+
<td>
26+
<button *ngIf="name.dirty" class="btn btn-success" (click)="editUser(user)">Save</button>
27+
</td>
28+
<td>
29+
<button class="btn btn-danger" (click)="deleteUser(user)">Delete</button>
30+
</td>
31+
</tr>
32+
<tr>
33+
<td></td>
34+
<td>
35+
<input class="form-control" [(ngModel)]="newUserName" #newUser="ngModel" />
36+
</td>
37+
<td></td>
38+
<td>
39+
<button *ngIf="newUser.dirty" class="btn glyphicon-plus" (click)="addUser(newUserName)"></button>
40+
</td>
41+
</tr>
42+
</tbody>
43+
</table>
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import {
2+
Component, OnInit,
3+
// animation imports
4+
trigger, state, style, transition, animate
5+
} from '@angular/core';
6+
7+
import { Http, URLSearchParams } from '@angular/http';
8+
9+
@Component({
10+
selector: 'fetchdata',
11+
templateUrl: './users.component.html',
12+
animations: [
13+
// Animation example
14+
// Triggered in the ngFor with [@flyInOut]
15+
trigger('flyInOut', [
16+
state('in', style({ transform: 'translateY(0)' })),
17+
transition('void => *', [
18+
style({ transform: 'translateY(-100%)' }),
19+
animate(1000)
20+
]),
21+
transition('* => void', [
22+
animate(1000, style({ transform: 'translateY(100%)' }))
23+
])
24+
])
25+
]
26+
})
27+
export class UsersComponent implements OnInit {
28+
29+
public newUserName: string;
30+
public users: IUser[];
31+
32+
// Use "constructor"s only for dependency injection
33+
constructor(private http: Http) { }
34+
35+
// Here you want to handle anything with @Input()'s @Output()'s
36+
// Data retrieval / etc - this is when the Component is "ready" and wired up
37+
ngOnInit() {
38+
this.newUserName = "";
39+
this.http.get('http://localhost:5000/api/user/all').map(res => res.json()).subscribe(result => {
40+
console.log(result);
41+
this.users = result as IUser[];
42+
});
43+
}
44+
45+
deleteUser(user) {
46+
this.http.delete("http://localhost:5000/api/user/delete/" + user.id).subscribe(result => {
47+
if (result.ok) {
48+
let position = this.users.indexOf(user);
49+
this.users.splice(position, 1);
50+
}
51+
else {
52+
alert("There was an issue, Could not delete user");
53+
}
54+
});
55+
}
56+
57+
editUser(user) {
58+
let urlSearchParams = new URLSearchParams();
59+
urlSearchParams.append('id', user.id);
60+
urlSearchParams.append('name', user.name);
61+
this.http.put('http://localhost:5000/api/user/update', urlSearchParams).subscribe(result => {
62+
if (!result.ok) {
63+
alert("There was an issue, Could not edit user");
64+
}
65+
});
66+
}
67+
68+
addUser(newUserName) {
69+
let urlSearchParams = new URLSearchParams();
70+
urlSearchParams.append('name', newUserName);
71+
this.http.post('http://localhost:5000/api/user/insert', urlSearchParams).subscribe(result => {
72+
if (result.ok) {
73+
this.users.push(result.json());
74+
this.newUserName = "";
75+
}
76+
else {
77+
alert("There was an issue, Could not edit user");
78+
}
79+
});
80+
}
81+
}
82+
83+
interface IUser {
84+
id: number;
85+
name: string;
86+
}

Server/RestAPI/UserController.cs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using AspCoreServer.Data;
2+
using AspCoreServer.Models;
3+
using Microsoft.AspNetCore.Mvc;
4+
using Microsoft.EntityFrameworkCore;
5+
using System;
6+
using System.Linq;
7+
using System.Threading.Tasks;
8+
9+
namespace AspCoreServer.Controllers
10+
{
11+
[Route("api/user/[action]")]
12+
public class UserController : Controller
13+
{
14+
private readonly SpaDbContext _context;
15+
16+
public UserController(SpaDbContext context)
17+
{
18+
_context = context;
19+
}
20+
21+
[HttpGet]
22+
public async Task<IActionResult> All(int currentPageNo = 1, int pageSize = 20)
23+
{
24+
var users = await _context.User
25+
.OrderByDescending(u => u.EntryTime)
26+
.Skip((currentPageNo - 1) * pageSize)
27+
.Take(pageSize)
28+
.ToArrayAsync();
29+
30+
return Ok(users);
31+
}
32+
33+
[HttpGet]
34+
public async Task<IActionResult> Details(int? id)
35+
{
36+
var user = await _context.User
37+
.Where(u => u.ID == id)
38+
.AsNoTracking()
39+
.SingleOrDefaultAsync(m => m.ID == id);
40+
41+
if (user == null)
42+
{
43+
return NotFound("User not Found");
44+
}
45+
else
46+
{
47+
return Ok(user);
48+
}
49+
}
50+
51+
[HttpPost]
52+
public async Task<IActionResult> Insert([Bind("Name")] Users user)
53+
{
54+
if (user.Name != null)
55+
{
56+
_context.Add(user);
57+
await _context.SaveChangesAsync();
58+
return Ok(user);
59+
}
60+
else
61+
{
62+
return NotFound("Name not given");
63+
}
64+
}
65+
66+
[HttpPut]
67+
public async Task<IActionResult> Update([Bind("ID,Name")] Users userUpdateValue)
68+
{
69+
try
70+
{
71+
userUpdateValue.EntryTime = DateTime.Now;
72+
_context.Update(userUpdateValue);
73+
await _context.SaveChangesAsync();
74+
return Ok(userUpdateValue);
75+
}
76+
catch (DbUpdateException)
77+
{
78+
//Log the error (uncomment ex variable name and write a log.)
79+
ModelState.AddModelError("", "Unable to save changes. " +
80+
"Try again, and if the problem persists, " +
81+
"see your system administrator.");
82+
return NotFound("User not Found");
83+
}
84+
}
85+
86+
[HttpDelete]
87+
[Route("{id:int}")]
88+
public async Task<IActionResult> Delete(int? id)
89+
{
90+
var userToRemove = await _context.User
91+
.AsNoTracking()
92+
.SingleOrDefaultAsync(m => m.ID == id);
93+
if (userToRemove == null)
94+
{
95+
return NotFound("User not Found");
96+
}
97+
else
98+
{
99+
_context.User.Remove(userToRemove);
100+
await _context.SaveChangesAsync();
101+
return Ok("Deleted user - " + userToRemove.Name);
102+
}
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)