6

I'm having trouble ironing out the file/image upload in ASP.NET MVC 6. Most tutorials appear to be outdated, and even some of the new ones seem to reference things that don't make sense.

In my view:

<div class="form-group">
    @using (Html.BeginForm("Create", "PostNin", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <label asp-for="NinImageString" class="control-label"></label>
        <input type="file" name="files" class="form-control" />
    }

    @*<input asp-for="NinImageString" class="form-control" />
    <span asp-validation-for="NinImageString" class="text-danger"></span>*@
</div>
<div class="form-group">
    <label asp-for="NinImageCaption" class="control-label"></label>
    <input asp-for="NinImageCaption" class="form-control" />
    <span asp-validation-for="NinImageCaption" class="text-danger"></span>
</div>

And then in my controller:

// GET: PostNins/Create
public IActionResult Create()
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,NinFk,NinDigit,NinImageString,NinImageCaption,NinNote")] PostNin postNin, IFormFile files)
{
    // need code here
        
    if (ModelState.IsValid)
    {
        _context.Add(postNin);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

    return View(postNin);
}

My understanding is that I have to use IFormFile to pull this off.

I would like to upload an image with a caption, and store it into the application folder NinImages where I can access it later. I suppose I have questions about that too, but that's for another question.

My understanding is that I have to somehow save a copy of the image into the directory system, under wwwroot, then save the path of the file as a string to the database.

SOLUTION:

My new controller looks like below. As a note, the fileTime is only to assign a unique value to each upload, to avoid duplicates. This works in this case because only one file can be uploaded at a time.

[HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("Id,NinFk,NinDigit,NinImageString,NinImageCaption,NinNote")] PostNin postNin, IFormFile uploadFile)
    {


        if (uploadFile != null && uploadFile.Length > 0)
        {
            var fileTime = DateTime.UtcNow.ToString("yyMMddHHmmss");
            var fileName = fileTime + Path.GetFileName(uploadFile.FileName);
            var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/NinFileUploads", fileName);

            postNin.NinImageString = filePath;
            _context.PostNins.Add(postNin);
            _context.SaveChanges();

            using (var fileStream = new FileStream(filePath, FileMode.Create))
            {
                await uploadFile.CopyToAsync(fileStream);
            }
            //if (ModelState.IsValid)
            //{
            //    _context.Add(postNin);
            //    await _context.SaveChangesAsync();
            //    return RedirectToAction(nameof(Index));
            //}
            return RedirectToAction(nameof(Index));

        }
        return View(postNin);
2
  • 4
    Does any of the answers here help? stackoverflow.com/questions/35379309/… If not, what error are you getting? And I don't know if this is a typo but this is wrong enctype = "multipart/form-date" it should be "multipart/form-data". Commented Sep 9, 2020 at 19:59
  • Good catch on typo, thanks. Some of them are helpful, but not complete or they are doing something different. Commented Sep 10, 2020 at 4:27

3 Answers 3

5

Here is a demo work:

PostNin Class:

public class PostNin
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string ImagePath { get; set; }
    }

Controller:

public async Task<bool> Create(PostNin postNin,IFormFile upload)
        {     
                if (upload != null && upload.Length > 0)
                {                
                    var fileName = Path.GetFileName(upload.FileName);
                    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images", fileName);
                    postNin.ImagePath = filePath;
                    _context.PostNins.Add(postNin);
                    _context.SaveChanges();
                    using (var fileSrteam = new FileStream(filePath, FileMode.Create))
                    {
                        await upload.CopyToAsync(fileSrteam);
                    }
                    return true;
                }
                return false;
        }

Result: enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

ooh, its close. Why did you use "bool" instead of "IActionResult"? I attempted to use your code but got an error, "Could not find a part of the path". See updated question
This worked perfectly. Thank you. I have a follow-up question about naming the uploaded files, which is why I haven't marked answered yet. I appreciate your help. Also, I just wanted to point out that your code and images were incredibly detailed and helpful.
2

You need to set the name attribute for the input element same as Create method parameter, in this solution name attribute and Create method parameter set to uploadFile

HTML

<input type="file" name="uploadFile" class="form-control" />

CS

Create([Bind("Id,NinFk,NinDigit,NinImageString,NinImageCaption,NinNote")] PostNin postNin, IFormFile uploadFile)

2 Comments

Fair point. I have adjusted this. What should I do next?
Mark correct solution for old question and create new one for next problem 😉
1

change the name of the file upload control to files

<input type="file" name="files" class="form-control" />

add [FromForm] before IFormFile files first and try if it works

Create([Bind("Id,NinFk,NinDigit,NinImageString,NinImageCaption,NinNote")] PostNin postNin, [FromForm]IFormFile files)

if it not working try to add new IFormFile files property to PostNin class or create a new class as a model for this action and add [FromForm] before it on the action parameter.

public class PostNinModel {
....
public IFormFile files { get; set; }
...
}

Create([FromForm] PostNinModel postNin)

2 Comments

I have updated the file upload control and added [FromForm] on action parameter. No IDE errors. but now what? How should I "try it"?
is the file been sent to the action? you can check this using breakpoint then you can save the file check this stackoverflow.com/questions/39322085/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.