receiving a json string in C# Web Api 2 - c#

I'm trying to do a patch with web api. I keep getting NULL for my json. Please Help
Here is my Json
[{"PartNumber":"AN33016UA-VB"}{"Category":"Chassis"}]
Here is my my class
public class wsCategory
{
public string PartNumber { get; set; }
public string Category { get; set; }
}
Here is my Api Controller
[HttpPatch]
[ActionName("IMDSCategory")]
public HttpResponseMessage IMDSCategory([FromBody]wsCategory jsonbody)
{
var data = jsonbody.PartNumber;
return new HttpResponseMessage(HttpStatusCode.Created);
}

The JSON is inavalid.
[{"PartNumber":"blahblah","Category":"Chassis"}]
I believe the array container will be parsed out correctly, but I'm on a chromebook right now, so I can't check that. If it still fails, drop the [].

based on your method
[HttpPatch]
[ActionName("IMDSCategory")]
public HttpResponseMessage IMDSCategory([FromBody]wsCategory jsonbody){...}
Your JSON is invalid given the model you are trying to parse.
[{"PartNumber":"AN33016UA-VB"}{"Category":"Chassis"}]
should be
{"PartNumber":"AN33016UA-VB","Category":"Chassis"}

Related

How to create a POST with form-data for an API endpoint that accepts a list of files inside a list of objects?

I am trying to create a request in postman to upload files to a dotnet core endpoint that expects the following shape:
public class MyDto
{
public DateTime Time { get; set; }
public List<Logs> Files { get; set; } = null!;
public class Logs
{
public ServiceEnum Service { get; set; }
public List<IFormFile> LogFiles { get; set; }
}
}
Function signature of action:
[HttpPost("{​id}​/log")]
public async Task<ActionResult> SaveLogs([FromRoute] string id, [FromForm] MyDto myDto)
My postman request looks like this:
When I try debugging this I can see that myDto.Files[0].Service is set yet, myDto.Files[0].LogFiles in null.
I was expecting that uploading multiple files would be mapped into myDto.Files[0].LogFiles from the request. I might be formatting the keys in the request wrong but I have tried multiple different key formats at this point.
I test with other simple and complex types, they can use square brackets and post successfully(Except for IFormFile). Maybe it is by design in Postman. Any way, no matter what type it is. You can always post like xx.xx.xx.
Change your post data like below:

Converting a JSON into own type results in null objects

from my rest call, I am receiving this JSON:
{
"livemode": true,
"error": {
"type": "unauthorized",
"message": "You did not provide a valid API key."
}
}
I need to fetch type and message into my type:
public class TestObject
{
string type { get; set; }
string message { get; set; }
}
But this returns null objects:
HttpClient client = new HttpClient();
Uri uri = new Uri("https://api.onlinebetaalplatform.nl/v1");
HttpResponseMessage response = await client.GetAsync(uri);
string content = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(content);
TestObject album = json.ToObject<TestObject>();
1.) I understand that the type and message attributes are "nested". How do I access them?
2.) Even if I call my type livemode and error, the objects still return null.
Can you help me out a little?
Thank you :)
There seems to be one set of curly brackets to many. I am pretty sure that the api you are querying is not returning the first and the last curly bracket. Continue on after that has been taken care of.
In order to fetch the data, add these class definitions
public class Error
{
public string type { get; set; }
public string message { get; set; }
}
public class Root
{
public bool livemode { get; set; }
public Error error { get; set; }
}
and change
TestObject album = json.ToObject<TestObject>();
To
Root album = json.ToObject<Root>();
As some of the comments to your question mentioned, you are currently trying to convert the JSON string to the nested Error object instead of the root object, where the Error object is located.
In the future, there are tools that can generate C# classes from JSON. I used https://json2csharp.com/ this time around to do so.
EDIT:
I just found out that Visual Studio actually has an in-built JSON to Class feature!

