Angular 8 How to connect Angular tutorial Tour of The Heroes to Entity Framework+SQL

My bad, didn’t check Your repositories :stuck_out_tongue:. Give me a couple of hours to check the code and I’ll reply :slight_smile:.

It took a while, but I get it now (I had to setup a Virtual Machine to test Your project :rofl:).

Your API is not working right because You have not defined any HTTP verbs yet. For example:

// File: HomeController.cs

using System.Web.Http;

namespace WebAPI.Controllers
{
    public class HomeController : ApiController
    {
        [HttpGet]
        public string Index()
        {
            return "Welcome to My API!";
        }

        [HttpPost]
        public string TestPost([FromBody] string aValue)
        {
            return aValue;
        }

        [HttpPost]
        public object TestPostComplex(object json)
        {
            return json;
        }
    }
}
// File: WebApiConfig.cs

using System.Web.Http;
using System.Web.Http.Cors;

namespace WebAPI
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            //Enable Cors                                                      Allow all headers and methods
            config.EnableCors(new EnableCorsAttribute("http://localhost/", headers: "*", methods: "*"));
            config.EnableCors(new EnableCorsAttribute("http://localhost:4200", headers: "*", methods: "*"));

            // Web API routes
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = RouteParameter.Optional }
            );
        }
    }
}

Now, when You press F5 using on Visual Studio CE, You start debugging the solution using the URL defined in the project settings, under the tab Web. To reach said API, You would need to use something like this on Angular:

http.get('http://localhost:port/api/').subscribe(response => console.log(response));
// Expected output: Welcome to My API!

But there are two extra endpoints defined on the HomeController, how do You reach them? Like this:

// The endpoints are mapped to: /api/controller-name/method-name
// where a method name can be "repeated" but must have a different HTTP Verb and signature.

http.post('http://localhost:port/api/home/testpost', 'A simple value').subscribe(r => console.log(r));
// Expected output: A simple value

http.post('http://localhost:port/api/home/testpostcomplex', {
  name: "John",
  surname: "Doe",
  age: 38
}).subscribe(r => console.log(r));
// Expected output: { name: "John", surname: "Doe", age: 38 }

By the way, since You’re using .NET, You should be moving to .NET Core instead of using .NET alone, since Core can run on Linux too :slight_smile:!

Hope it helps :slight_smile:

1 Like

Adding to thorough, great and detailed responses from @skaparate, you technically should be able to set up your client-side (Angular) , no matter the version, to hit your backend (.Net WebApi ).
Angular versions after 1.x have not seen drastic changes so in most of the cases you can use the new version of Angular by just a couple of small changes. Especially if it’s between versions 7 and 8.

I suggest this link, to check how you can easily update your whole app from version 7 to 8 after you made the current app work smooth. Based on the discussion I think creating the API methods should make the app work fine.

Good luck! :call_me_hand:t4:

1 Like

Wow :sunglasses: Great work!!

Ah! Sorry for my ignorance, so I cannot just delete HomeController and ValuesController?
I thought only CourseController was needed.

1 Like

Ah I see! HomeController used for View “Home Page”

Nobody is born knowing, so no apology needed :slight_smile: (I even had to read the documentation to provide the sample–long time without using .NET).

You’re missing something and I’ll try to explain.

Suppose You request this URL: GET http://localhost/api/courses/list; and, let’s assume we’re using the same WebApiConfig class from My latest reply. Well, this request is mapped like this:

# This is what the routeTemplate defines.

# The prefix, api/
api -> This part is just mapped as a prefix.

