1

我正在尝试让我的 .Net WebApi 2.2 接受来自 bitbucket 的帖子。但是 BB 不会将其数据作为主体发布,而是作为发布参数发布。

我在这里使用 PostMan 模拟了 bitbucket 发送的内容: http ://www.posttestserver.com/data/2014/11/05/shea/22.05.091712543622

您可以在此处导入 PostMan 集合:https ://www.getpostman.com/collections/ec562c5141d85fe7b850

当我尝试发布到我的 ApiController 时,我得到

{
    "Message": "The requested resource does not support http method 'POST'."
}

当我的 post 函数签名如下所示时,就会发生这种情况:

public string Post([FromUri]string payload)
{
    var hookEvent = JsonConvert.DeserializeObject<HookEvent>(payload);
    ....

或 public string Post(string payload) { var hookEvent = JsonConvert.DeserializeObject(payload); ……

当我做:

public string Post([FromUri]HookEvent payload)
{
    ....

有效负载不为空,但其中的所有字段均为空。

    public string Post(HookEvent payload)
    {

给出这个错误:

"Message": "The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource.",
"ExceptionMessage": "No MediaTypeFormatter is available to read an object of type 'HookEvent' from content with media type 'application/octet-stream'.",
"ExceptionType": "System.Net.Http.UnsupportedMediaTypeException",
"StackTrace": "   at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n   at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)"

我知道我的“HookEvent”正在正确反序列化,因为如果更改 PostMan 以将有效负载作为请求正文发送,则对象将正确反序列化,并设置所有字段。不幸的是,BB 并没有以这种方式发送有效载荷,而是作为 post 参数发送。

我的控制器签名是:

public class BitbucketHookController : ApiController
{
    ....

其他路由位:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapMvcAttributeRoutes();
    }
}

和 Global.asax.cs 中的 Application_Start()

        DiConfig.Register();
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

我必须做什么才能让我的控制器接受 post 有效负载?

4

1 回答 1

0

我能够提交的最佳解决方案是使用容器模型。

public class HookEventContainer
{
    public string payload { get; set; }
    public HookEvent HookEvent {
        get
        {
            if (string.IsNullOrEmpty(payload))
            {
                return null;
            }
            return JsonConvert.DeserializeObject<HookEvent>(payload);
        }
    }
}

然后将其用于我的 Post 签名:

    // POST api/<controller>
    //
    public string Post(HookEventContainer eventData)
    {
        var hookEvent = eventData.HookEvent;

丑陋但有效。

我还向 Bitbucket 发送了一个请求,以了解他们选择将有效负载作为参数而不是请求正文发送的原因。自从 Atlassian 购买它们后,它们并没有那么敏感......

于 2014-11-06T19:46:00.853 回答