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
Related
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:
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.
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"}
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; }
}
What I would like to do is the following:
var client = new JsonServiceClient(ServiceUrl);
var request = new FooQuery {Id = 1};
IEnumerable<Project> response = client.Get(request);
However, my FooQuery doesn't implement any IReturn, and I'd like it not to (it's in a library without ServiceStack references). Here's my service side:
Library of business objects:
public class ProjectQuery
{
public int Id { get; set; }
}
AppHost:
Routes.Add<ProjectQuery>("/project", "GET");
Service:
public object Get(Foo request)
{
// do stuff.
}
Is there some nice, clean way to create the JsonServiceClient without using the IReturn interface on my business object?
Looks like there's no way not to use IReturn if you don't want to provide a URL to the JsonServiceClient Get() requests. Just decided to create another set of DTOs in my ServiceStack implementation, that are essentially mirrors of the real DTOs in another library. Then when a request comes in to my SS DTO, I create the other library's DTO, set each property, and pass it along.
Not pretty, but that's the best I could find so far.
I had the same problem using IReturn and Routes, as I wanted to use the DTOs
in assemblies with business logic, without ServiceStack references.
It worked for me, using in the Client Model
public class TestRequest
{
public int vendorId {get; set; }
public string barcode {get; set; }
public string username { get; set; }
public string password { get; set; }
}
then in the AppHost
Routes.Add<TestRequest( "/TestAPI/Reservation/{vendorId}/{barcode}"," GET,OPTIONS")
.Add<TestRequest>("/TestAPI/Reservation", "POST, OPTIONS")
and the call for JsonServiceClient with POST
request.vendorId=12344;
request.barcode="AAS1223";
TestResponse response = client.Post<TestResponse>(server_ip + "/TestAPI/Reservation", request);
OR with GET
TestResponse response = client.Get<TestResponse>(server_ip + "/TestAPI/Reservation/12344/AAS1223?username=John&password=99");
Then in the service Get or Post functions
public TestResponse Get(TestRequest request)
{
// request members hold the values of the url.
return DoBusinessLayerWork(request);
}
Using the Send() method from the JsonServiceClient type is the way to go about doing this.