Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The application completed without reading the entire request body. #7

Closed
chuksgpfr opened this issue May 30, 2019 · 8 comments
Closed
Labels
invalid This doesn't seem right question Further information is requested wontfix This will not be worked on

Comments

@chuksgpfr
Copy link

chuksgpfr commented May 30, 2019

Request.Body.Seek(0, SeekOrigin.Begin); using (var reader = new StreamReader(Request.Body)) { var json =await reader.ReadToEndAsync(); }

when testing my webhook, it throws 500 internal server error. and then in my server i see this error "The application completed without reading the entire request body."

@bchavez
Copy link
Owner

bchavez commented May 30, 2019

Hi @chuksgpfr ,

You'll have to provide more information:

  • A stack trace if possible.
  • The complete and full controller source code of the endpoint that's supposed to handle the webhook.
  • A list of all your dependencies.
    • Including ASP.NET Core version, .NET version, and SDK version.
    • Operating System, the exception is occurring on and version.
    • Your hosting environment, IIS, Kestrel or IISExpress.

@chuksgpfr
Copy link
Author

chuksgpfr commented May 31, 2019

  1. I can't get stack trace now..
  2. The complete controller handling the webhook is...
        [HttpPost]
        [AllowAnonymous]
        public async Task<ActionResult> BalanceAccount()
        {
            string sharedSecret = "ff9a9b56-4b94-ffac-9c9f-97f9937d2d6c";
            var requestSignature = Request.Headers[HeaderNames.WebhookSignature];
            Request.Body.Seek(0, SeekOrigin.Begin);
            using (var reader = new StreamReader(Request.Body))
            {
                var json =await reader.ReadToEndAsync();

                if (WebhookHelper.IsValid(sharedSecret, requestSignature, json))
                {
                    var webhook = JsonConvert.DeserializeObject<Webhook>(json);
                    var chargeInfo = webhook.Event.DataAs<Charge>();
                    //the customer id created in the charge controller
                    var customerId = chargeInfo.Metadata["customerId"].ToObject<string>();

                    if (webhook.Event.IsChargeConfirmed)
                    {
                        var user = await _userRepo.FindById(customerId);
                        //if (user != null)
                        //{
                        var bal = _contextRepo.FindBalanceByUserId(customerId);
                        FundAccount newFund = new FundAccount()
                        {
                            User = user,
                            Amount = chargeInfo.Pricing["Amount"].Amount,
                            PaymentMethod = "BITCOIN",
                            AccountDetails = chargeInfo.Addresses["bitcoin"],
                            TransactionId = Guid.NewGuid().ToString(),
                            Status = "PAID",
                            Date = chargeInfo.ConfirmedAt
                        };
                        if (bal == null)
                        {
                            Balance newBalance = new Balance()
                            {
                                User = user,
                                Amount = chargeInfo.Pricing["Amount"].Amount,
                                DateUpdated = DateTime.UtcNow
                            };
                            _contextRepo.CreateBalance(newBalance);
                        }
                        else
                        {
                            bal.Amount += chargeInfo.Pricing["Amount"].Amount;
                            bal.DateUpdated = DateTime.UtcNow;
                            _contextRepo.UpdateBalance(bal);
                        }

                        _contextRepo.FundAccount(newFund);
                        // return RedirectToAction("fundlist", "dashboard");
                        //}

                        return Ok(new { userId = "Yes" });
                    }
                }
            }
            //var json = await new StreamReader(Request.Body).ReadToEndAsync();

            // StreamReader SourceReader = System.IO.File.OpenText()

            
            //Create a successful payment page
            return Ok(new { userId = "customerId"});
        }
  1. ASP.NET core version 2.1 .NET core 2.2
    OS is windows 10.
    Hosting environment is IISExpress

@bchavez
Copy link
Owner

bchavez commented May 31, 2019

@chuksgpfr , you might want to call this.Request.EnableRewind() so you can rewind the request stream. For performance reasons, the request stream can only be read forward once. So, you'll need to tell ASPNET you want to rewind the stream. Here's a working example of how to read from the request body stream.

