locked
Trying to Add Image Upload to Form RRS feed

  • Question

  • User-939035612 posted

    I am porting a WebForms site to ASP.Net Core Razor Pages and have finally gotten to the point where I can create a new post in a database using my form, but I also need to upload an image and save data about it in an images table. I am using this as a guide https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-3.1

    This is what I have so far in my form:

    <form id="newpost" method="post">
    <div class="form-group">
        <div>
            <div class="input-group mb-3 px-2 py-2 rounded-pill bg-white shadow-sm">
            <input asp-for="HeaderImage" id="upload" type="file" onchange="readURL(this);" class="form-control border-0">
            <label asp-for="HeaderImage" id="upload-label" for="upload" class="font-weight-light text-muted">Header Image (Optional)</label>
            <div class="input-group-append">
                <label for="upload" class="btn btn-light m-0 rounded-pill px-4"> <i class="fa fa-upload mr-2 text-muted"></i><small class="text-uppercase font-weight-bold text-muted">Choose file</small></label>
            </div>
            <span class="text-danger" asp-validation-for="HeaderImage"></span>
        </div>
        <div class="row mb-3">
            <div class="col-md-2">
                <label asp-for="Input.HeaderImageName"></label>
            </div>
            <div class="col-10">
                <input class="form-control" asp-for="Input.HeaderImageName" />
            </div>
            <span class="text-danger" asp-validation-for="Input.HeaderImageName"></span>
        </div>
             Uploaded image area
            <div class="bg-light">
                    <p class="font-italic text-black-50 text-center">The image uploaded will be rendered inside the box below.</p>
                    <div class="image-area mt-4"><img id="imageResult" src="#" alt="" class="img-fluid w-100 rounded shadow-sm mx-auto d-block"></div>
                </div>
    
            </div>
        </div>
    <button type="submit" value="Create" class="btn btn-primary">Submit Post</button>
        </form>
    <script type="text/javascript">
                // Add the following code if you want the name of the file appear on select
                $(".custom-file-input").on("change", function () {
                    var fileName = $(this).val().split("\\").pop();
                    $(this).siblings(".custom-file-label").addClass("selected").html(fileName);
                });
            </script>

    <script>

            /*  ==========================================
                SHOW UPLOADED IMAGE
            * ========================================== */
            function readURL(input) {
                if (input.files && input.files[0]) {
                    var reader = new FileReader();

                    reader.onload = function (e) {
                        $('#imageResult')
                            .attr('src', e.target.result);
                    };
                    reader.readAsDataURL(input.files[0]);
                }
            }

            $(function () {
                $('#upload').on('change', function () {
                    readURL(input);
                });
            });

            /*  ==========================================
                SHOW UPLOADED IMAGE NAME
            * ========================================== */
            var input = document.getElementById('upload');
            var infoArea = document.getElementById('upload-label');

            input.addEventListener('change', showFileName);
            function showFileName(event) {
                var input = event.srcElement;
                var fileName = input.files[0].name;
                infoArea.textContent = 'File name: ' + fileName;
            }
        </script>

    My code behind has the following relevant snippets

    [Display(Name = "Header Image (Optional)")]
    		[DataType(DataType.Upload)]
    		[FileExtensions(Extensions = "jpeg,jpg,png,gif", ErrorMessage = "Invalid File Extention, Only .jpg, .jpeg, png, and .gif allowed!")]
    		public IFormFile HeaderImage { get; set; }
    		public Images Images
            {
    			get;
    			set;
            }
    public class InputModel
    		{
    			[MaxLength(50)]
    			[Display(Name = "Image Name (Optional):")]
    			[RegularExpression("^(?!.*<[^>]+>).*", ErrorMessage = "No HTML tags allowed!")]
    			public string HeaderImageName { get; set; }
    		}
    if (HeaderImage != null)
                    {
    					Images headerImage = new Images();
    					headerImage.Imagetype = 2;
    					if(Input.HeaderImageName != null)
                        {
    						headerImage.Imagename = Input.HeaderImageName;
                        }
    					string uploadsFolder = Path.Combine(webHostEnvironment.WebRootPath, "images");
    					string uniqueFileName = Guid.NewGuid().ToString() + "_" + HeaderImage.FileName;
    					string filePath = Path.Combine(uploadsFolder, uniqueFileName);
    					using (var fileStream = new FileStream(filePath, FileMode.Create))
    					{
    						HeaderImage.CopyTo(fileStream);
    					}
    					headerImage.Image = uniqueFileName;
    					await _context.AddAsync(headerImage);
    					await _context.SaveChangesAsync();
    
                    }

    Images are stored using this model:

    public partial class Images
        {
            [Key]
            public int Imageid { get; set; }
    
            //[FileExtensions(Extensions = "jpeg,jpg,png,gif", ErrorMessage = "Invalid File Extention, Only .jpg, .jpeg, png, and .gif allowed!")]
            [DataType(DataType.ImageUrl, ErrorMessage ="Invalid File Type!")]
            public string Image { get; set; }
            public int? Imagetype { get; set; }
            public int? Postid { get; set; }
            public int? Comment { get; set; }
            public string Userid { get; set; }
            [MaxLength(50)]
            [Display(Name = "Image Name (Optional):")]
            [RegularExpression("^(?!.*<[^>]+>).*", ErrorMessage = "No HTML tags allowed!")]
            public string Imagename { get; set; }
    
            public virtual Comments CommentNavigation { get; set; }
            public virtual Imagetypes ImagetypeNavigation { get; set; }
            public virtual Posts Post { get; set; }
    
        }

    Last time I tried to run the script it threw no error in the debugger but no record was added to the database and no file was saved in the images folder.

    Wednesday, October 28, 2020 8:12 AM

