Utsuhoagie
Utsuhoagie
Explore posts from servers
CC#
Created by Utsuhoagie on 8/10/2024 in #help
EF Core with TPC hierarchy: InvalidCastException despite no casting
I have a problem when trying to use TPC hierarchy mapping in EF Core 8, where I get InvalidCastExceptions despite never casting anything. What I wanted to do is have a BaseAuditedEntity class for most models in my app, so that I could use it for a feature: TierList entity has many TierListItems, and each TierListItem relates to a BaseAuditedEntity entity in the app, such as a Circle (music group) or ArrangementSong or any other base entity. The (simplified) models:
public class Circle : BaseAuditedEntity
{
public string Name { get; set; }

public List<ArrangementSong> ArrangementSongs { get; set; }
}

public class ArrangementSong : BaseAuditedEntity
{
public string Title { get; set; }

public int CircleId { get; set; }
public Circle Circle { get; set; }

public List<OfficialSong> OfficialSongs { get; set; }
public List<OfficialSongArrangementSong> OfficialSongArrangementSongs { get; set; }
}

public class OfficialSong : BaseAuditedEntity
{
public string Title { get; set; }

public required List<ArrangementSong> ArrangementSongs { get; set; }
public required List<OfficialSongArrangementSong> OfficialSongArrangementSongs { get; set; }
}

public class TierListItem : BaseEntity
{
public int TierListTierId { get; set; }
public TierListTier TierListTier { get; set; } = default!;

public int SourceId { get; set; }
public BaseAuditedEntity Source { get; set; }
}

public abstract class BaseAuditedEntity : BaseEntity
{
public DateTime CreatedOn { get; set; }
public string CreatedByUserName { get; set; } = string.Empty;

public DateTime? UpdatedOn { get; set; }
public string? UpdatedByUserName { get; set; }
}

public abstract class BaseEntity
{
public int Id { get; set; }
}
public class Circle : BaseAuditedEntity
{
public string Name { get; set; }

public List<ArrangementSong> ArrangementSongs { get; set; }
}

public class ArrangementSong : BaseAuditedEntity
{
public string Title { get; set; }

public int CircleId { get; set; }
public Circle Circle { get; set; }

public List<OfficialSong> OfficialSongs { get; set; }
public List<OfficialSongArrangementSong> OfficialSongArrangementSongs { get; set; }
}

public class OfficialSong : BaseAuditedEntity
{
public string Title { get; set; }

public required List<ArrangementSong> ArrangementSongs { get; set; }
public required List<OfficialSongArrangementSong> OfficialSongArrangementSongs { get; set; }
}

public class TierListItem : BaseEntity
{
public int TierListTierId { get; set; }
public TierListTier TierListTier { get; set; } = default!;

public int SourceId { get; set; }
public BaseAuditedEntity Source { get; set; }
}

public abstract class BaseAuditedEntity : BaseEntity
{
public DateTime CreatedOn { get; set; }
public string CreatedByUserName { get; set; } = string.Empty;

public DateTime? UpdatedOn { get; set; }
public string? UpdatedByUserName { get; set; }
}

public abstract class BaseEntity
{
public int Id { get; set; }
}
The base classes configuration:
modelBuilder.Entity<BaseEntity>()
.UseTpcMappingStrategy();


modelBuilder.Entity<Circle>()
.HasMany(c => c.ArrangementSongs)
.WithOne(a => a.Circle)
.IsRequired();
// ...
modelBuilder.Entity<BaseEntity>()
.UseTpcMappingStrategy();


