0

I'm building an Angular2 service to log certain events, stored in ILog objects, and send them to an API to be stored in a database.

My log service is pretty straightforward:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { EnvironmentModule } from "../environment";
import { ILog } from "./log";
@Injectable()
export class LogService {
 constructor(private _http: Http, private environment: EnvironmentModule) { }
 postLog(log: ILog): void {
 this.json = this.convertToJSON(log);
 this._http.post(this.environment.getWebApiUri() + 'api/Log/PostLog/', log, {})
 .subscribe(
 () => console.log('Success')
 ); //goes to localhost:3304/WebAPI/Log/PostLog/, returns 404 not found
 }
}

And it calls a WebAPI Controller that passes the data off to a service to be processed:

[RoutePrefix("api/Log")]
public class LogController : ApiController
{
 private ILogService _LogService;
 public LogController() : this(new LogService())
 {
 } //constructor
 public LogController(ILogService LogService)
 {
 _LogService = LogService;
 } //constructor
 [HttpPost()] 
 [Route("PostLog")]
 public void PostLog(Log log)
 {
 _LogService.PostLog(log);
 } //PostLog
} //class

Yet, when my service calls the API it throws a 404 Not Found Error.

Navigating to the path in the browser I see this:

<Error>
 <Message>
 No HTTP resource was found that matches the request URI
 'http://localhost:3304/WebAPI/api/Log/PostLog/'.
 </Message>
 <MessageDetail>
 No action was found on the controller 'Log' that matches the request.
 </MessageDetail>
</Error>

Can anyone help me with this? I don't understand why it's behaving this way.

asked Oct 6, 2016 at 19:55
3
  • Its because you cant post an atomic value directly to your method as json. You could turn it into an object and then post it as a corresponding object or post it as form uri encoded which also works. This is a limitation of asp.net's web api. Commented Oct 6, 2016 at 20:24
  • @Igor I get the same error whether I POST json or the ILog object. Do you have documentation on this? Commented Oct 6, 2016 at 20:28
  • I updated my answer, the 2nd link has a good example of how you can just change your javascript code and get it to work (i think). Commented Oct 6, 2016 at 20:34

1 Answer 1

6

Its because you cant post an atomic value directly to your method as json. You could turn it into an object and then post it as a corresponding object or post it as form uri encoded which also works. This is a limitation of asp.net's web api.

There are some other similar questions all with similar answers. Here is a quick example of how you could change it to work.

c# code

[HttpPost()] 
[Route("PostLog")]
public void PostLog(LogContainerModel logModel)
{
 _LogService.PostLog(logModel.log);
}
// model
public sealed class LogContainerModel {
 public string log { get; set; }
}

javascript code

private convertToJSON(log: ILog): string {
 return JSON.stringify({log: log});
}

Option 2

Stringify it as an object according to this previous SO answer.

c# code

[HttpPost()] 
[Route("PostLog")]
public void PostLog([FromBody] string jsonString)

javascript code

private convertToJSON(log: ILog): string {
 return JSON.stringify({'': log}); // if that does not work try the snippet below
 // return JSON.stringify({'': JSON.stringify(log)});
}

Option 3

Here are some options from bizcoder.com

Use HttpResponseMessage

[HttpPost()] 
[Route("PostLog")]
public async Task PostLog(HttpRequestMessage request)
{
 var jsonString = await request.Content.ReadAsStringAsync();
 _LogService.PostLog(jsonString);
}

Or use json.net

[HttpPost()] 
[Route("PostLog")]
public void PostLog([FromBody]JToken jsonbody)
{
 var jsonString = jsonbody.ToString();
 _LogService.PostLog(jsonString);
}
answered Oct 6, 2016 at 20:29

7 Comments

Alternatively you can add [FromBody] to the jsonString parameter of the action method, and have your client side code post something like "{log:\"message\"}" (basically encode the log object as JSON twice) in the request body. But the method you describe is nicer.
Great insights. Unfortunately, still having the same issues even after trying all of those ideas
@NathanFoss - added 2 more options under option #3
Thanks for all the help @Igor. I am changing my implementation to pass through the object directly in light of that bizcoder article. Unfortunately, I still get a 404 with all of these options.
@NathanFoss - it might not only be the fact that you are sending json. At this point I would set a break point and copy the string this.environment.getWebApiUri() + 'api/Log/PostLog/' and make sure that its correct. Then use Fiddler to test that url with a value. If that does not work try it again and post without a value (remove value as well from web api method). This should help you determine if the issue (at this point) is the url, route, or something other than the parameter you are passing.
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.