match json data to class properties - c#

I have used one webapi method where [FromBody] i used my class object.
like below:
public HttpResponseMessage ProcessResource([FromBody]FileContent contentvalue)
{//some business logic
}
and below is my json format which i am sending from client machine:
{"FileContent":{"ResourceStrings":[{"StringKey":"TestKey","StringID":1,"Value":"TestKey"},{"StringKey":"SampleKey","StringID":2,"Value":"Test key 1"},{"StringKey":"HomeKey","StringID":3,"Value":"Home DEV"},{"StringKey":"custom.WVF.ContactForm.Name","StringID":4,"Value":"NAME"},{"StringKey":"custom.CMS.MenuItem","StringID":5,"Value":"CMS.MenuItem"}]},}
below is FileContent class used:
public class ResourceString
{
public string StringKey { get; set; }
/// <summary>
/// Gets or sets the StringKey
/// </summary>
/// <value>
/// StringKey
/// </value>
public int StringID { get; set; }
/// <summary>
/// Gets or sets the StringID
/// </summary>
/// <value>
/// StringID
/// </value>
public string Value { get; set; }
/// <summary>
/// Gets or sets the Value
/// </summary>
/// <value>
/// Value
/// </value>
}
/// <summary>
/// Added RootObject new class to serialize and deserialize for resource string
/// </summary>
public class RootObject
{
/// <summary>
/// Gets or sets the list of ResourceString
/// </summary>
public List<ResourceString> ResourceStrings { get; set; }
}
public class FileContent
{
public List<ResourceString> ResourceStrings { get; set; }
}
Now when i am sending json data from client machine and debugging my web api method then FileContent object value is null.
How do i get json data in this method parameter?
Now i am able to get json data in that method using Roma's solution.
After getting data i need again i need to deserialize it to ResourceString then again i should get my json format like below:
{"ResourceStrings":[{"StringKey":"TestKey","StringID":1,"Value":"TestKey"},{"StringKey":"SampleKey","StringID":2,"Value":"Test key 1"},{"StringKey":"HomeKey","StringID":3,"Value":"Home DEV"},{"StringKey":"custom.WVF.ContactForm.Name","StringID":4,"Value":"NAME"},{"StringKey":"custom.CMS.MenuItem","StringID":5,"Value":"CMS.MenuItem"}]}
How do i make it deserialize to get the same?

Make your RootObject:
public class RootObject
{
public FileContent FileContent { get; set; }
}
And change your action to:
public HttpResponseMessage ProcessResource([FromBody]RootObject obj)
{
//some business logic
}
OR
If you want to parse into FileContent your JSON should be:
{"ResourceStrings":[{"StringKey":"TestKey","StringID":1,"Value":"TestKey"},{"StringKey":"SampleKey","StringID":2,"Value":"Test key 1"},{"StringKey":"HomeKey","StringID":3,"Value":"Home DEV"},{"StringKey":"custom.WVF.ContactForm.Name","StringID":4,"Value":"NAME"},{"StringKey":"custom.CMS.MenuItem","StringID":5,"Value":"CMS.MenuItem"}]}

Related

c# Generic class for handling static method

I want to have a base generic class to handle model conversion.
Below are the model interfaces
public interface IRawModel
{
}
public interface IDtoModel
{
}
public interface IRawDto<T1, T2>
where T1 : IRawModel
where T2 : IDtoModel
{
/// <summary>
/// Get DTO model.
/// </summary>
/// <param name="item">Raw item</param>
/// <returns>DTO item</returns>
static T2 GetDto(T1 item) => throw new NotImplementedException();
}
Model classes
public class UserDto : IDtoModel
{
/// <summary>
/// Gets or sets firstname.
/// </summary>
public string? FirstName { get; set; }
/// <summary>
/// Gets or sets lastname.
/// </summary>
public string? LastName { get; set; }
/// <summary>
/// Gets or sets email.
/// </summary>
public string? Email { get; set; }
}
public class User : IRawModel, IRawDto<User, UserDto>
{
/// <summary>
/// Gets or sets first name.
/// </summary>
public string FirstName { get; set; }
/// <summary>
/// Gets or sets last name.
/// </summary>
public string LastName { get; set; }
/// <summary>
/// Gets or sets email.
/// </summary>
public string Email { get; set; }
/// <summary>
/// Gets DTO model.
/// </summary>
/// <param name="user">User</param>
/// <returns>User DTO</returns>
public static UserDto GetDto(User user) => new UserDto
{
Email = user.Email,
FirstName = user.FirstName,
LastName = user.LastName,
};
}
When i get a collection of users and to handle conversion in generic way i created below base class
public class BaseRepository<T1, T2, T3>
where T1 : IRawModel
where T2 : IDtoModel
where T3 : IRawDto<T1, T2>
{
/// <summary>
/// Convert collection
/// </summary>
/// <param name="items">T3 items</param>
/// <returns>DTO items</returns>
public IEnumerable<T2> GetDtos(IEnumerable<T3> items)
{
IEnumerable<T2> result = Enumerable.Empty<T2>();
// Something like this, not able to figure out
//result = items
// .Select(x => T3.GetDto((T1)x))
// .ToList();
return result;
}
}
I read interfaces can't have static methods until some c# 8.
Is this an overkill for a conversion, should i implement this conversion in individual classes?

