9

Total noob on asp.net, trying to teach myself ASP.NET Core 2.0 MVC here.

What I am currently stuck on:

Trying to find a tutorial for image uploads to place the image into a subdir of root, eg /images/items, then save that path to the database so that when the items are listed I can img src the image too.

This is what I have done so far:

ItemsController:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,SupplierId,CategoryId,Name,Description,Image,Price,Enabled,DateAdded")] Item item)
{
     if (ModelState.IsValid)
     {
         // add image upload


         // end image upload

         _context.Add(item);
         await _context.SaveChangesAsync();
         return RedirectToAction(nameof(Index));
     }
     return View(item);
}

And my Item Model class is:

public class Item
{
    public int Id { get; set; }
    public int SupplierId { get; set; }
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string Image { get; set; }
    public float Price { get; set; }
    public Boolean Enabled { get; set; }
    public DateTime DateAdded { get; set; }
}

And my razor Create form is:

@model QualitySouvenirs.Models.Item

<form asp-action="Create" enctype="multipart/form-data">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

    //Other input fields has been removed for brevity

    <div class="form-group">
         <label asp-for="Image" class="control-label"></label>
         <input asp-for="Image"  type="file" class="form-control" />
         <span asp-validation-for="Image" class="text-danger"></span>
    </div>

    <div class="form-group">
        <input type="submit" value="Create" class="btn btn-default" />
    </div>
</form>

And here is my Index.cshtml where I would like to display the image:

@model IEnumerable<QualitySouvenirs.Models.Item>

<table class="table">
    <thead>
        <tr>
           // other th's removed for brevity
           <th>
              @Html.DisplayNameFor(model => model.Image)
           </th>

           <th></th>
        </tr>
    </thead>
    <tbody>
       @foreach (var item in Model)
       {
          <tr>
            // other td's removed for brevity
            <td>
               @Html.DisplayFor(modelItem => item.Image)
            </td>

            <td>
               <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
               <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
               <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
            </td>
          </tr>
       }
    </tbody>
</table>

Where do I go from here? I suspect I need some using declarations?

6
  • 1
    It has complained about not finding the listed elements to work with => which elements are not found? If you encounter some errors on building/debug process, include them in your question. Commented Sep 19, 2018 at 6:07
  • @TetsuyaYamamoto: All I remember was the particular code snippet I found had Path and PathString in it... Commented Sep 19, 2018 at 6:25
  • 1
    Ah right, looking at this one: fiyazhasan.me/… Commented Sep 19, 2018 at 6:26
  • @Onyx I am answering your question thoroughly! But please add create.cshtml file code to the question instead of index.cshtml file. index.cshtml is not relevant to the question. Commented Sep 19, 2018 at 11:29
  • @TanvirArjel: I've added Create. Thanks. Commented Sep 19, 2018 at 20:53

1 Answer 1

10

Write your Create POST method as follows:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Item item,IFormFile image)
{
    if (ModelState.IsValid)
    {
        if (image != null && image.Length > 0)
        {
            var fileName = Path.GetFileName(image.FileName);
            var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot\\images\\items", fileName);
            using (var fileSteam = new FileStream(filePath, FileMode.Create))
            {
                await image.CopyToAsync(fileSteam);
            }
            item.Image = fileName;
        }

        _context.Add(item);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(item);
}

Then for displaying the image in the table:

<td>
    <img class="img-responsive" src="@Url.Content("~/images/items/" + @item.Image)" alt="">
</td>
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you so much!! I had to add some using declarations in order to get your code to work, but I found those here: stackoverflow.com/questions/37153261/… Being : using Microsoft.AspNetCore.Http; using System.IO;
@Onyx Whenever handle file you should always use using block in c#. Here is the details: learn.microsoft.com/en-us/dotnet/csharp/language-reference/…
and that is the kind of information that is so hard to find. Having come from PHP programming, where documentation is prolific, if a little outdated at times, I am finding ASP.Net very difficult as there seems to be a real lack of cookbooks in this regard. And then it also seems that searching is a problem; how many different languages are called ASP.net?
I have clicked the green tick... should I be doing something else too?
@Onyx This is actually not! ASP.NET is not difficult at all. May be you are very new to ASP.NET. It will be irradiated soon. ASP.NET has a huge community and resources. Welcome to ASP.NET!

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.