Web API C# - Returning full KVC Json - c#

I am using RestKit from an iOS app to connect to a Web API service that we are building in C# .Net 4.
I am having the same issue from here: RestKit non-kvc object mapping
Basically C# returns something like:
formatted raw
BODY
[
{
"Id":6,
"Guid":"00000000-0000-0000-0000-000000000000",
"Owner":null,
"Message":"Testing Wom#10",
"HashTags":null,
"createdtime":"2012-10-28T00:00:00",
"PlayedCount":100,
"DurationInSecs":150.0,
"FileSizeInBytes":20000,
"FileUrl":"http://www.wom.com"
}
]
While the standard format expected by RestKit is
{"woms": [
{
"Id":6,
"Guid":"00000000-0000-0000-0000-000000000000",
"Owner":null,
"Message":"Testing Wom#10",
"HashTags":null,
"createdtime":"2012-10-28T00:00:00",
"PlayedCount":100,
"DurationInSecs":150.0,
"FileSizeInBytes":20000,
"FileUrl":"http://www.wom.com"
}
]
I don't care using a way or another, however, it seems that it would be easier from the iOS side to make C# return the "customers" class name.
How can I tell C# to return that?
Thanks.
This is the current code in my ApiController in C#:
namespace WomWeb.Controllers.Apis
{
[Authorize]
public class WomsController : ApiController
{
private WomContext db = new WomContext();
// GET api/Woms
public IEnumerable<Wom> GetWoms()
{
return db.Woms.AsEnumerable();
}

I've had some issues like this when trying to serialize JSON in C#. I think the easiest way is wrap the customer in another class. If you only need to serialize in one place you can do something like var temp = new Object { customer customer = new customer(); } right before making the call to serialize it.

This is the best solution I have found so far. Basically replace the IEnumerable by HttpResponseMessage and use the Request.CreateResponse to respond (code below).
While it works it is less than ideal: I lose the abstraction, and now the controller respond with Json regardless of the request headers (that logic was resolved automatically, but when using the CreateResponse I am writing directly to the output).
// GET api/Woms
//public IEnumerable<Wom> GetWoms()
public HttpResponseMessage GetWoms()
{
//return db.Woms.Include("Owner").AsEnumerable();
return Request.CreateResponse(HttpStatusCode.OK, new { woms = Include("Owner").AsEnumerable() });
}

Related

Insert in DB a JSON object from a URL

I'm new to the REST API world. I explain my need: at a specific URL I have a raw JSON text, I would like this text to be acquired by my application and inserted later in the DB as a model I created previously through EF. C# NET-CORE 2.2.
if I wasn't clear enough, don't hesitate to ask me for more details.
Thanks in advance!
Edit:
I'm sorry if it' was unclear, I will provide more detail:
Actually, i have a JSON string downloaded from an url. I did it with the following code:
var client = new WebClient();
var jsonFull = client.DownloadString(string.Format("https://url"));
It's working fine. Now, I need to take from this string only a little part of the JSON, so i did:
using var jsonDoc = JsonDocument.Parse(jsonFull);
var jsonParsed = jsonDoc.RootElement;
var myCV = jsonParsed.GetProperty("cv");
CVE is an object of this JSON, and I succesfully take it.
Inside this object, there is another one called CV_data, so I extract this:
var myCVLE = myCV.GetProperty("CV_data_meta");
The result is a var with inside
ValueKind = Object : "{
"ID": "CV-2019",
"ASS": "cv#ms.org"
}"
Now, I have a class like that
public class CV_data_meta
{
[JsonPropertyName ("ID")]
public string ID { get; set; }
[JsonPropertyName("ASS")]
public string ASS { get; set; }
}
The question is: how i can put the value in the var myCVLE in the class CV_data_meta?
I tried with
var myCVClass = JsonSerializer.Deserialize<CV_data_meta>(myCVLE);
But I get an error.
Note: I can't deserialize all the string JSON into an object, because there are a lot of information that I don't need.
Thanks in advance all!
As I understand from your question, it follows:
You first need to create the JSON object mapping (class) that the API URL will return.
Then consume the API url like this:
var client = new WebClient();
var reply =
client.DownloadString(
string.Format("https://www.yourapi.com/yourpath?yourkey={0}", yourkey));
receive and map object with mapped class
var yourvar = JsonConvert.DeserializeObject<yourclass>(reply);
Now you have the API return mapped to a class in your application, you can do whatever you want with it, including saving to a database.

how to use the Permission helper intent from dialogflow in wehhook c#

I'm new to dialogflow and trying to use permission handler to ask for location permission using .NET core webapi. I've created intent, entities and event(google.assistent.permission) in dialogflow console. Now I want to send a request from my webapi to send the request to access location.
Can somebody please provide a code sample how to send request to access location from my webhook?
You need to include the helper intent DialogFlow JSON as part of the payload:
WebhookResponse response;
Struct payload;
response.Payload = payload;
Alternatively, it can be added as a fulfillment message with the payload type1.
The payload struct can be parsed from JSON:
response.Payload = Struct.Parser.ParseJson(#"{
""google"": {
""expectUserResponse"": true,
""systemIntent"": {
""intent"": ""actions.intent.PLACE"",
""data"": {
""#type"": ""type.googleapis.com/google.actions.v2.PlaceValueSpec"",
""dialogSpec"": {
""extension"": {
""#type"": ""type.googleapis.com/google.actions.v2.PlaceValueSpec.PlaceDialogSpec"",
""permissionContext"": ""To find a location"",
""requestPrompt"": ""Where would you like to go?""
}
}
}
}
}
}");
Or created using the Protobuf API (slightly faster due to skipping the parsing step and type safe, but incredibly ugly):
response.Payload = new Struct
{
Fields =
{
["google"] = Value.ForStruct(new Struct
{
Fields =
{
["expectUserResponse"] = Value.ForBool(true),
["systemIntent"] = Value.ForStruct(new Struct
{
// ... and so on
})
}
})
}
};
Keep in mind that including any message in the payload (which is necessary to call the helper) will override any other messages you added previously and ignore anything added afterwards (they are still part of the returned object, but stripped out by DialogFlow). That means: If you want any other rich response, it currently also needs to be manually added to the payload. At that point, you might as well create the entire JSON response from scratch.

Not able to fetch response from HttpClient POST method using Angular 7, .net core 2.2

I am creating quite basic implementation of CRUD methods using Angular and ASP.NET Core in the back end.
The back-end work perfectly, but cannot get the response after redirect action.
Let me bring the code:
the C# Controller bit:
[HttpPost]
[ProducesResponseType(200, Type = typeof(IActionResult))]
public async Task<ActionResult<CapCustomerResponseDto>> CreateCustomer([FromBody] CreateCustomerRequestDto request)
{
try
{
///. .. *creating command*
await _createCustomercommandHandler.Execute(command);
return CreatedAtRoute("GetCapCustomer", new { id = command.Id.ToString() }, command);
}
catch (Exception e)
{
// Some custom handling
}
}
So at the end we have the magical CreatedAtRoute() method, which redirects to the get controller
the Angular 7 httpClient implementation
addCustomer(customer): Observable<Customer> {
return this.http.post<Customer>(apiUrl, customer, httpOptions).pipe(
tap((customer: Customer) =>
console.log(`added customer w/ id=${customer.customerId}`)
),
catchError(this.handleError<Customer>("addCustomer"))
);
}
which actually returns nothing.
My customer is added properly, I can see it in the database. When using swagger, I can see the controllers working. Even in Network monitor.
but I have no clue how to retrieve the newly created customer response into my TS classes
Instead I get this:
Error: The requested path contains undefined segment at index 1
from Console
Question.
How can I make this work?

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?

Reading custom Content-Type (f.e. StackOverflow) feeds using HttpClient from WebAPI

I like a lot how the HttpClient is architectured - but I can't figure out how to add a "not quite standard" media type to be handled by the XmlSerializer.
This code:
var cli = new HttpClient();
cli
.GetAsync("http://stackoverflow.com/feeds/tag?tagnames=delphi&sort=newest")
.ContinueWith(task =>
{
task.Result.Content.ReadAsAsync<Feed>();
});
works fine when pointed to atom feeds that have Content-Type of "text/xml", but the one in the example fails with the "No 'MediaTypeFormatter' is available to read an object of type 'Feed' with the media type 'application/atom+xml'" message.
I tried different combinations of specifying MediaRangeMappings for the XmlMediaTypeFormatter (to be passed as an argument to ReadAsAsync) but with no success.
What is the "recommended" way to configure the HttpClient to map "application/atom+xml" and "application/rss+xml" to XmlSerializer?
Here is the code that works (credits to ASP.net forum thread):
public class AtomFormatter : XmlMediaTypeFormatter
{
public AtomFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/atom+xml"));
}
protected override bool CanReadType(Type type)
{
return base.CanReadType(type) || type == typeof(Feed);
}
}
var cli = new HttpClient();
cli
.GetAsync("http://stackoverflow.com/feeds/tag?tagnames=delphi&sort=newest")
.ContinueWith(task =>
{
task.Result.Content.ReadAsAsync<Feed>(new[] { new AtomFormatter });
});
Still, would like to see a solution without subclassing XmlMediaTypeFormatter - anybody?
The problem is that you are trying to convert the result straight to Feed. As error is clearly saying, it cannot figure our how to convert the application/atom+xml into Feed.
You would have to perhaps return as XML and then use and XmlReader to initialise your Feed.
Alternative is to provide your own media formatter - and implementation which encapsulates this.

Categories

Resources