Extracting values from an encoded post request - c#

At the moment my web app accepts post request fine. But I'm trying to read all the properties that are passed through to the object and then resend that object with a couple of properties changed. I'm having trouble viewing the object properties. Usual JSON objects are sent as a string and I can see all the properties that sent. Is there a way to see all the properties of an encoded JSON object?
I've tried examples from How to Get the HTTP Post data in C#?
public ActionResult Post(object value)
{
string[] keys = Request.Form.AllKeys;
for (int i= 0; i < keys.Length; i++)
{
Response.Write(keys[i] + ": " + Request.Form[keys[i]] + "<br>");
}
return new HttpStatusCodeResult(200);
}
But I get a compiler error indicating that HttpRequestMessage does not contain a definition for 'Form'.
I also tried Request.Form["payload"]; or Request["payload"] then i am presented with the error Cannot applying indexing to an expression of type 'HttpRequestMessage'
I would like to know the properties that are sent before I create the class. Do I have to create the class first then cast it to the object?

System.Web.HttpContext.Current.Request.Form
this can help you to access Form information in anywhere.
no matter ApiController or anything else
actually for webform and MvcController you can directly access Request.Form, but not in ApiController

Related

How to get the data from a selected value in a view .NET Core API?

I'm creating an application where the user can post information and see the information posted, something like a forum. I created a list where the publications stored in the database are shown, so on the main page that list is shown with the title, description, date, etc. of each publication. Now, what I'm trying to do is select anyone of the posts in the list and then display the full information of the selected post in other view. I'm using a MVC view with its respective controller to consume the API.
The code on the API controller to get the info of the selected post:
[HttpGet]
[Route("seePost")]
public IActionResult seePost([FromBody] int idSelPost)
{
PostContentModel post = new PostContentModel();
var postContent = db.Content.Find(idSelPost);
var postInfo = db.Forum.Find(idSelPost);
post.TittlePost = postInfo.TittlePost;
post.DescPost = postInfo.DescPost;
post.CreationDate = postInfo.CreationDate;
post.Content = postContent.Content;
return Ok(post);
}
With the code above I joining two different tables Content and Forum to return only a one model with the complete info of the post, to know what is the post selected the method receives an integer which is the id from the post selected displayed on the list. I've testing the method with Postman sending a number on a JSON file, but it appears that the JSON value could not converted to System.Int32:
{
"IdPost":6
}
Also, I have tried to do the same by creating a model class that only has an int variable to store the id of the selected post and pass it as a parameter to the model in the seePost method, but it gives me the "invalid name of column... " Sqlexception.
So, I don't know how to do this, any help is appreciated.
Routing
{
"IdPost":6
}
means that you need to accept an object with a property IdPost;
public class Post
{
public int IdPost {get;set;}
}
[HttpGet]
[Route("seePost")]
public IActionResult seePost([FromBody] Post post)
{
// TODO check if not null
var id = post.Id;
OR
Just send the number
6
OR
Send the id in the URL.
[HttpGet]
[Route("seePost/{idSellPost}")]
public IActionResult seePost(int idSelPost)
{
"invalid name of column... "
It seems that your model seems to out of sync with the database. You need to confirm that both Content and Forum models are mapped correctly.

Marketo - Response of Bulk API serialization

I'm trying to use the Bulk Import API endpoint within Marketo to fetch the warnings and failures associated with a bulk job I created within Marketo.
The output of these jobs is stated as an ObservableOfInputStreamContent, yet the response of these endpoints returns a csv string (with header column), that's not a JSON object. To compound to this problem, we are using the generated swagger files with the swagger definition file provided by Marketo. These generated c# client side files have the ObservableOfInputStreamContent object, but it's an empty object. I'm not sure if this is intended, or a mistake on Marketo's side. The generated files will attempt to use Newtonsoft.Json.JsonConvert.DeserializeObject<ObservableOfInputStreamContent>(responseText, JsonSerializerSettings); to deserialize the API response to the ObservableOfInputStreamContent.
Generated code that deserializes the API response:
var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responseText, JsonSerializerSettings);
return new ObjectResponseResult<T>(typedBody, responseText);
}
catch (Newtonsoft.Json.JsonException exception)
{
var message = "Could not deserialize the response body string as " + typeof(T).FullName + ".";
throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception);
}
Problem one is that the API does not return JSON to begin with (eg):
address,city,country,
123 lane, new york, USA
745 street, new york, USA
This call will return this error because of this:
Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: a. Path '', line 0, position 0.
The second issue is that ObservableOfInputStreamContent is defined as an empty object to begin with in the generated files. So if the API response was valid JSON, I don't think it would know how to convert to that empty ObservableOfInputStreamContent object. The good news about the generated code is that it gives me an option to extend the ObservableOfInputStreamContent because it's defined as a partial class.
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.1.11.0 (Newtonsoft.Json v11.0.0.0)")]
public partial class ObservableOfInputStreamContent
{
}
That said, is there any possible way I can use the JsonSerializerSettings to get around this issue? Could I extended the ObservableOfInputStreamContent class to hold a string property and then create my own JsonConverter to convert the string returned from the API into the new ObservableOfInputStreamContent?

Getting exception while retrieving data from POST method?