Answers

  • User753101303 posted

    Hi,

    The debugger is to see what happens (rather than what doesn't happen). My guess is that HeaderImage.FileName is null ? What if you add enctype="multipart/form-data" and try again ?

    Also I was bit a confused at first as the "guide" you follow is quite different. My understanding is that you want to use a submit button rather than Ajax. Start maybe rather with https://www.learnrazorpages.com/razor-pages/forms/file-upload.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, October 28, 2020 9:16 AM

All replies

  • User753101303 posted

    Hi,

    The debugger is to see what happens (rather than what doesn't happen). My guess is that HeaderImage.FileName is null ? What if you add enctype="multipart/form-data" and try again ?

    Also I was bit a confused at first as the "guide" you follow is quite different. My understanding is that you want to use a submit button rather than Ajax. Start maybe rather with https://www.learnrazorpages.com/razor-pages/forms/file-upload.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, October 28, 2020 9:16 AM
  • User-939035612 posted

    Thanks, I changed HeaderImage.FileName to just HeaderImage and the null reference went away. But then I still go no feedback from the debugger until I commented out that line. Then I got the same error for if(Input.HeaderImageName != null) even thought the input has a string in it. 

    I'm going to try moving that out of the input model to its own model and adding a bindproperty since nothing in the Image model has a required annotation.

    Wednesday, October 28, 2020 9:35 AM
  • User-939035612 posted

    Now I have a null reference exception for: string uniqueFileName = Guid.NewGuid().ToString() + "_" + HeaderImage.FileName;

    System.NullReferenceException
      HResult=0x80004003
      Message=Object reference not set to an instance of an object.
      Source=PostAlmostAnything
      StackTrace:
       at PostAlmostAnything.Pages.post.IndexModel.<OnPostAsync>d__56.MoveNext() in C:\Users\sulli\source\repos\PostAlmostAnything\PostAlmostAnything\Pages\post\Index.cshtml.cs:line 291

    Wednesday, October 28, 2020 9:45 AM
  • User-939035612 posted

    That did it. enctype="multipart/form-data"

    Wednesday, October 28, 2020 9:50 AM
  • User-939035612 posted

    Could you possibly help me with this next feature https://stackoverflow.com/questions/64583109/where-can-i-find-a-multi-image-upload-with-previews-plugin-for-asp-net-core I need to do the same thing for a multi file upload. The data being saved will be basically the same except for the imagetype number, but I want the user to be able to determine how many images are uploaded by dragging and dropping them onto the form. 

    Thursday, October 29, 2020 12:20 AM