Compare the Hash of a JSON object - c#

I am attempting to get a hash comparer to work so I can validate an incoming request.
Flow:
Sender creates json object -> sender creates hash of json object with a key that they and I know -> sender sends json object and header with hash in it -> I recieve request -> I hash the json object with the common key -> I compare my hash to the one in the header to validate user sending it
I am struggling to create a hash from my json object.
This is the example code in Ruby (from the sender) where request_payload is JSON object.
hmac=OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'),YOUR_COMPANY_SIGNING_KEY,request_payload)
signature = Base64.strict_encode64(hmac)
I want to do this in C#.
I am using the data from the Call Rail API (see right side) and attempting to hash it into string and then encode it.
[HttpPost]
public async Task<ActionResult> PostAsync(dynamic request)
{
string signature = GetHash(request.ToString(), "072e77e426f92738a72fe23c4d1953b4"); // this key is from the example in Call Rail
string encodedSignature = Base64Encode(signature);
return Ok();
}
public static String GetHash(dynamic text, String key)
{
ASCIIEncoding encoding = new ASCIIEncoding();
Byte[] textBytes = encoding.GetBytes(text);
Byte[] keyBytes = encoding.GetBytes(key);
Byte[] hashBytes;
using (HMACSHA1 hash = new HMACSHA1(keyBytes))
hashBytes = hash.ComputeHash(textBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
I think where I am struggling is how I can take my incoming JSON
{"answered":false,"business_phone_number":"","call_type":"voicemail","company_id":155920786,"company_name":"Boost Marketing","company_time_zone":"America/Los_Angeles","created_at":"2018-02-19T13:41:00.252-05:00","customer_city":"Rochester","customer_country":"US","customer_name":"Kaylah Mills","customer_phone_number":"+12148654559","customer_state":"PA","device_type":"","direction":"inbound","duration":"13","first_call":false,"formatted_call_type":"Voicemail","formatted_customer_location":"Rochester, PA","formatted_business_phone_number":"","formatted_customer_name":"Kaylah Mills","prior_calls":16,"formatted_customer_name_or_phone_number":"Kaylah Mills","formatted_customer_phone_number":"214-865-4559","formatted_duration":"13s","formatted_tracking_phone_number":"404-555-8514","formatted_tracking_source":"Google Paid","formatted_value":"--","good_lead_call_id":715587840,"good_lead_call_time":"2016-06-17T10:23:33.363-04:00","id":766970532,"lead_status":"previously_marked_good_lead","note":"","recording":"https://app.callrail.com/calls/766970532/recording/redirect?access_key=aaaaccccddddeeee","recording_duration":8,"source_name":"Google AdWords","start_time":"2018-02-19T13:41:00.236-05:00","tags":[],"total_calls":17,"tracking_phone_number":"+14045558514","transcription":"","value":"","voicemail":true,"tracker_id":354024023,"keywords":"","medium":"","referring_url":"","landing_page_url":"","last_requested_url":"","referrer_domain":"","conversational_transcript":"","utm_source":"google","utm_medium":"cpc","utm_term":"","utm_content":"","utm_campaign":"Google AdWords","utma":"","utmb":"","utmc":"","utmv":"","utmz":"","ga":"","gclid":"","integration_data":[{"integration":"Webhooks","data":null}],"keywords_spotted":"","recording_player":"https://app.callrail.com/calls/766970532/recording?access_key=aaaabbbbccccdddd","speaker_percent":"","call_highlights":[],"callercity":"Rochester","callercountry":"US","callername":"Kaylah Mills","callernum":"+12148654559","callerstate":"PA","callsource":"google_paid","campaign":"","custom":"","datetime":"2018-02-19 18:41:00","destinationnum":"","ip":"","kissmetrics_id":"","landingpage":"","referrer":"","referrermedium":"","score":1,"tag":"","trackingnum":"+14045558514","timestamp":"2018-02-19T13:41:00.236-05:00"}
And then be able to Hash it into something useful.
With the test signing key I am given, I should get back UZAHbUdfm3GqL7qzilGozGzWV64=. I know this from the APIDocs.
I am currently sending up the JSON string above via postman but I notice that extra '{ }' are added on when I treat it as datatype dynamic or object.
Any insight would be greatly appreciated!

I think the problem you are facing is that the .NET Core WebAPI is helpfully parsing the body into JSON (into a JObject) for you.
As #dbc identified, really what you need is the raw string body to use to generate the HMAC Signature, which you can verify before parsing the body into JSON yourself.
I tested This answer and was able to receive the body as a plain string:
using System;
using System.Linq;
using System.Threading.Tasks;
using System.IO;
using Microsoft.AspNetCore.Mvc.Formatters;
namespace netcoretest {
public class RawJsonBodyInputFormatter : InputFormatter
{
public RawJsonBodyInputFormatter()
{
this.SupportedMediaTypes.Add("application/json");
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
var request = context.HttpContext.Request;
using (var reader = new StreamReader(request.Body))
{
var content = await reader.ReadToEndAsync();
return await InputFormatterResult.SuccessAsync(content);
}
}
protected override bool CanReadType(Type type)
{
return type == typeof(string);
}
}
}
in Startup.cs:
// in ConfigureServices()
services.AddMvc(options => {
options.InputFormatters.Insert(0, new RawJsonBodyInputFormatter());
});
In your controller:
[HttpPost]
public async Task<ActionResult> PostTest([FromBody]string request)
{
// here request is now the request body as a plain string;
// you can now compute the signature on it and then later parse it to JSON.
}
However, testing your current code to generate the Base64-encoded signature, I am not getting the correct signature:
you are converting the output of the HMAC to hexadecimal string, and then taking the bytes of that string and putting those into your Base64 encoding. The sample ruby you linked returns plain bytes, not a hexadecimal string from HMAC.digest:
[5] pry(main)> hmac = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), YOUR_COMPANY_SIGNING_KEY, s)
=> "Q\x90\amG_\x9Bq\xAA/\xBA\xB3\x8AQ\xA8\xCCl\xD6W\xAE"
So at least that portion needs to be corrected in your implementation as well.
Update
I was able to get the correct signature with the following code:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System;
using System.Security.Cryptography;
using System.Text;
namespace netcoretest.Controllers
{
[Route("test")]
[ApiController]
public class TestController : ControllerBase
{
public TestController()
{
}
// POST: /test
[HttpPost]
public async Task<ActionResult> PostTest([FromBody]string request)
{
ASCIIEncoding encoding = new ASCIIEncoding();
Byte[] key = encoding.GetBytes("072e77e426f92738a72fe23c4d1953b4");
HMACSHA1 hmac = new HMACSHA1(key);
Byte[] bytes = hmac.ComputeHash(encoding.GetBytes(request));
Console.WriteLine(ByteArrayToString(bytes));
String result = System.Convert.ToBase64String(bytes);
Console.WriteLine(result);
return Ok();
}
public static string ByteArrayToString(byte[] ba)
{
return BitConverter.ToString(ba).Replace("-","");
}
}
}
I tested posting to this endpoint using the following:
url --request POST https://localhost:5001/test --insecure --header 'Content-Type: application/json' --data-binary #test.json
where test.json is the sample JSON blob from the API Documentation.
If using this same code you cannot get the signature to match, double check that your test.json does not have any trailing newlines or whitespace.
Hope this helps!