Newtonsoft Json serialize dynamic property back to respective T Type

I have a class that I am converting into a json string and saving. The class contains 2 dynamic properties which are of some type T. In my case its LdrEntity. Now when I am deserializing and getting the object back, it is assigning a json string to that dynamic property. Is there a way to specify to serilialize the dynamic property back to LdrEntity instead of the json string. Please help.
Here is my class (Please see LdrReagentEntity and BciReagentEntity properties)
using Domain.Model.Shared.Entity.Panel;
using System.Collections.Generic;
namespace Authoring.DataAccess.DataModel
{
/// <summary>
/// Cocktail reagent structure to coordinate data.
/// </summary>
public class CocktailReagent
{
/// <summary>
/// Id.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Reagent type.
/// </summary>
public ReagentType Type { get; set; }
/// <summary>
/// Reagent name.
/// </summary>
public string ActualName { get; set; }
/// <summary>
/// Reagent name.
/// </summary>
public int Version { get; set; }
/// <summary>
/// Stability days.
/// </summary>
public int StabilityDays { get; set; }
/// <summary>
/// Number of tests.
/// </summary>
public int NumberOfTests { get; set; }
/// <summary>
/// Reagent comments.
/// </summary>
public string Comments { get; set; }
/// <summary>
/// Cocktail reagent Items.
/// </summary>
public List<CocktailReagentItem> SelectedReagents { get; set; }
}
public class CocktailReagentItem
{
public string Id { get; set; }
public uint Index { get; set; }
public uint Volume { get; set; }
public dynamic LdrReagentEntity { get; set; } //The original type is LdrEntity
public dynamic BciReagentEntity { get; set; } //The original type is LdrEntity
}
}
The two dynamic properties when converted are of type LdrEntity.
So when I convert to json string, I do the following.
public class LdrExportObj
{
public List<CocktailReagent> CocktailReagents { get; set; }
public string HashCode { get; set; }
}
public void Export()
{
var exportObj = new LdrExportObj
{
CocktailReagents = listOfCocktailReagents, //These are the list of items I am saving
HashCode = HashCodeHelper.GenerateHashCode(str),
};
var exportStr = JsonConvert.SerializeObject(exportObj, Formatting.Indented); //I get the json string and save it.
//Save to file
}
When I Import I say
public void Import()
{
var obj = JsonConvert.DeserializeObject<LdrExportObj>(str);
var cocktailsStr = JsonConvert.SerializeObject(obj.CocktailReagents, Formatting.Indented); //If I expand the object and see the dynamic properties, its a json string.
return new LdrExportObj()
{
CocktailReagents = obj.CocktailReagents,
HashCode = obj.HashCode,
};
}
When I debug, its not serializing the internal json string back to LdrEntity, instead its assigning a json string to the dynamic property, See the BciReagentEntity Property in the screenshot. I want it to be conveted back to the original LdrEntity type.

Why IFormFile is null in nested object?

