我正在尝试从我的 Angular 应用程序执行 POST 到 .net Web API 实例,但服务器返回 null
。
服务器
[HttpPost]
public string callBcknd([FromBody]string body)
{
try
{
Log.Info(string.Format("{0}", body));
}
catch(Exception ex)
{
return "error";
}
}
}
angular *注意我使用的是 HttpClient 而不是 Http.. 不确定这是否也是问题
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);}}}
配置
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}
);
}
}
通过上述设置,我不会在客户端产生任何 404 服务器错误(通过检查 chrome 的控制台),但它在后端返回 null。但是当我尝试使用 Postman 时,它使用相同的 url 正确发送值。如果我不在后端的方法中包含 [FromBody],我会在客户端收到 404 服务器错误。此外,消息说“没有找到与请求 URI 匹配的 HTTP 资源”。与此类似的问题似乎通过 [FromBody] 解决了问题,但我仍然得到一个空...我还怀疑我的网络配置文件(不是上面的那个)应该包含一些标题,所以当我添加一些标题时,比如内容输入 json 等,然后我在客户端收到 500 服务器错误。在这一点上,我真的很困惑,不知道该怎么做。
更新1
以下服务器代码返回了消息,但我仍然将正文设置为 null.. 没有观察到任何错误
[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());
}
}
最佳答案
我看到您会在代码中遇到意外错误和空值的多种原因:
- (错误)您的 .net 方法
callBcknd
甚至不应该编译,因为它只能在出现异常时返回一些内容。 - (错误)当向您的 api Controller 发送数据时,您应该发送 json 消息正文和 api Controller 方法应该接受一个复杂的对象,并且不是原始类型,比如
string
/int
/bool
等 - (警告)您的 Angular 服务应该公开功能并返回可观察对象或组件随后可以订阅的 promise 。不要直接公开
HttpClient
。 - (警告)您的网络 api 应该返回接口(interface)
IHttpActionResult
而不是直接返回类型。然后,您可以使用 Ok 和 Content 以及 BadRequest 等内置方法来返回状态信息和数据。另见 Action Results in Web API 2 - (建议)使用
Route
和RoutePrefix
作为属性,而不是依赖路由配置。这更加灵活,并且还允许您指定要包含在 URL 中的参数,这将有助于实现更 RESTful 的设计。另见 Attribute Routing in ASP.NET Web API 2 - (建议)添加 CamelCasePropertyNamesContractResolver解决前端和后端之间的 Camel 和帕斯卡外壳。另见 Serialization using ContractResolver
这是一个很好的示例,说明如何调用 Web API 以及如何构建代码。
请注意,这些代码示例仅显示添加或修改的相关部分
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));
}
注意以下几点:
ApiModel
表示请求中的传入对象。 Angular 调用然后发送{content: 'This is what I have sent'}
这反射(reflect)了这种类型。IHttpActionResult
是您的 Web API 方法的响应类型- 您可以在
CallBcknd
方法中返回不同的类型以及状态信息
添加了 Route
和RoutePrefix
以更好地控制 uri 路径。- Angular 组件和服务已拆分为 2 个方法,服务返回一个可观察对象,组件调用服务方法并订阅返回的可观察对象。当您扩展此示例时,您希望使用接口(interface)将
any
替换为定义的预期结果,对于您要发送的任何传入参数也是如此。
关于c# - Angular 发布到 .net Web API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47172114/