# The {controller} on the routeTemplate = courses
courses -> The configuration would search for a controller called CoursesController (it doesn't need to end with Controller as long a it extends the class ApiController.

# The {action} on the routeTemplate = list
list -> The configuration expects a method called List on the CoursesController.

# The {id}, which is optional, would be at the end of Your URL: http://localhost/api/courses/list/1 <- this is the {id} = 1

Keep in mind that the WebApiConfig routes are just string comparisons (actually, they are more complex, but don’t worry about it right now), hence the framework just compares the requested URL and tries to match with the defined routes, which in turn are mapped to controllers and methods on the controllers.

Not exactly :stuck_out_tongue:.

Here, the HomeController just responds with a message (Index) to let You know is working. A production API may send You to another page that displays how to request data (the documentation of Your API). In other words, HomeController is just a sample. You can delete it and just leave the CoursesController, as long as You configure it on the WebApiConfig class.

Is it clear/clearer now? If not, tell me what You don’t understand and I’ll try to explain better :slight_smile:.

Thanks for the support! Ok, now I have some questions.

It was a requiremt for my assignment that I use .NET, but will use .NET.Core in the future :grinning:

The URL for debugging, I find it in SolutionExplorer/right click project => properties/Web
Project URL http://localhost:60565/

By the way, the course.list.html displays randomly,

So even if HomeController by default serve the ASP,NET homepage it wants HTTP verbs :roll_eyes:?

If I implement your solution then I have to create 3 subscriber functions in a Angular component.
They subscribe each to an observable in the service class.
1 GET and 2 POST functions.

Can I then use ngOninit() to execute the functions like this:

ngOnInit() {
    this.GetConsole();
    this.PostSimpleValue();
    this.PostTestComplex();
  }

Yes, I didn’t include it in case You modify it :stuck_out_tongue:.

Yes, they need the verbs. It’s the way the framework knows how to handle the controllers and methods. For example, GET should not include a body of data (it’s a convention, not a rule), whereas POST and PUT need the body data to create/update the model.

Yes! In fact, that’s the recommended way of doing it. Look at my Issue Tracker project on github (I did it for the curriculum). It uses Node/Express for the back end (project requirement), but it also defines the routes and controllers similar to how .NET Framework does.

Thanks! I am using Angular 8, but the tutorial i am using as template is using version 7.

Again thanks for the support!

Ok, lets see! Since I dont have a onClick() event to trigger the functions I use ngOnInit().

I am not sure if this is correct implementation, I used this.service.refreshList() as template.

course-list.component:

ngOnInit() {
    this.service.refreshList();

    this.service.StartConsoleOutput();
    this.service.testPostComplex();
    this.service.testSimple();
  }

course.service.cs

 /**Testing HomeController */
   
   StartConsoleOutput(){
    this.http.get('http://localhost:60565/api/home').subscribe(response => console.log(response));
   }

    testSimple(){
      this.http.post('http://localhost:60565/api/home/testpost', 'A simple value').subscribe(r => console.log(r));
    }



   testPostComplex(){
     this.http.post('http://localhost:60565/api/home/testpostcomplex', {
      name: "John",
      surname: "Doe",
      age: 38
    }).subscribe(r => console.log(r));
     
   }

Yes, that’s how You would do it, although You should be calling the Courses endpoint (after You create it on the WebApi).

Do not mix the component that lists the courses with the one that updates/creates them. Try to split them in multiple files, otherwise it will become harder to maintain.

Great!
Sorry, I don’t understand: “calling the Courses endpoint (after You create it on the WebApi)”

I am litle bewildred because Angular is not able to access WepAPI.

Angular gives this output in console from browser:

ERROR 
Object { headers: {…}, status: 0, statusText: "Unknown Error", url: "http://localhost:60565/api/home", ok: false, name: "HttpErrorResponse", message: "Http failure response for http://localhost:60565/api/home: 0 Unknown Error", error: error }
[core.js:6014:19](webpack:///node_modules/@angular/core/fesm2015/core.js

If I start WebApi this message is displayed:

 404 Server Error in '/' Application

If I type in url http://localhost:60565/api/home this is displayed in WebApi browser.

 <string>Welcome to My API!</string>

/testpost and /testpostcomplex gives error:
“The requested resource does not support http method ‘GET’.”

So I improvised a litle bit
In HomeController.cs I tried to force the routes with Attribute Routing, and in WebApiConfig.cs I tried multiple routes, one for HomeController and CourseController :thinking:

[HttpGet]
        [Route("api/home")]
        public string Index()
        {
            return "Welcome to My API!";
        }

Everything is pushed to GitHub
Regards

Hey!

Sorry for the delay, I had problems accessing the forum yesterday.

It seems to be a problem with Cors, although it seems to be correctly configured :thinking:. I cannot reproduce the error right now (I will not have access to My computer for, at least, 3 days). I tested this using .NET Core tough, and after configuring CORS, it works fine :stuck_out_tongue:.

That’s fine, it means the API is working, which means the CORS are not configured right.

The other two endpoints will not work because the browser defaults to GET requests. A form, on the other hand, may POST data.

Check out this tutorial, which may help You solve the problem :slight_smile:.

Thanks! No problem! Don’t think about that :smile:

I will study CORS, and try to not break the code.
I checked for firefox console.info may be useful .

1 Like

Finally! Everything is working :stuck_out_tongue_closed_eyes: All CRUD functions are fine!
Thank you!! …For you :cake:

Routing is hard.
I added to all the POST,GET,Delete,PUT functions in CourseController

[ActionName("Courses")]

This is how things are:

WebApiConfig.cs file

using System.Web.Http;
using System.Net.Http;
using System.Web.Http.Cors;

namespace WebAPI
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            //Enable Cors   
            config.EnableCors();
            config.EnableCors(new EnableCorsAttribute("http://localhost", headers: "*", methods: "*"));
            config.EnableCors(new EnableCorsAttribute("http://localhost:4200", headers: "*", methods: "*"));

            // Web API routes
     
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = RouteParameter.Optional }
            );
          
        }
    }
}

RouteConfig.cs:

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;

namespace WebAPI
{

    public class RouteConfig
    {
        [System.Web.Http.HttpGet]
        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 }
            );
        }
    }
}

Congratulations :partying_face:!

You were able to solve the problem by Yourself in the end :slight_smile:!

Whenever You need help, You know where to find us,

Happy coding!

1 Like

:smiley:
It is very motivating when you are able to give some pointers. Thank you!

I did find another tutorial that I can customize. It is in Angular7, but very comprehensive. Nice training for conceptual understanding.

With my finished project I would like to have course list and course details presented as default.
The user should not be able to do any Create Update Delete, only Read and click on Course-list to populate form.
But now I would like to implement a new Admin page. The user may click on a Admin and do CRUD from here.

Regards

1 Like

Hi! Take a look at my project!
" https://github.com/Tribbiiani/AngularWebAPI "

New features:

  1. CanActivate guard to protect admin-display page, must login verify
  2. Scrollbars for listing courses without affecting html layout.
  3. Default course page: User only able to read from database
  4. Admin-Display page user able to fully CRUD
  5. Styling

So I would like to add a simple form on the admin-page just to check for a 4-letter password: “1234”
It will use the login btn functionality to login after verifying password.

I do get some complaint about the image style credits, I am honoring the owner.

Sometimes the redirect to admin-display is not working after I login, but then I can use the Continue to Admin Page btn instead.

Regards!

1 Like

You’ve certainly improved a lot, so… congratulations :partying_face:!

I see You’re using the angular-cli scaffolding feature, which is nice since it gives the project a better structure; helps you understand how to better structure any software (Angular is highly opinionated, in contrast to Vue or React).

Those are the kind of problems one always has when learning something new :stuck_out_tongue:.

Keep it up and happy coding!

1 Like