c# - Angular 发布到 .net Web API

标签 c# angular asp.net-web-api

我正在尝试从我的 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());
            }
        }

最佳答案

我看到您会在代码中遇到意外错误和空值的多种原因:

  1. (错误)您的 .net 方法 callBcknd 甚至不应该编译,因为它只能在出现异常时返回一些内容。
  2. (错误)当向您的 api Controller 发送数据时,您应该发送 json 消息正文和 api Controller 方法应该接受一个复杂的对象,并且不是原始类型,比如 string/int/bool
  3. (警告)您的 Angular 服务应该公开功能并返回可观察对象或组件随后可以订阅的 promise 。不要直接公开 HttpClient
  4. (警告)您的网络 api 应该返回接口(interface) IHttpActionResult 而不是直接返回类型。然后,您可以使用 Ok 和 Content 以及 BadRequest 等内置方法来返回状态信息和数据。另见 Action Results in Web API 2
  5. (建议)使用RouteRoutePrefix 作为属性,而不是依赖路由配置。这更加灵活,并且还允许您指定要包含在 URL 中的参数,这将有助于实现更 RESTful 的设计。另见 Attribute Routing in ASP.NET Web API 2
  6. (建议)添加 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));
}

注意以下几点:

  1. ApiModel 表示请求中的传入对象。 Angular 调用然后发送 {content: 'This is what I have sent'} 这反射(reflect)了这种类型。
  2. IHttpActionResult 是您的 Web API 方法的响应类型
  3. 您可以在 CallBcknd 方法中返回不同的类型以及状态信息
  4. 添加了
  5. RouteRoutePrefix 以更好地控制 uri 路径。
  6. Angular 组件和服务已拆分为 2 个方法,服务返回一个可观察对象,组件调用服务方法并订阅返回的可观察对象。当您扩展此示例时,您希望使用接口(interface)将 any 替换为定义的预期结果,对于您要发送的任何传入参数也是如此。

关于c# - Angular 发布到 .net Web API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47172114/

相关文章:

c# - Web API 2/ token 返回更多信息

c# - 在 MediaTypeFormatter 中请求 URI

angular - 服务器端渲染使用Angular4(Angular Universal)

Angular 可观察属性 - 最佳实践

angular - 样式 "mat-sort-header-sorted"在 mat-table 教程中没有效果?

c# - MVC 4 WebAPI 中的操作

c# - 理解枚举——用作常量

c# - 如何旋转自定义移动标记(图像)GMap

c# - 从注册表中删除文件夹 - 权限问题

.net - WebAPI 多个 Put/Post 参数