I have a web api with some actions that should receive both data and files. To do so, I am accepting multipart/form-data instead of JSON and binding to the model using [FromForm]:
[Authorize(Policy = "MyCustomPolicy")]
public async Task<IActionResult> Create([FromForm]MyCustomDto myDto)
{
// Do some stuff here
}
public class MyCustomDto
{
public int Id { get; set; }
public string Title { get; set; }
public IEnumerable<IFormFile> Attachments { get; set; }
}
This works fine and is correctly bound to the DTO.
The Policy is checked and enforced using a AuthorizationHandler, which also works fine.
In said AuthorizationHandler, I need to access some stuff passed to the controller, such as IDs in the route or DTOs.
Accessing route data is quite easy with authContext.RouteData.Values["nameOfIdField"].
For the body, however, I have created a helper extension method that reads the body stream and deserializes it:
public static async Task<T> DeserializeBody<T>(this AuthorizationFilterContext context, string name)
{
var content = string.Empty;
using(var reader = new StreamReader(context.HttpContext.Request.Body, System.Text.Encoding.UTF8, true, 1024, true))
{
content = await reader.ReadToEndAsync();
reader.BaseStream.Seek(0, SeekOrigin.Begin);
}
if (string.IsNullOrWhiteSpace(content))
{
return default(T);
}
return JsonConvert.DeserializeObject<T>(content);
}
Again, this also works quite fine. However, now I am having trouble with DTOs that are not passed as JSON but - as said in the beginning - as form data.
The body's content is not a JSON that can be serialized easily:
-----------------------------7e2b13b820d4a
Content-Disposition: form-data; name="id"
232
-----------------------------7e2b13b820d4a
Content-Disposition: form-data; name="title"
test
-----------------------------7e2b13b820d4a
Content-Disposition: form-data; name="attachments"; filename="C:\Temp\Test.jpg"
Content-Type: image/jpeg
Is there any way to bind this to my DTO easily, without having to manually parse it?
[FromQuery]and a[FromRoute]because while it seems easy enough, you have replicated that logic somewhere hidden from sight and it will fail.