Though #john_Ledbetter 's answer works great, I decided an action filter fit me better. So I used his answer as a base and modified it for me. I don't believe this solution would need the InputFormatter
ValidateCallRailRequestFiler.cs
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace My_API.ActionFilters
{
public class ValidateCallRailRequestFilter: ActionFilterAttribute
{
//private readonly ILogger<ValidateCallRailRequestFilter> _logger;
//public ValidateCallRailRequestFilter(ILogger<ValidateCallRailRequestFilter> logger)
//{
// _logger = logger;
//}
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
//executing before action is called
// this should only return one object since that is all an API allows. Also, it should send something else it will be a bad request
var param = actionContext.ActionArguments.SingleOrDefault();
if (param.Value == null)
{
//_logger.LogError("Object sent was null. Caught in ValidateCallRailRequestFilter class.");
actionContext.Result = new BadRequestObjectResult("Object sent is null");
return;
}
var context = actionContext.HttpContext;
if (!IsValidRequest(context.Request))
{
actionContext.Result = new ForbidResult();
return;
}
base.OnActionExecuting(actionContext);
}
private static bool IsValidRequest(HttpRequest request)
{
string json = GetRawBodyString(request.HttpContext);
string token = "072e77e426f92738a72fe23c4d1953b4"; // this is the token that the API (Call Rail) would provide
string signature = request.Headers["Signature"];
// validation for comparing encoding to bytes and hashing to be the same
//https://rextester.com/EBR67249
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] key = encoding.GetBytes(token);
HMACSHA1 hmac = new HMACSHA1(key);
byte[] bytes = hmac.ComputeHash(encoding.GetBytes(json));
string result = System.Convert.ToBase64String(bytes);
return signature.Equals(result, StringComparison.OrdinalIgnoreCase);
}
public static string GetRawBodyString(HttpContext httpContext)
{
var body = "";
if (httpContext.Request.ContentLength == null || !(httpContext.Request.ContentLength > 0) ||
!httpContext.Request.Body.CanSeek) return body;
httpContext.Request.EnableRewind();
httpContext.Request.Body.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(httpContext.Request.Body, System.Text.Encoding.UTF8, true, 1024, true))
{
body = reader.ReadToEnd();
}
httpContext.Request.Body.Position = 0;
return body;
}
}
}
This includes a body reader that reads in the JSON and a way to deny incoming requests that don't match the signature as 403 forbidden.
Then within my controller:
[ValidateCallRailRequestFilter]
[HttpPost]
public async Task<ActionResult> PostAsync(dynamic request)
{
...
return Ok();
}
with a using My_Api.ActionFilters;
And then I hit it with postman.