using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.AspNetCore.Mvc;

namespace FooBar.Controllers
{
   [Route("api/[controller]")]
   [ApiController]
   public class ValuesController : ControllerBase
   {
      // POST api/values
      [HttpPost]
      public async Task<ActionResult> Post()
      {
         this.Request.EnableRewind(); // <-- This is very important

         var body = this.Request.Body;
         body.Seek(0, SeekOrigin.Begin);

         using (var reader = new StreamReader(body))
         {
            var payload = await reader.ReadToEndAsync();

            return Ok(payload);
         }
      }
   }
}

Reference: #1

@bchavez
Copy link
Owner

bchavez commented Jun 1, 2019

Hi @chuksgpfr , I hope my last post help you solve your issue. If you have any other questions, feel free to continue posting here. For now, I'm going to close the issue. Thanks again for asking your question.

-Brian

@bchavez bchavez closed this as completed Jun 1, 2019
@bchavez bchavez added invalid This doesn't seem right question Further information is requested wontfix This will not be worked on labels Jun 1, 2019
@chuksgpfr
Copy link
Author

Hi @bchavez I'm sorry for the late reply, SCHOOL ISSUES...

While sending a test webhook from coinbase, i'm still getting 500 internal server error...

Please can u create an actual project and try. This will be very helpful to me.

Thanks..

PS: I'm testing locally using ngrok. Thanks. Coinbase Shows "Remote server at 6f7d068b.ngrok.io returned an HTTP 502" while ngrok shows no error using https

@chuksgpfr
Copy link
Author

Thanks man.....

Just fixed it.

@chuksgpfr
Copy link
Author

Quick question...
When sending a test from coinbase, does it carry any information on the body and is the test different from the actual webhook. Because this lines of code refuse to run.

AccountDetails = chargeInfo.Addresses["bitcoin"]
Amount = chargeInfo.Pricing["Amount"].Amount

@bchavez
Copy link
Owner

bchavez commented Jun 4, 2019

Hi @chuksgpfr ,

The HTTP body of the webhook should contain something. You'll need to read the body into the webhook object model to get more details about what that object is. The line below illustrates how to read the body into a Webhook object:

var webhook = JsonConvert.DeserializeObject<Webhook>(Request.Body.Json);

Again, don't forget to EnableRewind() to read the body. Set a breakpoint on the line above to debug.

Also, you'll have to examine the ngrok Web Interface to look at more details of the webhook payload that is hitting your endpoint for the exact HTTP payload details of what was sent to you.

cmd_3324

From these, it should be clear after examining the breakpoint on the webhook object and by examining the ngrok web interface what is being delivered to your endpoint; and ultimately, what you have access to.

Additionally, chargeInfo.Pricing["Amount"].Amount seems redundant. It should be something more simple like chargeInfo.Pricing.Amount.


Lastly, I want to help with friendly advice: please remember, anytime you have an issue with code and you have to report an issue to a person who is not next to you (like over the Internet), please always remember that the other person doesn't have access to your computer and it is very hard for the other person to get an idea of what your problem is without being next to you to help you.

It's very difficult for everyone to provide help over the Internet just by writing text. 😢 So, here are some helpful tips to make the process more successful for everyone:

When reporting an issue to someone --

  • Spend as much time as you can writing clearly about what the problem is. This goes a long way to help convey that you've done your best in trying to understand why something is wrong.
    • Include stack traces.
    • Include full exception messages.
  • Post as much code as possible. The more the better. Understanding context goes a very long way in helping solve problems. I can only see what you give me. Imagine how hard it is to understand how a program is working only seeing tiny bits of code, it's very, very, very difficult.
  • Post as much diagnostics info you have. .NET runtimes versions, OS versions, server versions, client versions. package dependency versions. Everything.
  • Post logs - any and all logs, HTTP traces, body, headers, custom logs. etc.
  • Post what you expect should happen and what you currently know about the problem. If you can find a problem in the source code, please point it out about what and why something should be different.

The more things you can provide about the problem, the more successful we will all be in helping you resolve those issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
invalid This doesn't seem right question Further information is requested wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants