How would you form your parameters for the action method which is supposed to receive one file
and one text
value from the request?
I tried
I'm using the following code to accomplish this in order to parse a response from Mailgun, which comprises both files and text values.
Please note that "dashifying" is just so property names like "MessageHeaders" get turned into "message-headers"; obviously you should use whatever logic makes sense for your use case.
Controller:
using System;
using Microsoft.AspNetCore.Mvc;
using NuGet.Protocol.Core.v3;
namespace Potato
{
[Route("api/[controller]")]
public class MailgunController : Controller
{
[HttpPost]
public IActionResult Post()
{
MailgunEmail email = new MailgunEmail(Request);
return Ok(email.ToJson());
}
}
}
Model:
using System;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
namespace Potato
{
public class MailgunEmail
{
public IEnumerable<IFormFile> Attachments { get; set; }
public string Recipient { get; set; }
public string Sender { get; set; }
public string From { get; set; }
public string Subject { get; set; }
public string BodyPlain { get; set; }
public string StrippedText { get; set; }
public string StrippedSignature { get; set; }
public string BodyHtml { get; set; }
public string StrippedHtml { get; set; }
public int? AttachmentCount { get; set; }
public int Timestamp { get; set; }
public string Token { get; set; }
public string Signature { get; set; }
public string MessageHeaders { get; set; }
public string ContentIdMap { get; set; }
public MailgunEmail(HttpRequest request)
{
var form = request.Form;
Attachments = new List<IFormFile>(form.Files);
foreach (var prop in typeof(MailgunEmail).GetProperties()) {
string propName = Dashify(prop.Name);
var curVal = form[propName];
if (curVal.Count > 0) {
prop.SetValue(this, To(curVal[0], prop.PropertyType), null);
}
}
}
private object To(IConvertible obj, Type t)
{
Type u = Nullable.GetUnderlyingType(t);
if (u != null) {
return (obj == null) ? GetDefaultValue(t) : Convert.ChangeType(obj, u);
} else {
return Convert.ChangeType(obj, t);
}
}
private object GetDefaultValue(Type t)
{
if (t.GetTypeInfo().IsValueType) {
return Activator.CreateInstance(t);
}
return null;
}
private string Dashify(string source)
{
string result = "";
var chars = source.ToCharArray();
for (int i = 0; i < chars.Length; ++i) {
var c = chars[i];
if (i > 0 && char.IsUpper(c)) {
result += '-';
}
result += char.ToLower(c);
}
return result;
}
}
}
You Can Get Multi Images By Sample Code Through MultiPart.
First Inject IHttpContextAccessor To ConfigureService Method In Startup Class.Then Call It With Constructor Injection In Controller:
private readonly IHttpContextAccessor _httpContextAccessor;
public FileController(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
Action Method Can Have Response Or Not.
public async Task<object> UploadImage()
{
var fileBytes = new List<byte[]>();
var files =
_httpContextAccessor.HttpContext.Request.Form.Files;
foreach (var file in files)
{
if (file.Length > 0)
{
using (var memoryStream = new MemoryStream())
{
await file.CopyToAsync(memoryStream);
fileBytes.Add(memoryStream.ToArray());
}
}
}
// TODO: Write Code For Save Or Send Result To Another Services For Save
}
I had the similar issue and I solved the problem by using [FromForm]
attribute and FileUploadModelView
in the function as follow:
[HttpPost]
[Route("upload")]
public async Task<IActionResult> Upload([FromForm] FileUploadViewModel model, [FromForm] string member_code)
{
var file = model.File;
// ...
}
This is a quick solution for anyone who is facing the same issue:
You will use ajax to send the following formData
let formData: FormData;
formData = new FormData();
formData.append('imageFile', imageFile);
formData.append('name', name);
Then you will receive it in your controller like this:
public string Post(IFormCollection data, IFormFile imageFile)
Then you will access the data as you do normally:
var name = data["name"];
I guess you're transmitting the file and text in proper JSON format.
You should create a new class which includes file and text as properties of type string. Add the new class to your method arguments with attribute[FromBody] and you'll be able to parse the image string according to your needs.
Another way would be accessing the whole request content via
await Request.Content.ReadAsStringAsync();
You would then have to parse the entire content, though.
This page helped me a lot https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads
so now in my code I have the controller method as:
public async Task<IActionResult> UploadFiles(UploadedFile ups)
and a class for the model as
public class UploadedFile
{
public string UploadName { get; set; }
public List<IFormFile> Files { get; set; }
}
and the form like
<form method="post" enctype="multipart/form-data" asp-controller="Files" asp-action="UploadFiles">