I am trying to execute a POST from my angular application to a .net Web API instance but the server returns null
.
server
[HttpPost]
public string callBcknd([FromBody]string body)
{
try
{
Log.Info(string.Format("{0}", body));
}
catch(Exception ex)
{
return "error";
}
}
}
angular *note that I am using HttpClient instead of Http.. not sure if this is also the problem
callServer(){
var test = { "name": "John" }
let data = JSON.stringify(test);
let headers = new HttpHeaders();
headers.set('Content-Type', 'application/json');
this.appService.http.post('http://localhost:3000/api/WebApI/callBcknd',
test,
{headers: headers})
.subscribe(data => {console.log(data);}}}
config
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new {action = "GET", id = RouteParameter.Optional}
);
}
}
With above setting, I don't gen any 404 server error in client side(by checking chrome's console) but it returns null in backend. But as I tried with Postman, it sends values properly with the same url. If I don't include [FromBody] inside of method in backend, I get an 404 server error in client side. Furthermore, messages says "NO HTTP resource was found that matches the request URI". Similar question to this seems solving the problem by having [FromBody] but I still get a null... I also suspected maybe my web config file(not the one in above) should contain some headers, so when I added some headers like content type to be json and etc then I get 500 server error in client side. At this point i am really confused and not sure what to proceed.
UPDATE1
Following server code returns the message but I am still getting the body as null.. no errors have been observed
[HttpPost]
public IHttpActionResult Callbcknd([FromBody] string body)
{
try
{
Log.Info(string.Format("called with data {0}", body));
return Ok(new { Message = "It worked!" });
}
catch(Exception ex)
{
return base.Content(HttpStatusCode.InternalServerError, ex.ToString());
}
}
I see multiple reasons why you would get unexpected errors and null values in your code:
callBcknd
should not even compile as it can only return something if there is an Exception.string
/int
/bool
etc.HttpClient
directly.IHttpActionResult
instead of the type directly. Then you can use the built in methods like Ok and Content and BadRequest to return status information along with data. See also Action Results in Web API 2
Route
and RoutePrefix
as attributes instead of relying on the route config. This is more flexible and will allow you to also specify parameters to be included in the URL which will make for a more RESTful design. See also Attribute Routing in ASP.NET Web API 2
This is a good example of how make calls to a Web API and how to structure your code.
Note that these code samples only show the relevant parts that were added or modified
WebApiConfig.cs
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// add this to ensure that casing is converted between camel case (front end) and pascal case (c#/backend)
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.MapHttpAttributeRoutes();
}
}
ApiModel.cs
public class ApiModel {
public string Content {get;set;}
}
WebApIController.cs
[RoutePrefix("api/WebApI")]
public class WebApIController : ApiController {
[HttpPost]
[Route("callBcknd")]
public IHttpActionResult CallBcknd([FromBody] ApiModel body)
{
try
{
Log.Info(string.Format("{0}", body.Content));
return Ok(new {Message = "It worked!"});
}
catch(Exception ex)
{
// example of how to return error with content. I would not recommend actually returning the exception details to the client in a production setting
return base.Content(HttpStatusCode.InternalServerError, ex.ToString());
}
}
}
application.service.ts
constructor(private httpClient: HttpClient){}
callServer(data: {content: string}) : Observable<any> {
return this.httpClient.post('http://localhost:3000/api/WebApI/callBcknd', data);
}
application.component.ts
constructor(private myService: MyService){}
onDoSomething(){
this.myService.callServer({content: 'This is what I have sent'})
.subscribe(data => console.log("Succeeded, result = " + data), (err)=> console.error("Failed! " + err));
}
Notice the following:
ApiModel
represents the incoming object in the request. The angular call then sends {content: 'This is what I have sent'}
which mirrors this type.IHttpActionResult
is the response type for your Web API methodCallBcknd
Route
and RoutePrefix
were added to give more control over the uri path.any
with defined expected results using interfaces and the same is true for any incoming parameters you want to send.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With