I've got these models
public sealed class UpdateFacilityReportFirstStepCommand : ICommand<ExecutionResult>
{
// other props
/// <summary>
/// Gets or sets the hired staff.
/// </summary>
/// <value>The hired staff.</value>
public List<HiredStaffUpsertModel> HiredStaff { get; set; } = new List<HiredStaffUpsertModel>();
}
public class HiredStaffUpsertModel
{
// other props
/// <summary>
/// Gets or sets the insurance card file.
/// </summary>
/// <value>The insurance card file.</value>
public HiredStaffCarInsuranceCardModel CarInsuranceCardFile { get; set; } = new HiredStaffCarInsuranceCardModel();
}
public class HiredStaffCarInsuranceCardModel
{
/// <summary>
/// Gets or sets the file.
/// </summary>
/// <value>The file.</value>
[FileValidator("pdf,doc,docx", 10 * 1024 * 1024, true)]
public IFormFile File { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is changed.
/// </summary>
/// <value><c>true</c> if this instance is changed; otherwise, <c>false</c>.</value>
public bool IsChanged { get; set; }
}
And in my controller I'm expecting public [FromForm] UpdateFacilityReportFirstStepCommand command.
That's how I send form in Postman (content-type: multipart/form-data):
And that's what I get:
I have no idea why my File is null, although bool IsChanged is received. My frontend developer said that he'll send me form keys like on the Postman screenshot, and I don't get why it works fine with primitive types and doesn't with files.
The way I found to solve it, it's same as yours.
public class Purchase
{
public string Customer { get; set; }
public IEnumerable<Product> Products { get; set; }
}
public class Product
{
public string ProductCode { get; set; }
public IFormFile ProductImage { get; set; }
}
You have to send it like Products[0].ProductImage, otherwise you'll get null in ProductImage.

Why is my int being read as 0 from Azure Table Storage, not as the stored value?

I'm trying to read values that I have stored in an Azure Storage Table. When I retrieve the entity, in Fiddler, I can see the response as having the correct value, i.e.:
{
"odata.etag":"W/\"datetime'2019-01-24T20%3A23%3A58.3605274Z'\"",
"PartitionKey":"0029c461-74b9-47a7-955b-28e07b1905ab",
"RowKey":"09a79860-f568-481c-9641-9a1d53ebd678",
"Timestamp":"2019-01-24T20:23:58.3605274Z",
"AdjustmentId":"[GUID]",
"CompanyName":"[CompanyNme]",
"CustomerId":"[GUID]",
"Date#odata.type":"Edm.DateTime",
"Date":"2019-01-24T20:23:49.9487324Z",
"FinalQuantity":35,
"Id":"[GUID]",
"InitialQuantity":36.0,
"OfferName":"[Product]",
"Requester":"[User]",
"Status":"Accepted",
"StatusMessage":"Created",
"Type":"QuantityAdjustment"
}
However, when I work with this resoponse in my C# code, the InitialQuantity is set to 0. I'm using Microsoft Azure WebJobs Extensions Storage v3.0.3 and WindowsAzure.Storage v9.3.3.
The entity class that the Azure Storage SDK maps this to is below:
public class Transaction : TableEntity, ITransaction
{
/// <summary>
/// Gets or sets the adjustment identifier.
/// </summary>
/// <value>The adjustment identifier.</value>
public string AdjustmentId { get; set; }
/// <summary>
/// Gets or sets the name of the company.
/// </summary>
/// <value>The name of the company.</value>
public string CompanyName { get; set; }
/// <summary>
/// Gets or sets the customer identifier.
/// </summary>
/// <value>The customer identifier.</value>
public string CustomerId { get; set; }
/// <summary>
/// Gets or sets the Transaction's date. Should be generated on creation.
/// </summary>
/// <value>The date.</value>
public DateTime? Date { get; set; }
/// <summary>
/// Gets or sets the final quantity following the transaction.
/// </summary>
/// <value>The final quantity.</value>
public int FinalQuantity { get; set; }
/// <summary>
/// Gets or sets the transaction identifier. Should be a GUID in string format. This is
/// generated when a new Transaction is created.
/// </summary>
/// <value>The identifier.</value>
public string Id { get; set; } = Guid.NewGuid().ToString().ToLower();
/// <summary>
/// Gets or sets the initial quantity.
/// </summary>
/// <value>The initial quantity.</value>
public int InitialQuantity { get; set; }
/// <summary>
/// Gets or sets the offer identifier.
/// </summary>
/// <value>The offer identifier.</value>
public string OfferId { get; set; }
/// <summary>
/// Gets or sets the name of the offer.
/// </summary>
/// <value>The name of the offer.</value>
public string OfferName { get; set; }
/// <summary>
/// Gets or sets the requester.
/// </summary>
/// <value>The requester.</value>
public string Requester { get; set; }
/// <summary>
/// Gets or sets the status. Set to pending by default.
/// </summary>
/// <value>The status.</value>
public string Status { get; set; } = TransactionStatus.Pending;
/// <summary>
/// Gets or sets the status message.
/// </summary>
/// <value>The status message.</value>
public string StatusMessage { get; set; }
/// <summary>
/// Gets or sets the type. Should be set using the constants in the <see
/// cref="T:LicenseAdjustmentManagement.Infrastructure.TransactionTypes"/> class.
/// </summary>
/// <value>The type.</value>
public string Type { get; set; }
public string ToJson()
{
return JsonConvert.SerializeObject(this);
}
}
Code that calls the entities.
var storageAccount = CloudStorageAccount.Parse("[ConnectionString]");
var tableClient = storageAccount.CreateCloudTableClient();
var transactionsTable = tableClient.GetTableReference("Transactions");
var query = TableQuery<Transaction>().Where(TableQuery.GenerateFilterCondition("Id", QueryComparisons.Equal, "[GUID]"));
var results = await transactionsTable.ExecuteQuerySegmentedAsync(query, default(TableContinuationToken)).AsEnumerable();
var transaction = results.First();
All the other values are being read correctly, but the InitialValue is always 0. Any suggestions?
Edit: As suggested by KSib below, the InitialValue is being serialized as a decimal or double so when it's deserialized as an int, it recieves the default value of int, 0. Any idea why this thing is being serialized as a decimal when it's declared as in int?
You're trying to de-serialize a decimal to an int, presumably and instead of throwing an exception I'm going to assume it just sets the property to default(int) which is 0

Deserialize into object with variable name

I hope someone can help me with this; I have just started working on a website which requires to make API calls. I use an open source library for the API calls. Most of the calls work great, but I can't get the most important one to work. The json string when deserialized returns an empty object.
JSON String:
{"benbeun":{"id":27266833,"name":"BenBeun","profileIconId":25,"summonerLevel":30,"revisionDate":1393655593000}}
Call, where responseText is the above JSON string:
public static T CreateRequest(string url)
{
var result = new T();
var getRequest = (HttpWebRequest)WebRequest.Create(url);
using (var getResponse = getRequest.GetResponse())
using (var reader = new System.IO.StreamReader(getResponse.GetResponseStream()))
{
var responseText = reader.ReadToEnd();
result = JsonConvert.DeserializeObject<T>(responseText);
}
return result;
}
Default class from the library:
public class SummonerDto
{
/// <summary>
/// Summoner ID.
/// </summary>
[JsonProperty("id")]
public long Id { get; set; }
/// <summary>
/// Summoner name.
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// ID of the summoner icon associated with the summoner.
/// </summary>
[JsonProperty("profileIconId")]
public int ProfileIconId { get; set; }
/// <summary>
/// Date summoner was last modified specified as epoch milliseconds.
/// </summary>
[JsonProperty("revisionDate")]
public long RevisionDate { get; set; }
/// <summary>
/// Summoner level associated with the summoner.
/// </summary>
[JsonProperty("summonerLevel")]
public long SummonerLevel { get; set; }
}
I can get the class below to work in my calls; however the 'benbeun' string is variable, so this class cannot be used.
public class Benbeun
{
public int id { get; set; }
public string name { get; set; }
public int profileIconId { get; set; }
public int summonerLevel { get; set; }
public long revisionDate { get; set; }
}
public class SummonerDto
{
public Benbeun benbeun { get; set; }
}
Any pointers? I already tried numerous options provided in other questions, but I fear my knowledge is lacking in where exactly my problem lies. I feel I am close with the code below, however it returns an empty object aswell.
public class SummonerDto
{
public IDictionary<string, Summoner> Summoner { get; set; }
}
public class Summoner
{
/// <summary>
/// Summoner ID.
/// </summary>
[JsonProperty("id")]
public long Id { get; set; }
/// <summary>
/// Summoner name.
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// ID of the summoner icon associated with the summoner.
/// </summary>
[JsonProperty("profileIconId")]
public int ProfileIconId { get; set; }
/// <summary>
/// Date summoner was last modified specified as epoch milliseconds.
/// </summary>
[JsonProperty("revisionDate")]
public long RevisionDate { get; set; }
/// <summary>
/// Summoner level associated with the summoner.
/// </summary>
[JsonProperty("summonerLevel")]
public long SummonerLevel { get; set; }
}
Use Dictionary<string,Summoner> to deserialize.
var obj = JsonConvert.DeserializeObject<Dictionary<string,Summoner>>(json);

Categories