Related

net5.0 - Error receiving diferent size of byte array between Microservices

I have 2 Microservices (In a simple way to share it), here's the code from the "source" Microservice
[HttpGet]
[Route("resource")]
public async Task<byte[]> LocateResource(Guid Id)
{
if (Id== Guid.Empty)
{
throw new Exception("Invalid Id");
}
var (content, message) = await _repo.LocateResource(Id);
if (!message.Equals("Success"))
{
throw new Exception(message);
}
// content.lenght equivalent to 56129
return content;
}
and then Here is the code for the "Client"
public async Task<byte[]> ReadFile(Guid Id)
{
var response = await _httpClient.GetAsync($"{_urlOptions.Value.ReadFileEndpoint}?Id={Id}");
response.EnsureSuccessStatusCode();
var file = await response.Content.ReadAsByteAsync();
// file.lenght equivalent to 74000
return file;
}
The problem is that I'm sending 56129 bytes and I'm receiving 74000 bytes in the "Client", and it looks like there is no explanation for this behavior. Can someone give me further details, please?
You should return response of type FileContentResult. For example:
using Microsoft.AspNetCore.Mvc;
namespace WebApplication2.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet("file")]
public IActionResult GetFile()
{
var result = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
return this.File(result, "application/octet-stream");
}
}
}
File is a helper method defined in ControllerBase class.
By default ASP.NET serializes content to JSON and binary data is encoded using base64. That's why you get bigger response then you expect. The result from my example looks like this when encoded and serialized: "AQIDBAUGBw==".
ReadAsByteAsync actually exist in HttpContent.
I suggest you have a custom response class that handles conversion

HttpClient Post Call

i want to do a REST POST call, using HttpClient.I keep having error - 'RestCall.PostRestCall(string, string, string, string)': not all code paths return a value'
Below is my Code. Its meant to receive baseUrl, contentType, requestBody, httpMethod; as input parameter and return the response status code, status description and response content.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace RestPostCall
{
public class RestCall
{
public static string PostRestCall(string baseURL, string httpMethod, string contentType, string requestBody)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(baseURL);
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue(contentType));
// List data response.
HttpResponseMessage response = client.GetAsync(requestBody).Result;
if (response.IsSuccessStatusCode)
{
// Parse the response body.
var dataObjects = response.Content.ReadAsAsync<IEnumerable<IDataObject>>().Result;
//Make sure to add a reference to System.Net.Http.Formatting.dll
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
//Make any other calls using HttpClient here.
//Dispose once all HttpClient calls are complete.
client.Dispose();
}
}
}
You method does not return any value, so change signature to return void type:
public static void PostRestCall(string baseURL, string httpMethod, string contentType,
string requestBody)
Change your method return type to void or if you want to return any value use return statement.

WebSocket API for Bitfinex by C# code

