Reputation: 3203
I'm currently learning Angular 4 and I have a task to create an organization chart visualization. I found multiple options how to do it and I picked this one. I chose it because it utilizes SQL database which I'm also supposed to use. The only problem for me is since the project is written in AngularJS that I have to migrate it to Angular 4 and I'm failing to come up with the proper way to do it.
I'm using Visual Studio 2015, empty ASP.NET web application project with MVC folder layout and this is what I have done so far:
HomeController.cs
using Pas.Angular.OrgChart.Models;
namespace Pas.Angular.OrgChart.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
public JsonResult GetEmployees()
{
List<Employees> emp = new List<Employees>();
using (EmployeesDBEntities dc = new EmployeesDBEntities())
{
emp = dc.Employees.OrderBy(a => a.PositionID).ToList();
}
return new JsonResult
{
Data = emp,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
}
employees.service.ts
import { Injectable } from "@angular/core";
import { Headers, Http } from "@angular/http";
import "rxjs/add/operator/toPromise";
@Injectable()
export class EmployeesService {
private headers: Headers;
private baseUrl = "/Home/GetEmployees" // Question no. 1
constructor(private http: Http) {
// Question no. 2
}
getEmployees(): Promise<JSON[]> {
return this.http.get(this.baseUrl) // Question no. 2
.toPromise()
.then(response => response.json())
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.log("An error has occurred: ", error);
return Promise.reject(error.message || error);
}
}
RouteConfig.cs
namespace Pas.Angular.OrgChart
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
Additional info:
ERROR Error: Uncaught (in promise): Response with status: 404 Not Found for URL: http://localhost:3002/Home/GetEmployees
My questions are (referring to numbers in code):
Last notes:
Using the tutorial from the link on the top I was able to make it run so I guess that my DB and DB model are OK. If you think this question lacks some important info let me know in comments and I'll add it. As I mentioned before, I'm new to Angular and I might be overlooking some important stuff.
Upvotes: 3
Views: 862
Reputation: 3203
I found out I had problems with correct URL. Because of some customization I've done in Index.cshtml I managed to break it somehow and instead of http://localhost/OrgChart/Home/GetEmployees
I was using different links which were all incorrect. This is the workaround I came up with.
employees.service.ts
import { Injectable, Inject } from "@angular/core"; //In order to inject DOCUMENT
import { Headers, Http } from "@angular/http";
import { DOCUMENT } from "@angular/platform-browser";
import "rxjs/add/operator/toPromise";
@Injectable()
export class EmployeesService {
private empUrl = "Home/GetEmployees";
private baseUrl: string;
constructor(private http: Http, @Inject(DOCUMENT) private document: any) {
// document injection and the way how to get the base URL
this.baseUrl = this.document.location.href + this.empUrl;
console.log(this.baseUrl);
// This will create a correct URL
// http://localhost/OrgChart/Home/GetEmployees
}
getEmployees(): Promise<any> {
return this.http.get(this.baseUrl)
.toPromise()
.then(response => response.json())
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.log("An error has occurred: ", error);
return Promise.reject(error.message || error);
}
}
This is how Index.cshtml head looks like. Without the href="~/src/"
I'm not able to access script but also because of it the URL ends up being malfunctioned. Hence the workaround.
Index.cshtml
<head>
<title>PAS org chart</title>
<base href="~/src/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style> ... </style>
<script src="~/node_modules/core-js/client/shim.min.js"></script>
<script src="~/node_modules/zone.js/dist/zone.js"></script>
<script src="~/node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('main.js').catch(function (err) { console.error(err); });
</script>
</head>
I'm not hundred percent sure that I'm doing the right thing but so far it works form me. I'll be glad if you find some risks or mistakes in this workaround and point them out.
Upvotes: 0
Reputation: 536
You should take closer look at attribute routing and also how to create a proper REST-ful API. The Employee entity should have its own controller, instead of being nested in the Home-controller.
The problem that you're facing right now is due to the route GetEmployees not being available, as there is already a default GET method defined on your HomeController (The Index() method).
Add a new EmployeesController in the Controllers folder, and put the GetEmployees method in there. In that way, you would be able to get all employees in a REST-ful way using a call like http://localhost:3002/Employees to get all employees, which also resonates much better with the way that Angular 2 services are supposed to be built. (I'm guessing that you mean Angular 2 and not 4, right?)
Upvotes: 2