【发布时间】:2017-12-15 10:15:37
【问题描述】:
目前我尝试实现一个 .NET Core 2.0 Web API web hook。
发送服务器上的 webhook 可以简单地配置为:
"endpoint": "http://localhost:50100/api/Hook"
发送服务器做了两件事:
- 在启动时,它会向定义的端点发送一个空帖子,以检查它是否存在以及支持哪些媒体类型
- 稍后,事件将作为帖子正文中的纯 json 发送到定义的端点
我实现了一个 HookController 并且知道我正面临一个(对我来说)奇怪的路由问题。
控制器实现如下:
[Route("api/Hook")]
public class HookController : Controller
{
protected ILogger<HookController> Logger { get; set; }
public HookController(ILogger<HookController> logger)
{
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
[HttpPost]
[Produces("application/json")]
[Consumes("application/json")]
public IActionResult HookReceiverLookUp()
{
Logger.LogInformation("Hook Receiver POST lookup called");
return Ok();
}
[HttpPost]
[Produces("application/json")]
[Consumes("application/json")]
public IActionResult HookReceiverEvent([FromBody] JObject res)
{
if (res == null)
{
Logger.LogInformation("Lookup called (most likely because post body was null)");
return Ok();
}
Logger.LogInformation("Hook Receiver event");
return Ok();
}
}
问题很简单:
- 如果我只有 HookReceiverLookUp 方法,服务器会在启动时识别出有效的端点,但显然此方法无法接收数据
- 如果我只有 HookReceiverEvent 方法,它可以从 POST 正文接收 json,但它不会被识别为有效端点(即使使用 [FromBody] JObject res = null)
- 如果我有这两种方法,接收 Web api 将不会以异常开始
AmbiguousActionException:匹配多个动作。以下操作匹配路线数据并满足所有约束:
那么这两种方法之间有什么区别(web api 说没有)以及如何将它们组合成一种方法(因为服务器配置让我只定义一种方法)?
我的最终解决方案
根据 Lennarts 的输入,我得到了一份可行的实施草案并正在运行。
public class HookController : Controller
{
protected ILogger<HookController> Logger { get; set; }
public HookController(ILogger<HookController> logger)
{
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
//configuration url: http://localhost:[port]/api/Hook/endpoint
[HttpPost("Endpoint")]
public IActionResult HookReceiver([FromHeader(Name = "Content-Type")] string type) //do not bind JObject here
{
if (type == null) return HookReceiverLookUp(); //check if it is the initial look up call / ignore body
//avoiding built in / default model binder and read the body yourself if necessary
string body;
using (var reader = new System.IO.StreamReader(Request.Body, System.Text.Encoding.UTF8, true, 1024, true))
{
body = reader.ReadToEnd();
}
//optionally convert it to Json if you want to work with json
JObject obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject>(body);
if (obj == null) return Ok(); //what else??
return HookReceiverEvent(obj);
}
private IActionResult HookReceiverLookUp()
{
Logger.LogInformation("Hook Receiver POST lookup called");
return Ok();
}
private IActionResult HookReceiverEvent(JObject res)
{
Logger.LogInformation("Hook Receiver POST lookup called\r\n" + res.ToString());
return Ok();
}
}
非常感谢 Lennart 的大力帮助和耐心。
【问题讨论】:
标签: asp.net-mvc-routing asp.net-core-webapi .net-core-2.0