I take data from Bittrex without WebSocket by this way
request = WebRequest.Create("https://bittrex.com/api/v1.1/public/getticker?market=USDT-BTC");
request.Credentials = CredentialCache.DefaultCredentials;
response = (HttpWebResponse)request.GetResponse();
dataStream = response.GetResponseStream();
reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
response.Close();
date = JsonConvert.DeserializeObject(responseFromServer);
It is very easy way and it is working on Bittrex. But I did a lot off request. I need do it on Bitfinex but I have the exeption "Too many request". As I understood I need WebSocket for this. By this adress https://api.bitfinex.com/v1/pubticker/BTCUSD. Somebody can show easy code to understand how I need to conect and write in Console info from WebSocket. Thanks!
BIttrex release in March beta version of new site and WebSocket. GitHub repository have samples for usage WebSocket channel to subscribe for events.
Here is C# example:
using System;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using Microsoft.AspNet.SignalR.Client;
namespace WebsocketSample
{
public sealed class BittrexWebsocket
{
public delegate void BittrexCallback(string info);
private HubConnection _hubConnection { get; }
private IHubProxy _hubProxy { get; }
private BittrexCallback _updateExchangeState { get; }
private BittrexCallback _updateOrderState { get; }
private BittrexCallback _updateBalanceState { get; }
public BittrexWebsocket(
string connectionUrl,
BittrexCallback updateExchangeState,
BittrexCallback updateOrderState,
BittrexCallback updateBalanceState
)
{
// Set delegates
_updateExchangeState = updateExchangeState;
_updateOrderState = updateOrderState;
_updateBalanceState = updateBalanceState;
// Create connection to c2 SignalR hub
_hubConnection = new HubConnection(connectionUrl);
_hubProxy = _hubConnection.CreateHubProxy("c2");
// Register callback for uE (exchange state delta) events
_hubProxy.On(
"uE",
exchangeStateDelta => _updateExchangeState?.Invoke(exchangeStateDelta)
);
// Register callback for uO (order status change) events
_hubProxy.On(
"uO",
orderStateDelta => _updateOrderState?.Invoke(orderStateDelta)
);
// Register callback for uB (balance status change) events
_hubProxy.On(
"uB",
balanceStateDelta => _updateBalanceState?.Invoke(balanceStateDelta)
);
_hubConnection.Start().Wait();
}
public void Shutdown() => _hubConnection.Stop();
// marketName example: "BTC-LTC"
public async Task<bool> SubscribeToExchangeDeltas(string marketName) => await _hubProxy.Invoke<bool>("SubscribeToExchangeDeltas", marketName);
// The return of GetAuthContext is a challenge string. Call CreateSignature(apiSecret, challenge)
// for the response to the challenge, and pass it to Authenticate().
public async Task<string> GetAuthContext(string apiKey) => await _hubProxy.Invoke<string>("GetAuthContext", apiKey);
public async Task<bool> Authenticate(string apiKey, string signedChallenge) => await _hubProxy.Invoke<bool>("Authenticate", apiKey, signedChallenge);
// Decode converts Bittrex CoreHub2 socket wire protocol data into JSON.
// Data goes from base64 encoded to gzip (byte[]) to minifed JSON.
public static string Decode(string wireData)
{
// Step 1: Base64 decode the wire data into a gzip blob
byte[] gzipData = Convert.FromBase64String(wireData);
// Step 2: Decompress gzip blob into minified JSON
using (var decompressedStream = new MemoryStream())
using (var compressedStream = new MemoryStream(gzipData))
using (var deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress))
{
deflateStream.CopyTo(decompressedStream);
decompressedStream.Position = 0;
using (var streamReader = new StreamReader(decompressedStream))
{
return streamReader.ReadToEnd();
}
}
}
public static string CreateSignature(string apiSecret, string challenge)
{
// Get hash by using apiSecret as key, and challenge as data
var hmacSha512 = new HMACSHA512(Encoding.ASCII.GetBytes(apiSecret));
var hash = hmacSha512.ComputeHash(Encoding.ASCII.GetBytes(challenge));
return BitConverter.ToString(hash).Replace("-", string.Empty);
}
}
class Program
{
static public BittrexWebsocket.BittrexCallback CreateCallback(string name)
{
//
// In a real app, your code would do something useful based on the
// information accompanying each event.
//
return (info) =>
{
Console.WriteLine($"Callback Invoked: {name}");
Console.WriteLine(
BittrexWebsocket.Decode(info)
);
};
}
static void Main(string[] args)
{
Task task = Task.Run(
async () =>
{
string apiKey = "YOUR_API_KEY";
string apiSecret = "YOUR_API_SECRET";
string baseUrl = "https://beta.bittrex.com/signalr";
var btx = new BittrexWebsocket(
baseUrl,
CreateCallback("exchange"),
CreateCallback("order"),
CreateCallback("balance")
);
// If we successfully authenticate, we'll be subscribed to the uO and uB events.
var isAuthenticated = await btx.Authenticate(
apiKey,
BittrexWebsocket.CreateSignature(apiSecret, await btx.GetAuthContext(apiKey))
);
// Register for orderbook updates on the BTC-ETH market
await btx.SubscribeToExchangeDeltas("BTC-ETH");
});
task.Wait();
Console.WriteLine("Press enter to exit sample...");
Console.ReadLine();
}
}
}
Run in PackageManager Console to add SignalR dependency:
Install-Package Microsoft.AspNet.SignalR.Client -Version 2.3.0
Also to connect you need get Key and Secret from your account on Bittrex.
string apiKey = "YOUR_API_KEY";
string apiSecret = "YOUR_API_SECRET";
For Bitfinex you can try next code:
using System;
using WebSocketSharp;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
using (var ws = new WebSocket("wss://api.bitfinex.com/ws/2"))
{
ws.OnMessage += (sender, e) => Console.WriteLine(e.Data);
ws.Connect();
ws.Send("{\"event\":\"subscribe\", \"channel\":\"ticker\", \"pair\":\"BTCUSD\"}");
Console.ReadKey(true);
}
}
}
}
Requires dependency from Nuget:
Install-Package WebSocketSharp-NonPreRelease -Version 1.0.0