modelBuilder.Entity<Circle>()
.HasMany(c => c.ArrangementSongs)
.WithOne(a => a.Circle)
.IsRequired();
// ...
A simple query could be like this:
var circles_Res = await _context.Circles
.Include(c => c.ArrangementSongs)
.Where(c => query.searchName == null || EF.Functions.ILike(c.Name, $"%{query.searchName}%"))
.Select(c => new CircleResponse(c)
{
ArrangementSongTitles = c.ArrangementSongs.Select(a => a.Title).ToList(),
})
.ToListAsync();
var circles_Res = await _context.Circles
.Include(c => c.ArrangementSongs)
.Where(c => query.searchName == null || EF.Functions.ILike(c.Name, $"%{query.searchName}%"))
.Select(c => new CircleResponse(c)
{
ArrangementSongTitles = c.ArrangementSongs.Select(a => a.Title).ToList(),
})
.ToListAsync();
But when running, I get this exception (it doesn't happen if I don't .Include(a => a.Circle) ) in the logs. I'm guessing that this is a problem with BaseEntity rows in the DB. There is no BaseEntity table because it's TPC, but after a migration I made to update the models from standalone Ids to using a base class, then I see that they use a common sequence. However, the existing Ids are unchanged, so there are many rows that share the same Ids. But I'm not sure if this is actually the cause, or how to fix this. Any help is greatly appreciated!
12 replies
CC#
Created by Utsuhoagie on 4/27/2023 in #help
✅ Nullable DateTimeOffset field in a [FromForm] model is always null
18 replies
CC#
Created by Utsuhoagie on 4/1/2023 in #help
❔ Why is my ASP.NET Core Web API not responding at all to a `multipart/form-data` request?
Specifically my client is Expo Go (React Native) on a physical Android, and the request does work in Postman. On my server:
C#
Models/FileUploadRequest.cs
public class FileUploadRequest
{
public IFormFile File1 { get; set; } = default!;
}

Controllers/FilesController.cs
[HttpPost("Upload")]
public async Task<IActionResult> Upload([FromForm] FileUploadRequest req)
{
var file1 = req.File1;
if (file1.Length > 0)
{
var safeFileName = Path.GetRandomFileName();
var safeFilePathName = Path.Combine(DANGEROUS_FILE_PATH, safeFileName);
var fileStream = System.IO.File.Create(safeFilePathName);
await file1.CopyToAsync(fileStream);
}
return Ok(new
{
Message = "File is uploaded",
File = file1
});
}
C#
Models/FileUploadRequest.cs
public class FileUploadRequest
{
public IFormFile File1 { get; set; } = default!;
}

Controllers/FilesController.cs
[HttpPost("Upload")]
public async Task<IActionResult> Upload([FromForm] FileUploadRequest req)
{
var file1 = req.File1;
if (file1.Length > 0)
{
var safeFileName = Path.GetRandomFileName();
var safeFilePathName = Path.Combine(DANGEROUS_FILE_PATH, safeFileName);
var fileStream = System.IO.File.Create(safeFilePathName);
await file1.CopyToAsync(fileStream);
}
return Ok(new
{
Message = "File is uploaded",
File = file1
});
}
On my client, I'm creating a request like this:
// Get photo from URI
const res = await fetch(photo.uri);
const img = await res.blob();

const formData = new FormData();
formData.append('File1', img);
const uploadRes = await API.post('Files/Upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
// Get photo from URI
const res = await fetch(photo.uri);
const img = await res.blob();

const formData = new FormData();
formData.append('File1', img);
const uploadRes = await API.post('Files/Upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
But whenever I try to send this request, the server does not respond at all. However, if I remove the headers (default Content-Type: application/json) then it does respond with 400, along with these logs:
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinder[13]
Attempting to bind property 'Capstone.Features.File.FileUploadRequest.File1' of type 'Microsoft.AspNetCore.Http.IFormFile' using the name 'Fi
le1' in request data ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinder[19]
Could not bind to model with name 'File1' and type 'Microsoft.AspNetCore.Http.IFormFile' as the request did not have a content type of either
'application/x-www-form-urlencoded' or 'multipart/form-data'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinder[13]
Attempting to bind property 'Capstone.Features.File.FileUploadRequest.File1' of type 'Microsoft.AspNetCore.Http.IFormFile' using the name 'Fi
le1' in request data ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinder[19]
Could not bind to model with name 'File1' and type 'Microsoft.AspNetCore.Http.IFormFile' as the request did not have a content type of either
'application/x-www-form-urlencoded' or 'multipart/form-data'.
5 replies
CC#
Created by Utsuhoagie on 3/8/2023 in #help
❔ [ASP.Net Core Web API] How to not be forced to add AuthenticationSchemes on actions' [Authorize]
2 replies
CC#
Created by Utsuhoagie on 10/25/2022 in #help
LINQ expression could not be translated after converting object
15 replies