7

Is there a way for me to receive a json object as a string and not convert to a class in my Web API?

If I create a class that matches the structure of the json object I receive, everything works nicely because the ModelBinder handles it. However, if I try to keep it as a string, it's failing. The value of transaction parameter ends up being null -- see my API method below.

This is what my CreditCardTransaction class looks like that I use to receive data into my API method:

public class CreditCardTransaction
{
   public int Amount { get; set; }
   public string Description { get; set; }
   public string Token { get; set; } // This is the json object
}

And my API method looks like this:

[HttpPost("process")]
public async Task<IActionResult> ProcessPayment([FromBody] CreditCardTransaction transaction)
{
   if(transaction == null || !ModelState.IsValid)
      return new StatusCodeResult(400);

   // Process transaction
}

I'm doing this for Stripe Checkout integration where Stripe frontend client converts sensitive credit card data into what they call a token which is a json object. So, in my backend API, I just want to receive the token along with a couple of simple data points i.e. amount and description.

If I set my CreditCardTransaction class to the above structure, transaction ends up getting a null value. Looks like ModelBinder doesn't like the idea of having a json object in Token property which is defined as a string.

If I create a class that matches the structure of the json object for the token, I'm able to receive it but it's causing other issues for me, not to mention all the unnecessary conversions.

I do NOT need the token except to pass it to Stripe's API to complete the transaction. I will not save it or manipulate it. Looks like Stripe's API is expecting a json object anyway so I simply want to receive it and pass it to their API as is without messing with it.

How do I receive this json object?

9
  • 1
    Did you try using the dynamic keyword? You can get an idea here about the usage of dynamic keyword. There is no need to define a POCO class. carlserver.com/blog/post/… Commented Dec 15, 2017 at 17:19
  • Sorry I am a bit confused... is Task<IActionResult> a standard object? Or can you show the definition Commented Dec 15, 2017 at 17:20
  • @Baskar Yes! dynamic worked! Thank you. Please post it as an answer so that I can accept it. Commented Dec 15, 2017 at 17:22
  • Try using the dynamic keyword? You can get an idea here about the usage of dynamic keyword. There is no need to define a POCO class. carlserver.com/blog/post/… Commented Dec 15, 2017 at 17:23
  • 2
    Just declare Token to be a JToken or JRaw. See Get Raw json string in Newtonsoft.Json Library. Commented Dec 15, 2017 at 17:25

1 Answer 1

8

Just read from Request.Body stream:

public async Task<IActionResult> ProcessPayment()
{
    using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
    {
            string rawValue = await reader.ReadToEndAsync();
    }
    ...
}

Updated: the following doesn't work with ASP.NET Core 2.0.

Actually, the string type for parameter should work if you post with Content-Type: application/json:

public async Task<IActionResult> ProcessPayment([FromBody] string transaction)
{
    ...
}

There is a good article about all these things: Accepting Raw Request Body Content in ASP.NET Core API Controllers

Sign up to request clarification or add additional context in comments.

4 Comments

The Content-Type is already set to application/json but for some reason, if I try to receive string, it's not working. I end up getting a null value in transaction parameter.
@Sam yeh, looks like the second option doesn't work with ASP.NET Core 2.0... Thought reading directly from Request.Body is working
I had to go back to the dynamic option. I then serialize the object using JsonConvert.SerializeObject(). Seems so unnecessary!
unncessary is the name of the game when it comes to .net core. Takes a week to just get to where express init starts you off.

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.