I am getting an exception while reading the post data.
I get error on this line:
HttpContext.Current.Request.Form["UserID"].ToString();
And the error is :
System.Collections.Specialized.NameValueCollection.this[string].get
returned null.
In method I have put this code :
StreamReader reader = new StreamReader(HttpContext.Current.Request.InputStream);
string requestFromPost = reader.ReadToEnd();
and data comes in that properly like this:
{
"UserID": "1000",
"Password": "ABCD"
}
Why I am not getting value in this HttpContext.Current.Request.Form["UserID"].ToString()? I also tried Request.QueryString but no success here.
Where am I doing wrong? Any help or suggestion would be much appreciated. Thanks!
There is no Form on this request. For a request body to be interpreted as form data, it must:
have a content type of x-www-form-urlencoded
be actually formatted as form encoded values, i.e. UserID=foo&Password=bar
JSON content is JSON, it will not be interpreted as form-data.
Web API should already take care of this for you. Given an action method:
public void Action(Credentials credentials)
where the Credentials class looks something like:
public class Credentials
{
string UserID { get; set;}
string Password { get; set; }
}
You shouldn't have to do anything else to have the framework turn this incoming JSON data into an instance of Credentials and pass it to the action method. This is automatic unless you've done something strange that breaks the conventions that WebAPI expects.

Getting POST data from WebAPI

We're working on developing an application that uses Plivo for sending and receiving SMS messages. For every request that Plivo sends, they also send a signature in the HTTP header so that we can verify the request came from Plivo and not from a random user.
https://www.plivo.com/docs/xml/request/#validation
To do this validation, we require the POST content as a query string (eg: To=15555555555&From=11234567890&TotalRate=0&Units=1&Text=Text!&TotalAmount=0&Type=sms&MessageUUID=2be622bc-79f8-11e6-8dc0-06435fceaad7).
Current solution
This is what we have so far:
private bool VerifyPlivo(object thing, HttpRequestMessage Request)
{
if (Request.Headers.Contains("X-Plivo-Signature"))
{
Dictionary<string, string> reqParams = (from x in thing.GetType().GetProperties() select x).ToDictionary(x => x.Name, x => (x.GetGetMethod().Invoke(thing, null) == null ? "" : x.GetGetMethod().Invoke(thing, null).ToString()));
IEnumerable<string> headerValues = Request.Headers.GetValues("X-Plivo-Signature");
string signature = headerValues.FirstOrDefault();
return XPlivoSignature.Verify(Request.RequestUri.ToString(), reqParams, signature, plivoToken);
}
else
{
return false;
}
}
[Route("RecieveSMS")]
[HttpPost]
public HttpResponseMessage RecieveSMS(PlivoRecieveSMS req)
{
if (!VerifyPlivo(req, Request))
{
return new HttpResponseMessage(HttpStatusCode.Forbidden);
}
... // do actual work here
}
This works by using the object that it maps to PlivoRecieveSMS and doing some reflection to get the properties and values, and sticking them in a Dictionary. This works well especially given our lack of the preferred solution...
Preferred solution
Right now, we require a model (PlivoRecieveSMS) to map the data, and then do introspection to find the key/values. We would like to move the logic to an extension of System.Web.Http.AuthorizeAttribute, so that we can do something as simple as:
[AuthorizedPlivoApi]
[Route("RecieveSMS")]
[HttpPost]
public HttpResponseMessage RecieveSMS(PlivoRecieveSMS req)
{
... // do actual work here
}
The actual authorization is done in AuthorizedPlivoApi - if it's not valid, the request never reaches the controller. But we cannot do this at the moment because we can't map it to a specific object inside of AuthorizedPlivoApi.
I would like to access the POST key's / values directly, or perhaps map it to a dynamic object that isn't pre-defined before hand. If I can do that, we can then achieve our preferred solution.
tl;dr: is there any way to push application/x-www-form-urlencoded data from a POST request into a Dictionary<string,string>() without using a specific model?

Post request with query string parameters

I'm trying to build a Web API for a complex type of searching. I want to support paging in the results. The "state" of the search is complex, so not really suitable for persisting in the query string. But I'd like for the paging options to be included within the query string.
I've implemented two methods, as below, and the web api code seems to understand what I'm trying to do, but the query string parameters never get assigned. Any hints or advice on this would be appreciated:
public Task<HttpResponseMessage<SearchResults>> Post(SearchRequest request) //Method 1
{
return Post(request, null, null);
}
public async Task<HttpResponseMessage<SearchResults>> Post(SearchRequest request, string page, string pageSize) //Method 2
{
//All of the complex code, including...
if (PageNo < TotalPages)
{
searchResults.AddLink(new Link { Uri = Url.Route("DefaultApi", new {
controller = "AdvancedSearch",
page = (PageNo + 1).ToString(),
pageSize = PageSize.ToString() }),
Relation = "nextPost" });
}
//Final wrap up, etc
}
On POSTing a SearchRequest to /api/AdvancedSearch, Method 1 is called, which in turn calls Method 2, which does the search, and packages up the results. As you can hopefully see, included in this result (if more pages of results are available) is a URL to post to for the next page. The generated URL base on this is /api/AdvancedSearch?page=2&pageSize=20, exactly as I'd hoped.
In my calling code, I then perform a POST to this second URL. Only Method 2 is invoked (as expected). But, both page and pageSize are null.
What am I doing wrong? Or what else do you need to see in order to answer this question?
Below is not needed
You need to decorate your parameters using [FromUri]:
public async Task<HttpResponseMessage<SearchResults>> Post(SearchRequest request,
[FromUri]string page,
[FromUri]string pageSize)
As I said in the comments, HttpResponseMessage<T> is being dropped since the Content property of HttpResponseMessage will perform all needed operations.
I checked and I passed querystring params in a post, no problem.

Categories

Resources