consume JSON from webhook in C#

Hi I'm looking to create a simple webhook receiver and dump the data into a table.
This is for receiving SMS using Zipwhip. Zipwhip will send a post with JSON.
Need to receive the JSON and process.
What is a simple way to accomplish this.
Thanks in advance.
In ServiceStack your callback would just need to match the shape of your Response DTO, e.g:
[Route("/path/to/callback")]
public class CorpNotes
{
public int Departments { get; set; }
public string Note { get; set; }
public DateTime WeekEnding { get; set; }
}
// Example of OrmLite POCO Data Model
public class MyTable {}
public class MyServices : Service
{
public object Any(CorpNotes request)
{
//...
Db.Insert(request.ConvertTo<MyTable>());
}
}
Example uses Auto Mapping Utils to populate your OrmLite POCO datamodel, you may want to do additional processing before saving the data model.
If the callback can send arbitrary JSON Responses in the payload you can use an object property to accept arbitrary JSON however we'd recommend using Typed DTOs wherever possible.
This can be what the receiving method in your controller can look like on the receiving side. Make sure that your receiving and sending json object match.
[HttpPost]
[Route("Edit")]
public JsonResult Edit([FromBody] CorpNotes newMessage)
{return Json(TotalWeekNoteSearch);}
public class CorpNotes
{
public int Departments { get; set; }
public string Note { get; set; }
public DateTime WeekEnding { get; set; }
}
I am actually working on a .net project receiving Json from a Angular front end, so this should be the same concept. Also make sure that what you are receiving is truly a workable object such as.
{Departments: 4, Note: "This is notes 2020Q1W13", WeekEnding: "2020-01-25T00:00:00"}
Also try looking into this example which would be helpful in regards to webhooks.
public class MyWebHookHandler : WebHookHandler
{
public MyWebHookHandler()
{
this.Receiver = "custom";
}
public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
CustomNotifications notifications = context.GetDataOrDefault<CustomNotifications>();
foreach (var notification in notifications.Notifications)
{
...
}
return Task.FromResult(true);
}
}
The type of the data is typically JSON or HTML form data, but it is possible to cast to a more specific type if desired.

Post a collection to ASP.NET WEB API

