Angular8 app http error 405 on page refresh - c#

i am developing an using Angular8 and .NET Core 3.0 in Visual Studio. I have a page with a form which is working without any issues. However when i press F5 on that page i get the following error
Failed to load resource: the server responded with a status of 405
(Method Not Allowed) [http://localhost:51871/notifications]
This is the submit function in the component class
onSubmit() {
if (this.registerForm.invalid) {
return;
}
let post: NotificationsInterface = {
email: this.registerForm.value.email,
subject: this.registerForm.value.subject,
text: this.registerForm.value.text,
};
this.http.post("Notifications", post).subscribe(result => {
console.error("ok");
}, error => console.error("error"));
}
This is the notification class in C#
public class Notifications
{
public string email { get; set; }
public string subject { get; set; }
public string text { get; set; }
}
This is the controller in C#
using Microsoft.AspNetCore.Mvc;
using HomeHelper.Models;
namespace HomeHelper.Controllers
{
[ApiController]
[Route("[controller]")]
public class NotificationsController : Controller
{
[HttpPost]
public IActionResult Post([FromBody]Notifications notification)
{
return Ok();
}
}
}
When i comment the controller part in C# the error is gone, however the data cannot be received. What is the best practice for such errors to be avoided ?
The error only occurs in the url " http://localhost:51871/notifications "
Best regards!
UPDATE: I have added the full code of the controller and the url with the specified error.

You can debug this issues by creating a get route with same end point in your controller.
when you refresh your Angular application as you have a route localhost:51871/notifications in your controller your server resolves the route and points you to the controller but as of now there is no Get method (as browser sends a get request when you refresh) so it gives you error.
I guess either to adopt to hash location strategy or try changing the angular route or you can do is all your backend api url should work if there is a api in the url path
like localhost:51871/api/notifications that will help to sort api is getting called

Try using hash location strategy.
RouterModule.forRoot(routes, {useHash: true})

Related

ASP.NET Core 5.0 Web API throws error 405 when trying to delete record using HttpDelete

I'm building an ASP.NET Core 5.0 Web API application as I mentioned in the title I have an issue when trying to delete a record from the database; I'm getting an error 405 Method Not Allowed response from HttpDelete request.
PS: I have added services.AddCors() and app.UseCors() with default policy.
This is the delete method code
public bool deleteLivreById(int id)
{
Livre l = _db.Livres.Find(id);
_db.Livres.Remove(l);
_db.SaveChanges();
return true;
}
And this is the HttpDelete method inside the controller
[HttpDelete("{id}/delete")]
public bool deleteLivreById(int id)
{
return _objGererLivre.deleteLivreById(id);
}
Finally this is a picture from console when navigating to HttpDelete Url
Edit: This is full code of my controller
namespace GestionLivre.Controllers
{
[ApiController]
[Route("test")]
public class LivreController : Controller
{
private IGererLivre _objGererLivre;
public LivreController(IGererLivre gererLivre)
{
_objGererLivre = gererLivre;
}
[HttpGet]
public JsonResult getLivres()
{
return Json(_objGererLivre.getLivres());
}
[HttpDelete("{id}/delete")]
public bool deleteLivreById(int id)
{
return _objGererLivre.deleteLivreById(id);
}
}
}
I opened the screenshot and noticed that you have selected 'GET' as http verb and method type is 'Delete'. Could you please change that and try.
As I understand by default when you're trying to access URL in browser it uses GET method. So we should to pass in header appropriate method(POST,GET,DELETE,PATCH,PUT) If you want to test HTTP methods I'll recommend you to use Postman or Swagger. Postman much easier to use whether than Swagger which you should to add to service configuration and middleware.
Example of Postman:
And than configure body like that to return response.
Also recommend you to use REST Best Practices. And name resources properly. https://restfulapi.net/resource-naming/#:~:text=2.-,Best%20Practices,-2.1.%20Use%20nouns

WEB API Controller not loading in browser

Having some issues getting started in C#, here's the error I'm getting:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
New to this language, any tips appreciated.
Here's my code:
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace Http5112Assignment2.Controllers
{
public class DiceGameController : ApiController
{
[Route("api/J2/DiceGame/{die1}/{die2})")]
public class J2Controller : ApiController
{
[HttpGet]
public int DiceGame(int die1, int die2)
{
int dieSum = die1 + die2;
return dieSum;
}
}
}
}
Kindly do the following.
Move each class to a separate file with the name as the Api controller. In here we can see that you have nested two Api controllers which should not be done.
Api controller route annotations usually looks like [Route("[controller]")] or [Route("api/[controller]")]. Below is an example.
[Route("api/[controller]")]
public class J2Controller : ApiController
{
[HttpGet("DiceGame/{die1}/{die2}")]
public int DiceGame([FromRoute] int die1, [FromRoute] int die2)
{
int dieSum = die1 + die2;
return dieSum;
}
}
If you want to call the DiceGame endpoint, then make sure your Api is running and you can simply do a HTTP GET request to the URL: https://localhost:[yourport]/api/j2/dicegame/69/420.
For more info on routing, visit the following URL.
Create web APIs with ASP.NET Core
I see that there may be a typo in your route string, note the ) in the /{die2})
So, Assuming that you didn't change anything in the default routing in your RouteConfig file, then Make sure you're URL is as follows (note that mine runs on https://localhost:44301 yours may differ)
https://localhost:44301/api/J2/DiceGame/12/34)
Note: It'd be helpful if you provide the request URL you were attempting to use that gave you the error or even better a cURL which is a standard format for that request that gave you the 404

.Net Core "Http failure response 404 Not Found" error [duplicate]

This question already has answers here:
404 error when making a POST call from Angular HttpClient to ASP.NET Core 2.2 Web API (with CORS enabled)
(2 answers)
Closed 3 years ago.
I am just starting to get into netcore 2.2 and I am trying to call my controller from angular as so however when I call the send contact email method from my service I get a "Http failure response for http://localhost:53270/api/DataController/SendContactEmail/: 404 Not Found"
As you can clearly see I am explicitly writing out the route in the below routine
sendContactEmail(contact: ISubmitModel): Observable<any> {
return this._http.post<any>('api/DataController/SendContactEmail/', contact)
}
and my controller method
[Route("api/[controller]")]
public class DataController : Controller
{
[HttpPost("[action]")]
public IActionResult SendContactEmail(ContactUs contact)
{
ContactUs form = new ContactUs()
{
Email = contact.Email,
Name = contact.Name,
Phone = contact.Phone,
Message = contact.Message
};
return Ok(form);
}
public class ContactUs
{
public string Name { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string Message { get; set; }
}
}
You should ommit the Controller part and just use Data
return this._http.post<any>('http://localhost:51889/api/Data/SendContactEmail/', contact)
As the others have mentioned you should not be using the word Controller in the route since you're using the Route Attribute with the template [controller] inside the route it'll only take the name of that controller without including the Controller word.
To make it more readable you could change the template api/[controller] for api/data so it doesn't lead to confusion.
This tends to be a good practice, because
if someday in the future you'd decide to change the name of the Controller for some reason, and you've tied the route to the controller name, the consuming applications of the api would break because the route would have changed (you don't want that) and obviously the consuming applications would have to change all the references to that route in order to work properly.

How do I customize ASP.Net Core model binding errors?

I would like to return only standardized error responses from my Web API (Asp.net Core 2.1), but I can't seem to figure out how to handle model binding errors.
The project is just created from the "ASP.NET Core Web Application" > "API" template. I've got a simple action defined as:
[Route("[controller]")]
[ApiController]
public class MyTestController : ControllerBase
{
[HttpGet("{id}")]
public ActionResult<TestModel> Get(Guid id)
{
return new TestModel() { Greeting = "Hello World!" };
}
}
public class TestModel
{
public string Greeting { get; set; }
}
If I make a request to this action with an invalid Guid (eg, https://localhost:44303/MyTest/asdf), I get back the following response:
{
"id": [
"The value 'asdf' is not valid."
]
}
I've got the following code in Startup.Configure:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
JsonErrorMiddleware.CreateSingleton(env);
if (!env.IsDevelopment())
{
app.UseHsts();
}
app
.UseHttpsRedirection()
.UseStatusCodePages(async ctx => { await JsonErrorMiddleware.Instance.Invoke(ctx.HttpContext); })
.UseExceptionHandler(new ExceptionHandlerOptions() { ExceptionHandler = JsonErrorMiddleware.Instance.Invoke })
.UseMvc()
}
JsonErrorMiddleware is simply a class that converts errors to the correct shape I want to return and puts them into the response. It is not getting called at all for the model binding errors (no Exception is thrown and UseStatusCodePages is not called).
How do I hook into the model binding to provide a standardized error response across all actions in my project?
I've read a bunch of articles, but they all seem to either discuss global exception handling or validation errors.
It's worth mentioning that ASP.NET Core 2.1 added the [ApiController] attribute, which among other things, automatically handles model validation errors by returning a BadRequestObjectResult with ModelState passed in. In other words, if you decorate your controllers with that attribute, you no longer need to do the if (!ModelState.IsValid) check.
Additionally, the functionality is also extensible. In Startup, you can add:
services.Configure<ApiBehaviorOptions>(o =>
{
o.InvalidModelStateResponseFactory = actionContext =>
new BadRequestObjectResult(actionContext.ModelState);
});
The above is just what already happens by default, but you can customize the lambda that InvalidModelStateResponseFactory is set to in order to return whatever you like.

Post service ASP.NET

I have a webservice to authentificate my user (from an app made with cordova) :
[RoutePrefix("api/RegisterUser")]
public class UsersController : ApiController
{
[HttpPost]
[Route("Authenticate")]
public async Task<IHttpActionResult> GetUserAuthenticated(string userName, string pwd)
{
//Code here
}
}
with cordova I use this :
let data = {
FK_BaseID:2,
FK_UserTypeID: this.IDs.userType,
Username: regData.email.toLowerCase(),
Password: regData.password,
}
this._http.post('RegisterUser', data);
But I get this error :
"Message":"No HTTP resource was found that matches the request URI '..../RegisterUser/Authentificate'.",
"MessageDetail":"No type was found that matches the controller named 'RegisterUser'."
My service was working fine with HttpGet but I can't manage to make it work with post.
I've tried something like this :
public IHttpActionResult GetUserAuthenticated(string body)
{
return Ok(body);
}
using [FromBody] also, but I'm unable to make it work. I've seen a few examples using Request.Form to navigate through the body of the request and thus the parameters. But my Request hasn't any Form property.
What am I missing ?
I would wrap the "body" param with a class or struct typedef
the way that the routing mechanism works is by matching methods and parameters received to those one who already been registered (see ApiExplorer class for instance in WebApi; this is how the asp App is actually booting itself into a full state web "actions receiver and invoker")
What happens with your code is, in my humble understanding, is that the app is searching for a complex parameter to build the "body" parameter since it is a POST message (hence the attribute name "FromBody") and thus fails to find an entry in the BODY sector of the http message for a complex "body" segment
just wrap the parameter with a class, i.e
public class MyMessage { public string Body {get;set;} }
notice here that this is actually the same as your code since the "MyMessage" identifier is actually not anywhere to be seen in the body of the message, and is a good example to understand since the web app mechanism actually does this kind of "pairing" on its own based on the url you have provided and the compile time signatures you have imposed on the action implementation
I'll do it like this :
public class AuthenticateViewModel {
public string Username {get; set;}
public string Password {get; set;}
}
And in your controller :
[RoutePrefix("api/RegisterUser")]
public class UsersController : ApiController {
[HttpPost]
[Route("Authenticate")]
public IHttpActionResult GetUserAuthenticated([FromBody]AuthenticateViewModel model){
var userName = model.Username;
var pwd = model.Password;
// Code logic here.
return Ok(model);
}
}
The names of your parameters have to match for the binding to execute.
You may want to check your client code also, seems like you're not posting on the right url :
let data = {
FK_BaseID:2,
FK_UserTypeID: this.IDs.userType,
Username: regData.email.toLowerCase(),
Password: regData.password,
}
this._http.post('api/RegisterUser/Authenticate', data);

Categories