1

I have a function that allows me to edit an image but I want as soon as I click the Edit button I will get the URL of the current image image: enter image description here Do not see "no file chosen" I want the URL of the image to appear on the right Step Two Once I swap a picture I also want the picture to change to the picture I swap

My Service:

public class FileService : IFileService
{
private readonly IWebHostEnvironment _environment;
public FileService(IWebHostEnvironment environment)
{
    _environment = environment;
}
public async Task<string> File([FromForm] CreateAnimalViewModel model)
{
    string wwwPath = _environment.WebRootPath;
    var path = Path.Combine(wwwPath, "Images", model.Photo!.FileName);
    if (model.Photo.Length > 0)
    {
        using var stream = new FileStream(path, FileMode.Create);
        await model.Photo.CopyToAsync(stream);
    }
      return model.Animal!.PhotoUrl = model.Photo.FileName;
}

public interface IFileService
{
Task<string> File([FromForm] CreateAnimalViewModel model);
}

My ViewModel:

public class CreateAnimalViewModel
{
public Animal? Animal { get; set; }
public IFormFile Photo { get; set; }
}

My Controller:

public async Task<IActionResult> EditAnimal(int id)
{
    var animal = await _repo.FindAnimalById(id); 
    ViewBag.Category = new SelectList(_repository.GetCategoriesTable(), "CategoryId", "Name");
    return View(new CreateAnimalViewModel() { Animal = animal});
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditAnimal([FromForm] CreateAnimalViewModel model)
{
    ModelState.Clear();
    TryValidateModel(model);

    await _file.File(model);

    if (!ModelState.IsValid)
    {
        await _repo.EditAnimal(model.Animal!);
        return RedirectToAction(nameof(Manager));
    }
    return View();
}

My Repository:

 public async Task<int> AddAnimal(Animal animal)
{
    _context.Add(animal!);
    return await _context.SaveChangesAsync();
}

public async Task<int> EditAnimal(Animal animal)
{
    _context.Update(animal);
    return await _context.SaveChangesAsync();
}

public DbSet<Category> GetCategories()
{
    var category = _context.Categories;
    return category;
}

My View:

@model PetShop.Client.Models.CreateAnimalViewModel
    <form asp-action="EditAnimal" method="post" enctype="multipart/form-data">
    <div asp-validation-summary="ModelOnly"></div><input type="hidden" asp-for="Animal!.AnimalId" id="Space"/>
    <dl class="row" >
    <dt class = "col-sm-2"><label asp-for="Animal!.Name" id="Space"></label></dt>
    <dd class = "col-sm-10"><input asp-for="Animal!.Name"/><span asp-validation-for="Animal!.Name" id="Validation"></span></dd>
    <dt class = "col-sm-2"><label asp-for="Animal!.BirthDate" id="Space"></label></dt>
    <dd class = "col-sm-10"><input asp-for="Animal!.BirthDate"/><span asp-validation-for="Animal!.BirthDate" id="Validation"></span></dd>
    <dt class = "col-sm-2"><label asp-for="Animal!.Description" id="Space"></label></dt>
    <dd class = "col-sm-10"><input asp-for="Animal!.Description"/><span asp-validation-for="Animal!.Description"></span>
    </dd> <dt class = "col-sm-2"><label asp-for="Animal!.CategoryId" id="Space"></label></dt>
    <dd class = "col-sm-10"><select asp-for="Animal!.CategoryId"asp-items="ViewBag.Category"></select>
    <span asp-validation-for="Animal!.CategoryId"></span></dd>
    <dt class = "col-sm-2"><label asp-for="Photo"></label></dt>
    <dd class = "col-sm-10"><input type="file" asp-for="Photo" accept="image/*"/>
        <img src="~/images/@Model.Animal!.PhotoUrl"
                         class="rounded-square"
                         height="50" width="75"
                         style="border:1px"
                         asp-append-version="true" accept="image/*" />
    <span asp-validation-for="Photo" id="ImageValidation"></span></dd>
    <br /> <br /><br/><input type="submit" value="Save" id="ButtonDesign"/>
</dl>
</form>
     <a asp-action="Commands"><input type="submit" value="Back to Admin Page" id="BackPageButton"/></a>

image: enter image description here

Md Farid Uddin Kiron
  • 16,817
  • 3
  • 17
  • 43
  • You are not getting the swaped picture because of this like `View(new CreateAnimalViewModel() { Animal = animal});` either you have to rebind the `viewmodel` with `databaseModel` explicitely or you have to introduce a new property then pass the value of new picture. The way you are reusing `CreateAnimalViewModel` is not correct. Additionally, your concept of `editing` how it works is not clear I think. [`Here your problem has the the answer`](https://stackoverflow.com/questions/71881214/edit-images-in-wwwroot/71887679#71887679) – Md Farid Uddin Kiron Apr 17 '22 at 06:17
  • @MdFaridUddinKiron I added what I wrote down with the DisplayPhoto And that gives me the same problem, As soon as I click SAVE the image does change but I want it to change on the same page and also to display the URL of the current image and not the no file chosen – Yosef Abada Apr 17 '22 at 06:29
  • @MdFaridUddinKiron you want to see in share screen? – Yosef Abada Apr 17 '22 at 06:31
  • No need. It seems you want to display the modified image at the same time ,you want to replace the old one if I am not misunderstood. – Md Farid Uddin Kiron Apr 17 '22 at 09:24
  • @MdFaridUddinKiron Again I want to do 2 things First thing I want Instead of in no chosen file get the URL of the current image that if I do Save and do not change the image then I will not get validation I will stay if the same image Second thing I want after every change of image to see an up-to-date image on the EDIT page and not on my main page – Yosef Abada Apr 17 '22 at 16:50
  • Within your current architecture you cannot achieve that. Either you have to introduce `ajax` or `viewComponet` to implement that. – Md Farid Uddin Kiron Apr 18 '22 at 08:36
  • Do you mean photo path? Like this right `C:\Users\myphysicalmachine\source\repos\Dotnet6App\DotNet6MVCWebApp\wwwroot\images\cs.jpg` and finally display beside the image in view? Is that you are looking for? – Md Farid Uddin Kiron Apr 18 '22 at 09:17
  • @MdFaridUddinKiron I updated my post hope you understand what I meant, I want to get the URL without changing image when I click the EDIT button to get straight the URL of the current animal – Yosef Abada Apr 18 '22 at 09:51
  • 1
    Alright got your point , yes that's possible and will try to add a sample for you. – Md Farid Uddin Kiron Apr 18 '22 at 12:25

1 Answers1

1

You cannot implement that:

I have gone through your code what you are trying to implement is to set initial value on input type="file" which is not possible due to security reasons which you can check here. In addition you can also have a look here thousands of questions been askedbefore. Note that it's against RFC standard.

What you can do is:

  • While loading the Edit page hide the <input type="file"

  • Set a checkbox beside photo and it URL like below:

    enter image description here

  • If the checkbox clicked then show the "file upload" option.

Note: Elementary JavaScript required for that implementation.

HTML:

<div>
    <form asp-action="EditAnimal" method="post" enctype="multipart/form-data">
        <div asp-validation-summary="ModelOnly"></div><input type="hidden" asp-for="Animal!.AnimalId" id="Space" />
        <div>
            <h4><strong>Animal Details</strong> </h4>

            <table class="table table-sm table-bordered table-striped">

                <tr>
                    <th> <label asp-for="Animal!.Name"></label></th>
                    <td> <input asp-for="Animal!.Name" class="form-control" placeholder="Enter animal name" /><span asp-validation-for="Animal!.Name"></span></td>
                </tr>
                <tr>
                    <th> <label asp-for="Animal!.Description"></label></th>
                    <td> <input asp-for="Animal!.Description" class="form-control" placeholder="Enter animal description" /><span asp-validation-for="Animal!.Description"></span></td>
                </tr>
                <tr>
                    <th> <label asp-for="Animal!.Category"></label></th>
                    <td> <input asp-for="Animal!.Category" class="form-control" placeholder="Enter animal category" /><span asp-validation-for="Animal!.Category"></span></td>
                </tr>
                <tr>
                    <th> <label asp-for="Photo"></label></th>
                    <td>
                        <img src="~/images/@Model.Animal!.PhotoUrl"
                             class="rounded-square"
                             height="50" width="75"
                             style="border:1px"
                             asp-append-version="true" accept="image/*" />
                        <span><a href="@Model.ImageURL">@Model.ImageURL</a></span>
                        <input type="checkbox" id="CheckBoxId" class="form-check-input" style="margin-top:16px;border:1px solid" /> <span><strong>Upload New File</strong></span>
                        <input type="file" name="photo" id="chooseFile" accept="image/*" />
                    </td>
                </tr>

                <tr>
                    <th> <label>Updated On Local Time</label></th>
                    <td> <input asp-for="Animal!.LocalTime" class="form-control" disabled /><span asp-validation-for="Animal!.Category"></span></td>
                </tr>
                
                <tr>
                    <th>  <button type="submit" class="btn btn-primary" style="width:107px">Update</button></th>
                    <td> </td>
                </tr>
                <tr>
                    <th>@Html.ActionLink("Back To List", "Index", new { /* id=item.PrimaryKey */ }, new { @class = "btn btn-success" })</th>
                    <td> </td>
                </tr>
            </table>
        </div>
    </form>

</div>

JavaScript:

@section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script>
    $(document).ready(function () {
        //On Edit Page Load Hiding the upload option
        $("#chooseFile").hide();

        //When upload check box clicked showing the upload option
        $('#CheckBoxId').mousedown(function() {
            if (!$(this).is(':checked')) {
                 this.checked = true;
                $("#chooseFile").show();
            }
            else{
                $("#chooseFile").hide();
            }
        });

    });
</script>
}

Output:

enter image description here

Md Farid Uddin Kiron
  • 16,817
  • 3
  • 17
  • 43
  • I tried to execute your code but I got it in error. First of all I have another section of valdition and I can not combine them together.Now I saw that you do **RedirectToAction** for the same page that I do not like that is why you get an update I wanted to ask if there is another way to do this that the image will change without clicking the "Update" button? Another thing I did not understand why the URL you did with the tag a – Yosef Abada Apr 19 '22 at 06:42
  • I meant that even if I do not make a change on the beast and do an update then I will get the beast as it is with you in the example if I do not choose a picture then I get an error that is not what I wanted – Yosef Abada Apr 19 '22 at 06:42
  • `"I wanted to ask if there is another way to do this that the image will change without clicking the "Update" button?"` No there are no way, either you have to do with button click or checkbox click, the thing is we have to handle this kind fo scenario using `click event` or `On Mouse hover` event. But there should be an event. – Md Farid Uddin Kiron Apr 19 '22 at 07:00
  • I saw an example that does what I mean : https://www.youtube.com/watch?v=aKDvfxiZ4Zw&t=870s – Yosef Abada Apr 19 '22 at 07:06
  • That's great then try that out. – Md Farid Uddin Kiron Apr 19 '22 at 07:09
  • Okay about changing the value of the URL is it invalid if I change it? ("no file chosen") – Yosef Abada Apr 19 '22 at 07:12
  • Its valid when you change the file itself replacing the new one, but absolutely invalid if you update the file name without selecting new one or modification. I am not sure what kind of requirement it is. – Md Farid Uddin Kiron Apr 19 '22 at 07:18