2

I want to know exactly why this is not working:

[HttpPost]
public IHttpActionResult Post(Slack_Webhook json)
{
    return Ok(json.challenge);
}

public class Slack_Webhook
{
    public string type { get; set; }
    public string token { get; set; }
    public string challenge { get; set; }
}

The Official Documentation says:

We’ll send HTTP POST requests to this URL when events occur. As soon as you enter a URL, we’ll send a request with a challenge parameter, and your endpoint must respond with the challenge value.

This is an example object (JSON) sent by Slack:

{
    "token": "Jhj5dZrVaK7ZwHHjRyZWjbDl",
    "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P",
    "type": "url_verification"
}

EDIT: I could write a book on code that does not work in this issue... here's another example that did not work - still no idea what is wrong:

[HttpPost]
public IHttpActionResult Post()
{
    var pairs = Request.GetQueryNameValuePairs();
    bool isValidToken = false;
    string c = "This does not work.";
    foreach(var pair in pairs)
    {
        if (pair.Key == "token")
        {
            if (pair.Value == "<UNIQUETOKEN>")
            {
                isValidToken = true;
            }
        }
        if (pair.Key == "challenge")
        {
            c = pair.Value;
        }
    }
    if (isValidToken == true)
    {
        return Json(new {challenge = c });
    }
    else
    {
        return BadRequest();
    }
}

EDIT2: Very interesting that I get NULL as a response from below code - that means the body of the received POST is empty.. Could anyone with a working Slack-Integration try that out? So their site is wrong, stating the challenge is sent in the body - where else could it be?

// POST: api/Slack
[HttpPost]
public IHttpActionResult Post([FromBody]string json)
{
    return Json(json);
}

EDIT3: This function is used to get the raw request, but there is nothing inside the body - I am out of solutions.. the support of Slack said, they have no idea about ASP.NET and I should ask here on SO for a solution. Here we are again! ;-)

[HttpPost]
public async Task<IHttpActionResult> ReceivePostAsync()
{
    string rawpostdata = await RawContentReader.Read(this.Request);
    return Json(new StringContent( rawpostdata));
}
public class RawContentReader
{
    public static async Task<string> Read(HttpRequestMessage req)
    {
        using (var contentStream = await req.Content.ReadAsStreamAsync())
        {
            contentStream.Seek(0, SeekOrigin.Begin);
            using (var sr = new StreamReader(contentStream))
            {
                return sr.ReadToEnd();
            }
        }
    }
}

The result ( as expected ) looks like this:

Our Request:
POST
"body": { 
     "type": "url_verification",
     "token": "<token>",
     "challenge": "<challenge>"
}
Your Response:
"code": 200
"error": "challenge_failed"
"body": {
 {"Headers":[{"Key":"Content-Type","Value":["text/plain; charset=utf-8"]}]} 
}

I think I'm missing something - is there another way to get the body of the POST-Request? I mean, I can get everything else - except the body ( or it says it is empty).

EDIT4: I tried to read the body with another function I found - without success, returns empty string - but to let you know what I already tried, here it is:

[HttpPost]
public IHttpActionResult ReceivePost()
{
    var bodyStream = new 
    StreamReader(HttpContext.Current.Request.InputStream);
    bodyStream.BaseStream.Seek(0, SeekOrigin.Begin);
    var bodyText = bodyStream.ReadToEnd();
    return Json(bodyText);
}

While trying to solve this I learnt a lot - but this one seems to be so impossible, that I think I will never solve it alone. Thousands of tries with thousands of different functions - I have tried hundreds of parameters and functions in all of WebApi / ASP.NET / MVC / whatever - why is there no BODY? Does it exist? What's his/her name? Where does it live? I really wanna hang out with that parameter if I ever find it, must be hidden at the end of the rainbow under a pot of gold.

3
  • Well according to the documentation it is possible you are not returning the value (challenge) in one of the expected formats. Also You have not stated what is not working. Commented Sep 9, 2017 at 14:11
  • Are you able to inspect the raw request? Commented Sep 9, 2017 at 16:58
  • Not as a whole - I checked the headers, content-type is json, everything else seems ok. How do I inspect the raw request? I don't know how I would do this. Commented Sep 9, 2017 at 17:54

3 Answers 3

1

If you can use ASP.NET Core 2, this will do the trick:

public async Task<ActionResult> HandleEvent([FromBody] dynamic data)
    => new ContentResult {Content = data.challenge};
Sign up to request clarification or add additional context in comments.

Comments

0

According to the official documentation linked to in the OP you have to format your response depending on the content type you return.

It is possible you are not returning the value (challenge) in one of the expected formats.

Once you receive the event, respond in plaintext with the challenge attribute value. In this example, that might be:

HTTP 200 OK
Content-type: text/plain
3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P

To do the above you would have needed to return your request differently

[HttpPost]
public IHttpActionResult Post([FromBody]Slack_Webhook json) {
    //Please verify that the token value found in the payload 
    //matches your application's configured Slack token.
    if (ModelState.IsValid && json != null && ValidToken(json.token)) {
        var response = Request.CreateResponse(HttpStatusCode.OK, json.challenge, "text/plain");
        return ResponseMessage(response);
    }
    return BadRequest();
}

Documentation also shows

Or even JSON:

HTTP 200 OK
Content-type: application/json
{"challenge":"3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"}

Which again would have to be formatted a little differently

[HttpPost]
public IHttpActionResult Post([FromBody]Slack_Webhook json) {
    //Please verify that the token value found in the payload 
    //matches your application's configured Slack token.
    if (ModelState.IsValid && json != null && ValidToken(json.token)) {
        var model = new { challenge = json.challenge };
        return Ok(model);
    }
    return BadRequest();
}

3 Comments

Thank you for your answer! Unfortunately, the problem seems to be different. The proposed solutions do not work ( returns Error 500). If I use Post() without parameter, it returns Ok, but how do I access the body of the request with the challenge inside? It has to be something with the Json-Object received that does not fit Slack_Webhook ( which seems to be very weird, as it should be automatically serialized to fit the object)..
@SBelz Check update. You have to tell the framework to look in the body of the request.
Mhh. I get Code 500 with this one, too. Postman gets 400, with an empty body.
0

Here's how you can access the data:

[HttpPost]  
[Route("something")]
public JsonResult DoSomething()
{
    var token = HttpContext.Request.Form["token"];

    // Is the same as:
    // var token = Request.Form["token"];

    return new JsonResult(token);
}

I suggest using a Request Bin for further debugging.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.