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.
-
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.Igor– Igor2016年10月06日 20:24:40 +00:00Commented 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?Nathan Foss– Nathan Foss2016年10月06日 20:28:28 +00:00Commented 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).Igor– Igor2016年10月06日 20:34:09 +00:00Commented Oct 6, 2016 at 20:34
1 Answer 1
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);
}
- SO - How to post a single string (using form encoding)
- SO - send single string parameter - this might be the better option, good answer.
7 Comments
[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.404
with all of these options.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.