Invalid ModelState, HTTP 400 Bad Request for JSON Array Sent to C# Web API Controller

In a C# Web API, I am trying to accept a POST request that contains a JSON array. I want to deserialize the JSON array to a LIST or ILIST of RegisterBindingModel class objects. Then, in the controller actions, I will iterate over the list and perform the desired action.
I am using essentially the stock ASP.NET 5 Web Application template in Visual Studio 2015. I have added a RegisterList method on the Account controller.
Separately, I have created a Web client in a C# console application. The client sends a POST request that contains a JSON array.
The response I get is always 400 - Bad Request.
Am I supposed to deserialize the JSON array to an ILIST or LIST in the RegisterList method signature? I've tried to use JsonConverter.DeserializeObject, but IntelliSenese says that the type name DeserializeObject does not exist in type JsonConverter.
The API documentation that generates with the Visual Studio template indicates that the client's JSON array is formatted correctly.
The following is the code for the RegisterList method:
// POST api/Account/RegisterList
[AllowAnonymous]
[Route("RegisterList")]
public async Task<IHttpActionResult> RegisterList(List<RegisterBindingModel> modelList)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
foreach (RegisterBindingModel model in modelList)
{
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
}
return Ok();
}
The following is the code for the client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using Web_Client_Register_Account;
using Newtonsoft.Json;
namespace Web_Client_Register_Account
{
class Program
{
static void Main(string[] args)
{
RunAsync().Wait();
}
static async Task RunAsync()
{
using (var client = new HttpClient())
{
Console.WriteLine("Hit any key");
Console.ReadLine();
client.BaseAddress = new Uri("http://localhost:9000/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var registrations = new List<Registration> { new Registration { Email = "orc#coast2coast.net", Password = "Secrets1!", ConfirmPassword = "Secrets1!" }, new Registration { Email = "gargoyle#coast2coast.net", Password = "Secrets1!", ConfirmPassword = "Secrets1!" }, new Registration { Email = "elf#coast2coast.net", Password = "Secrets1!", ConfirmPassword = "Secrets1!" }, new Registration { Email = "ranger#coast2coast.net", Password = "Secrets1!", ConfirmPassword = "Secrets1!" } };
//HTTP Post - A JSON List in a Single POST
var registration_manifest = JsonConvert.SerializeObject(registrations);
Console.ReadLine();
HttpResponseMessage response = await client.PostAsJsonAsync("api/Account/RegisterList", registration_manifest);
if (response.IsSuccessStatusCode)
{
Uri registrantUrl = response.Headers.Location;
Console.WriteLine(registrantUrl);
Console.ReadLine();
}
Console.WriteLine(response);
Console.ReadLine();
}
}
}
}
HttpClient.PostAsJsonAsync already encodes to JSON, so skip the JsonConvert.SerializeObject and just
HttpResponseMessage response = await client.PostAsJsonAsync("api/Account/RegisterList",
registrations);

POST throws HttpRequestMessage does not contain a definition for Form

I am trying to get POST data in C# and everything I have read says to use
Request.Form["parameterNameHere"]
I am trying that, but I get an error saying
System.Net.Http.HttpRequestMessage does not contain a definition for Form and no extension method for Form.'
The method in question is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.HttpRequest;
namespace TextServer.Controllers
{
public class TextController : ApiController
{
// POST api/<controller>
public HttpResponseMessage Post([FromBody]string value)
{
string val = Request.Form["test"];
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new StringContent("Your message to me was: " + value);
return response;
}
Any help is greatly appreciated.
You should pass your object in the request body and retrieve values from the body:
public HttpResponseMessage Post([FromBody] SomeModel model)
{
var value = model.SomeValue;
...
Or if all you need is the string:
public HttpResponseMessage Post([FromBody] string value)
{
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new StringContent("Your message to me was: " + value);
return response;
}

Categories