Why IFormFile is null in nested object? - c#

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.

Related

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.

I cannot retrieve my saved data from database using Entity Framework and I'm not getting any errors

I have the following code, and am trying to retrieve the data from my database. I know the data is saving correctly, but what am I doing wrong when calling it? I use the SQL Server Object Window within Visual Studio and can see that there is information in the database in the Song table, but when I try to call it in my action method, I do not see any information being retrieved when a breakpoint is set on the .ToList() method.
MusicController.cs
SongDatabase db = new SongDatabase();
[HttpGet]
public ActionResult Music()
{
var songs = db.Songs.ToList();
return View(songs);
}
Song.cs
/// <summary>
/// This is the song of the music for the playlist, and will be logged into the Music Manager app.
/// </summary>
public class Song
{
/// <summary>
/// The Id of the song.
/// </summary>
public int SongId { get; set; }
/// <summary>
/// The name of the song.
/// </summary>
[Required]
[DisplayName("Song")]
public string SongName { get; set; }
/// <summary>
/// The artist of the song.
/// </summary>
[Required, StringLength(100)]
[DisplayName("Artist")]
public string ArtistName { get; set; }
/// <summary>
/// Represents an album from an artist.
/// </summary>
[Required, StringLength(50)]
[DisplayName("Album")]
public string AlbumName { get; set; }
/// <summary>
/// The duration of the song.
/// </summary>
public double Duration { get; set; }
/// <summary>
/// Whether or not this song should be excluded when calculating the total duration of the current playlist.
/// </summary>
public bool Exclude { get; set; }
}
SongDatabase.cs
public class SongDatabase : DbContext
{
public DbSet<Song> Songs { get; set; }
public SongDatabase()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SongDatabase>());
}
}

My .saveChanges() method is not saving because it is saying an object reference is required for the non-static field, method, or property

I am getting an error when I call the .SaveChanges(). It is telling me an object reference is required for the non-static field, method, or property 'SongDatabase.Songs'. Here is my code for my controller. Can someone tell me why this error is occurring?
[HttpPost]
public ActionResult Add(Song song)
{
using (SongDatabase db = new SongDatabase())
{
SongDatabase.Songs.Add(song);
SongDatabase.SaveChanges();
}
return RedirectToAction("Music");
}
Here is my code for my database for the songs.
public class SongDatabase : DbContext
{
public DbSet<Song> Songs { get; set; }
public DbSet<Artist> Artists { get; set; }
public DbSet<Album> Albums { get; set; }
public SongDatabase()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SongDatabase>());
}
}
And lastly, here is the code for my Song class.
public class Song
{
public Song()
{
Album = new List<Album>();
}
/// <summary>
/// The Id of the song.
/// </summary>
public int SongId { get; set; }
/// <summary>
/// The name of the song.
/// </summary>
public string SongName { get; set; }
/// <summary>
/// The artist of the song.
/// </summary>
public int ArtistId { get; set; }
/// <summary>
/// The duration of the song.
/// </summary>
public double Duration { get; set; }
/// <summary>
/// Whether or not this song should be excluded when calculating the total duration of the current playlist.
/// </summary>
public bool Exclude { get; set; }
/// <summary>
/// Navigation property linking the album class to the song class.
/// </summary>
public virtual ICollection<Album> Album { get; set; }
/// <summary>
/// Navigation property linking the artist class to the song class.
/// </summary>
public virtual Artist Artist { get; set; }
}
You're trying to access public DbSet<Song> Songs { get; set; } as a static value, in your code here
[HttpPost]
public ActionResult Add(Song song)
{
using (SongDatabase db = new SongDatabase())
{
SongDatabase.Songs.Add(song);
SongDatabase.SaveChanges();
}
return RedirectToAction("Music");
}
You create an instance of SongDatabase with SongDatabase db = new SongDatabase() but you're not using that instance db. You should change it for
[HttpPost]
public ActionResult Add(Song song)
{
using (SongDatabase db = new SongDatabase())
{
db.Songs.Add(song);
db.SaveChanges();
}
return RedirectToAction("Music");
}

match json data to class properties

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"}]}

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