I am an engineering student, doing my final degree project based on xamarin apps, including a connection between the client (xamarin) and API (.net). I am trying to send some encrypted data (in base64 encoding) included on a json object as the Request. On the side of the API, it takes the json request, does some fully homomorphic encryption functions and returns the response within new encrypted information.
The problem is when I am trying to receive the response in API as a self-created class named "Post.cs" which includes the next properties;
public class Post
{
public ulong ? userId { get; set; }
public int ? id { get; set; }
public string? title { get; set; }
public string? body { get; set; }
public string? userIdEncrypted { get; set; }
public string? userIdEncryptedReturned { get; set; }
public string? parmsStr { get; set; }
public Post(ulong? userId, int? id, string? title, string? body, string? userIdEncrypted, string? userIdEncryptedReturned, string? parmsStr)
{
this.userId = userId;
this.id = id;
this.title = title;
this.body = body;
this.userIdEncrypted = userIdEncrypted;
this.userIdEncryptedReturned = userIdEncryptedReturned;
this.parmsStr = parmsStr;
}
So, my API takes the request and deserialize it in order to create a "Post" and do some stuff with it.
I am trying to reproduce HttpPost as follows:
[Route("api/[controller]")]
[ApiController]
public class PostController
{
#region CONSTRUCTOR
public PostController()
{
}
#endregion
//POST ://api/Post
[Route("api/[controller]")]
[HttpPost]
public Post ReceivePost([FromBody] Post post)
{
...
var _post = new Post(post.userId, post.id, post.title, post.body, post.userIdEncrypted
post.userIdEncryptedReturned, post.parmsStr);
... FHE functions...
return _post;
}
}
So, at the time I post the "Post" from the client on xamarin, I am sending a Post as the already mentioned structure, where userIdEncrypted and parmsStr contains a base64 encoded string. When it arrives to the API server, the following issue appears:
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'System.IO.Stream'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.
---> System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'System.IO.Stream'.
--- End of inner exception stack trace ---
CLIENT ON XAMARIN APP
This is the json string that I post from the client:
PostModel postAux = new PostModel()
{
userId = 2,
id = 1,
title = "Title for post 1",
body = "Body for post 1",
};
/******************************************************
* Encrypt data of the post (userId)
******************************************************/
PostModel newPost = initializeFHE(postAux);
//Here is where I fill the encrypted data (base64 string) included in the Post object
/******************************************************
* POST encrypted data to the server in csharp
******************************************************/
Uri requestUri = new Uri("http://myHost:3000/api/Post");
var client = new HttpClient();
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json")); // ACCEPT header
var json = JsonConvert.SerializeObject(newPost);
var contentJson = new StringContent(json.ToString(), Encoding.UTF8, "application/json");
//Console.WriteLine(contentJson);
var response = await client.PostAsync(requestUri, contentJson);
...
In which PostModel refers to this self-created Model:
public class PostModel : BaseViewModel
{
public ulong userId { get; set; }
public int id { get; set; }
public string title { get; set; }
public string body { get; set; }
public string userIdEncrypted { get; set; }
public string userIdEncryptedReturned { get; set; }
public string parmsStr { get; set; }
}
I am aware of my inexperience programming on .Net and c#, so any help and explanations are welcome.
Regards,
Raul.
this is one of those rare error messages that tells you exactly what the problem is
Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported.
you need to add a default constructor to Post
public Post() {}
Related
This the request's body:
{
userId: 382,
serviceName: 'Translation'
}
And this is a property on my API controller:
[BindProperty]
public string ServiceName { get; set; }
But it's null. How should I configure ASP.NET Core to bind from JSON too?
I'm using .NET 6.
Perhaps make FromBody explicit and specify the name, in case it is related to the casing not matching.
[FromBody(Name = "serviceName")]
// Creating a class for the method
public class data{
public int UserId { get; set; }
public string Service { get; set; }
}
// If you wish to do in method
public void getdata([FromBody] data recivedata) {
data d = new data();
d.UserId = recivedata.UserId;
d.Service = recivedata.Service;
// perform any action with the data
}
I am looking to receive 1 CNCTask class object from the body, but I also need to transfer a file in the same POST request. I have written out my POST route definition as:
[HttpPost("TaskUpload")]
[Consumes("application/json")]
public async Task<ActionResult<CNCTask>> Post([FromBody] CNCTask task, IFormFile file)
With my route defined as such, I just don't get how I will even transfer the file (e.g. when testing from Postman). A file would usually be sent in the body (I think ?), but if I already have my CNCTask object being selected by the [FromBody], how do I negotiate this file transfer as well ?
I'm quite confused as to how to send both the class object and the file. Any tips would be appreciated.
EDIT
text body request that only includes a CNCTask object
{
"description":"truc",
"completion":24,
"machine":{
"hostname":"some host",
"port": 1234
}
}
form-data body request that includes the full Payload (CNCTask + IFormFile)
This was tested using a Postman and Visual studio.
You have to create a model class
public class CNCTask
{
public string Description { get; set; }
public int Completion { get; set; }
public Machine Machine { get; set; }
public IFormFile File { get; set; }
}
public class Machine
{
public string Hostname { get; set; }
public int Port { get; set; }
}
action
[HttpPost("TaskUpload")]
public async Task<ActionResult<CNCTask>> Post(CNCTask model)
and you can test it using postman
You can retrive form data as follows
var formdata = Request.Form["formdata"];
var model = JsonConvert.DeserializeObject<ModelEntity>(formdata);
And write your controller this way
public async Task<ActionResult<CNCTask>> Post(IFormFile file)
{
var formdata = Request.Form["formdata"];
var model = JsonConvert.DeserializeObject<InitialDemandEntity>(formdata);
...
}
I am currently developing a web api in .NET Core 3. I currently have the following model for my error response object:
public class ErrorRo
{
public string Message { get; set; }
public int StatusCode { get; set; }
public string Endpoint { get; set; }
public string Parameters { get; set; }
public string IpAddress { get; set; }
}
This is a mandated response I need to implement, management has pushed this. It allows more verbose error messages for people hitting our API so that they know what went wrong.
At the moment I am currently populating this object manually in the methods themselves. Is there a way where I can overwrite the response methods. I.e. can I override the BadRequest of IActionResult to automatically populate these fields?
Thanks!
You can use result filters for this purpose. Add a filter which repalces result before sending it back
Model
public class CustomErroModel
{
public string Message { get; set; }
public int StatusCode { get; set; }
public string Endpoint { get; set; }
public string Parameters { get; set; }
public string IpAddress { get; set; }
}
Filter
public class BadRequestCustomErrorFilterAttribute : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
//todo: check for BadRequestObjectResult if anything is returned for bad request
if (context.Result is BadRequestResult)
{
var result = new CustomErroModel
{
StatusCode = 200, //you status code
Endpoint = context.HttpContext.Request.GetDisplayUrl(),
Message = "some message",
IpAddress = context.HttpContext.Connection.RemoteIpAddress.ToString(), //find better implementation in case of proxy
//this returns only parameters that controller expects but not those are not defined in model
Parameters = string.Join(", ", context.ModelState.Select(v => $"{v.Key}={v.Value.AttemptedValue}"))
};
context.Result = new OkObjectResult(result); // or any other ObjectResult
}
}
}
Then apply filter per action or globally
[BadRequestCustomErrorFilter]
public IActionResult SomeAction(SomeModel model)
or
services
.AddMvc(options =>
{
options.Filters.Add<BadRequestCustomErrorFilterAttribute>();
//...
}
Well it depends on the scenario, but one possible approach could be to use a middleware using a similar strategy like the one described in this question, so that you complete the response with extra information.
I have a C# lambda function that is called from API gateway using a GET request.
[LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
public ResponseModel MyFunction(RequestModel request)
{
return new ResponseModel { body = "Hello world!" };
}
public class RequestModel
{
[JsonProperty("a")]
public string A { get; set; }
[JsonProperty("b")]
public string B { get; set; }
}
public class ResponseModel
{
public int statusCode { get; set; } = 200;
public object headers { get; set; } = new object();
public string body { get; set; } = "";
}
How do I map the query string parameters sent to API gateway to the RequestModel parameter in MyFunction?
I have called the function with parameters but they don't seem to come through. Is there a wait to achieve this with a C# lambda function?
Thanks,
Chris
Try putting this in your RequestModel:
public class RequestModel
{
[JsonProperty("queryStringParameters")]
public Dictionary<string, string> QueryStringParameters { get; set; }
}
Then access the query string values as request.QueryStringParameters["foo"], etc.
If you checked the Use Lambda Proxy integration box in API Gateway for your resource and method (which I suspect you did, since you've structured your response object with the statusCode, headers, and body fields), the corresponding request object structure is documented in Input Format of a Lambda Function for Proxy Integration, buried deep in AWS's documentation. There are also other fields available like the body, headers, HTTP verb, etc.
My understanding is that you can also create a custom Payload Mapping to map different parts of the request to a custom JSON object, but doing so requires more configuration than using the built-in Lambda Proxy.
I am returning a json string to a WebMethod in WebForms and I want to take the json string and parse it into custom Order objects.
I have a class:
public class Order
{
public string Item { get; set; }
public string Color { get; set; }
public string Qty { get; set; }
public string Size { get; set; }
}
And a WebMethod:
[WebMethod]
public static string SendOrder(string json)
{
List<Order> orders = new List<Order>();
return json;
}
I am passing this string:
{
json: [
{
"Item":"Nike Polo #286772 - Women's Dri-FIT Micro Pique Short Sleeved Polo",
"Size":"XL",
"Color":"Light Blue",
"Quantity":"3"
},
{
"Item":"Port Authority Women's Jacket #L790 - Black",
"Size":"Medium",
"Color":"Black",
"Quantity":"3"
}
]
}
I want to loop through this string and creating new Orders.
What is the best way to do this?
That JSON is a little oddly formatted as it maps to the following classes (using http://json2csharp.com):
public class Json
{
public string Item { get; set; }
public string Size { get; set; }
public string Color { get; set; }
public string Quantity { get; set; }
}
public class RootObject
{
public List<Json> json { get; set; }
}
I'm not sure why you have a top-level variable named json, but whatever.
At this point just use JSON.NET to deserialize into the structure.
JsonConvert.DeserializeObject<RootObject>(yourJsonString);
If you want to rename the object from Json to Order you'll need to use an attribute for that. I don't recall the name off the top of my head but it should be easy to find in the JSON.NET documentation.
I recently completed a Windows Phone app that retrieved info from a Web API-based server as Json strings. I ended up using the JsonConvert class to convert my lists of objects from Json strings to my custom objects. Here's an example of one of my client-side methods that receives and converts the Json strings:
public async void GetGames()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("base url");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("specific url extention (like api/Order)");
if (response.IsSuccessStatusCode)
{
string s = await response.Content.ReadAsStringAsync();
var deserializedResponse = JsonConvert.DeserializeObject<List<Order>>(s);
//rest of code
}
}
}
Also, make sure that your web method is actually doing something. The example web method you posted creates creates a new list then just returns the parameter you passed in. Using Web API, you could return a list of all Order objects in your database via a method similar to the following:
public IQueryable<Order> GetOrders()
{
return db.Orders; //db is an instance of your DbContext class
}
I hope this is helpful. Let me know if you have any questions.