How should I post a collection of objects to a WEB API Rest service?
This is what I have in my Rest service..
I am using XmlSerializer
Here is the ActionMethod
public class DevicesController : ApiController
{
[HttpPost]
public void PushToDb([FromBody] device[] devices)
{
var iCount = devices.Count();
...
...
}
Here is the device DTO:
public class device
{
public string serialnumber { get; set; }
public string hw_part_id { get; set; }
}
Here is the Request:
http://localhost:50384/api/Devices/PushToDb
And the XML input
<devices>
<device
<serialnumber>1</serialnumber>
<hw_part_id>A</hw_part_id>
</device>
<device>
<serialnumber>2</serialnumber>
<hw_part_id>A</hw_part_id>
</device>
</devices>
Content-Type is set as application/xml.
When I send this Post request, devices is always null. But if I change the Action method to just accept one device, I am able to receive the device data in the Action method.
Only when I am passing a collection I am not able to receive the input in the Action method.
Am I missing something? What should I do to be able to post a collection (XML input) to ASP.NET Rest service?
Thanks in advance.
Rag
As said in the comment decorate your class this way
[DataContract]
public class device
{
[DataMember]
public string serialnumber { get; set; }
[DataMember]
public string hw_part_id { get; set; }
}
Then use newtonsoft (or any other library) to serialize an array of device type to json. and use System.Net.WebClient this way:
using (WebClient client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/json";
var jsonObj = JsonConvert.SerializeObject(yourArray); //yourArray is a device[]
client.UploadString(ApiServiceUrl, jsonObj);
}
dear take a small break from work and watch this MVA Course, it will definitely solve your problem
https://www.microsoftvirtualacademy.com/en-us/training-courses/web-api-design-jump-start-8689?l=BMxSvaH1_3804984382
thank you

RESTAPI body parameters are passed null when calling in c#

I am trying to call a rest api method from c#. Problem is for all content types it passes null to body parameter.I shared my code below.Apart from this code I have tried to write body parameter to request as stream.It didn't work either. I have also tried 'application/x-www-form-urlencoded' as content type.
Calling rest api method from c# sample:
string token = Server.UrlEncode("v0WE/49uN1/voNwVA1Mb0MiMrMHjFunE2KgH3keKlIqei3b77BzTmsk9OIREken1hO9guP3qd4ipCBQeBO4jiQ==");
string url = "http://localhost:2323/api/Applications/StartProcess?token=" + token;
string data = #"{""ProcessParameters"": [{ ""Name"":""flowStarter"",""Value"": ""Waffles"" }],
""Process"": ""RESTAPISUB""}";
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
client.BaseAddress = new System.Uri(url);
byte[] cred = UTF8Encoding.UTF8.GetBytes("username:password");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred));
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
System.Net.Http.HttpContent content = new StringContent(data, UTF8Encoding.UTF8, "application/json");
HttpResponseMessage messge = client.PostAsync(url, content).Result;
string description = string.Empty;
if (messge.IsSuccessStatusCode)
{
string result = messge.Content.ReadAsStringAsync().Result;
description = result;
}
Rest api Method:
[HttpPost]
[ActionName("StartProcess")]
public int StartProcess([FromUri]string token,[FromBody]WorkflowStartParameters parameters)
{
try
{
LoginInformation info = CasheProcesses.ReadCashe(token);
eBAWSAPI api = Service.GetWSService();
WorkflowProcess proc = api.StartProcess(info.Id, info.Password, info.ImpersonateUserId, info.Language, parameters);
return proc.ProcessId;
}
catch (Exception ex)
{
throw new Exception("An error occured when starting process,exception detail:" + ex);
}
}
WorkflowStartParameters class structure:
public class WorkflowStartParameters
{
public WorkflowParameter[] ProcessParameters;
public string Process { get; set; }
}
public class WorkflowParameter
{
public string Name { get; set; }
public string Value { get; set; }
}
I have searched this problem a lot. It seems as a very common problem. I just found this solution working properly, passing request parameter to rest api method and reading body parameter from there. But it is not a valid solution for me.
If you have any idea,feel free to share.
Thanks,
Zehra
I don´t know if it can solve your problem, but let me try.
I guess you don´t have to utilize Server.UrlEncode in your call, but:
Dim myUri As New Uri(Token)
And I guess you must not encode also your username and password - try pass them as string.
Your problem appear to be here:
public class WorkflowStartParameters
{
public WorkflowParameter[] ProcessParameters; <---- needs get/set
public string Process { get; set; }
}
This needs to be a public property to serialize properly. Currently you have it set up as a public field. Just add { get; set; } and give that a try. I would also look into serializing with Newtonsoft.Json to ensure your object is properly serialized. Trying to do it with escape strings will be messing the more data you are sending.
By the way there can be issues sometimes serializing arrays, I would change that to :
public List<WorkflowParameter> ProcessParameters{get;set;}
Finally I have achieved to send filled out data to server. It was about serialization problem. But it didn't work with json serialization before send data. I have added DataContract attribute to my class and it works properly.
Unfortunately still I couldn't figure out this when I make ajax calls from java script it works without DataContract attribute but if I call it in c# it needs DataContract attribute. If someone share the information about this I would appreciate!
I am sharing new class structure, everything else but this still same:
[Serializable]
[DataContract]
public class WorkflowParameter
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Value { get; set; }
}
[Serializable]
[DataContract]
public class WorkflowStartParameters
{
[DataMember]
public WorkflowParameter[] ProcessParameters { get; set; }
[DataMember]
public string Process { get; set; }
}

Categories