ASP.NET MVC 5 - JSON -(动态?)模型绑定 - REST 服务 - Webhooks - Chargebee

ASP.NET MVC 5 - JSON - (Dynamic?) Model Binding - REST services - Webhooks - Chargebee

这应该很容易,但我卡住了。我已经使用服务 (ChargeBee) 设置了一个 webhook,该服务成功发布了我的网站 JSON。这是我要绑定的模型:

public class ChargeBeeWebhookModel
{
    public string id { get; set; }

    public string occurred_at { get; set; }

    public string source { get; set; }

    public string @object { get; set; }        

    public string content { get; set; }

    public string event_type { get; set; }

    public string webhook_status { get; set; }
}

除了 "content" 之外的所有内容都具有约束力,它是空的。问题是 "content" 会根据触发的事件类型而改变。例如,对于 "customer created" 事件,它可能是这样的:

 "customer": {
        "id": "8avVGOkx8U1MX",
        "first_name": "Benjamin",
        "last_name": "Ross",
        "email": "Benjamin@test.com",
        "auto_collection": "on",
        "created_at": 1317407411,
        "object": "customer",
        "card_status": "valid",
        "payment_method": {
            "object": "payment_method",
            "type": "card",
            "gateway": "chargebee",
            "reference_id": "tok_KyVr8xPHl5BSx1",
            "status": "valid"
        },
        "account_credits": 0
    },
    "card": {
        "customer_id": "8avVGOkx8U1MX",
        "status": "valid",
        "gateway": "chargebee",
        "iin": "411111",
        "last4": "1111",
        "card_type": "visa",
        "expiry_month": 1,
        "expiry_year": 2016,
        "object": "card",
        "masked_number": "************1111"
    }

我只需要将这些复杂对象绑定到某种类型。字符串不工作。绑定后,我可以使用 event_type 属性 轻松检查它是否是我要处理的事件,并将其反序列化为适当的自定义类型。

我该怎么做?我觉得我错过了一些非常简单的东西。据我所知,Chargebee 不会让我为每种类型的事件设置不同的 URL,这是我认为最有意义的。这是一个 URL,我必须绑定许多可能的响应。

我需要自定义模型活页夹吗?有没有更简单的方法?

也许有人可以制作一个 ChargeBee 标签?

谢谢大家


编辑:


根据要求,示例请求如下所示:

Headers
POST HTTP/1.1
Host:********.ngrok.io //(obviously I commented this out)
Authorization: Basic cGF0cmlvdGN5YmVybmV0aWNzZHJvbmVtYXN0ZXI6c3VuZGV2aWxjb2NvYXJhZ2luZ2J1bGw=
Content-Type: application/json; charset=utf-8
User-Agent: ChargeBee

Body
{
    "id": "ev_3Nl8ERLPElBCRU6",
    "occurred_at": 1341167306,
    "source": "admin_console",
    "object": "event",
    "content": {
        "subscription": {
            "id": "3Nl8ERLPElBCGl1",
            "plan_id": "basic",
            "plan_quantity": 1,
            "status": "future",
            "start_date": 1341772105,
            "trial_start": 1341772105,
            "trial_end": 1344450505,
            "created_at": 1341167305,
            "has_scheduled_changes": false,
            "object": "subscription",
            "addons": [{
                "id": "data_usage",
                "quantity": 1,
                "object": "addon"
            }],
            "due_invoices_count": 0
        },
        "customer": {
            "id": "3Nl8ERLPElBCGl1",
            "first_name": "Benjamin",
            "last_name": "Ross",
            "email": "Benjamin@test.com",
            "auto_collection": "on",
            "created_at": 1341167305,
            "object": "customer",
            "card_status": "valid",
            "payment_method": {
                "object": "payment_method",
                "type": "card",
                "reference_id": "3Nl8ERLPElBCGl1",
                "status": "valid"
            }
        }
    },
    "event_type": "subscription_created",
    "webhook_status": "not_configured"
}

除非我弄错了,否则我认为模型绑定器无法处理这种情况。据我所知,它需要预定义的类型并且不能处理可变性或动态的东西。如果我错了,请纠正我。不管怎样,我稍后会用完整的代码示例来回答这个问题,但现在我已经放弃了纯模型绑定方法,正在阅读 Request.InputStream 来获取我需要的 JSON 数据。然后,根据模型绑定器没有问题的 event_type,我将反序列化为我的预定义类型。只是我以前从来没有真正需要手动从请求中挑选一些东西;我一直用模型活页夹。

好的,下面应该可以工作。不要为内容传递 Javascript 对象,而是对您的对象使用 JSON.stringify 并将其结果设置为内容。这样,在您的控制器中,内容的值将是一个字符串。

这就是我想要实现的目标。 Request.InputStream 是必经之路;我开始尝试手动执行此操作,但幸运的是 ChargeBee 有一个官方 .NET 库(与 Mandrill 不同)可以为我完成所有操作:

    [HttpPost]
    [BasicAuthentication(username: "x", password: "y", BasicRealm = "z")]
    public HttpStatusCodeResult ChargeBeeWebhook()
    {
        if (ModelState.IsValid)
        {          
            Event chargeBeeEvent = new Event(Request.InputStream);

            EventTypeEnum? eventType = chargeBeeEvent.EventType;

            Event.EventContent eventContent = chargeBeeEvent.Content;

            if (eventType == EventTypeEnum.SubscriptionCreated)
            {
                Subscription subscription = eventContent.Subscription;

                Customer customer = eventContent.Customer;

                // more stuff
            }          

            return new HttpStatusCodeResult(200);
        }
        else
        {
            return new HttpStatusCodeResult(400); // bad request
        }
    }