How do I save a file to SQL Server using Razor forms?

Robert Brown 0 Reputation points
2023-12-18T22:13:08.65+00:00

I have built a web application that connects to a local SQL Server. I would like to use the web form to save a file in the database. I am experiencing an error related to the model types and provider types. When I use a byte array type for the property/method in the entity model class, nothing is saved to the database. I have tried using an IFormFile type for the property/method in my entity model class, but it does not convert to the byte array type needed to save the file to the database. I have also used the 'image' SQL datatype for saving an image, and the validation causes an invalid image error.

Thanks.

Developer technologies | .NET | Entity Framework Core
Developer technologies | ASP.NET | ASP.NET Core
SQL Server | Other
{count} votes

5 answers

Sort by: Most helpful
  1. Q&A Assist
    2023-12-18T22:13:08.6533333+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    To save a file to SQL Server using Razor forms, you can use a byte array type for the property/method in the entity model class. However, if nothing is saved to the database, you may need to check if the byte array is being properly converted to a base64 string before being saved to the database. You can also try using the 'image' SQL datatype for saving an image, but make sure to disable validation to avoid the invalid image error.

    References:

    1 person found this answer helpful.
    0 comments No comments

  2. Bruce (SqlWork.com) 81,981 Reputation points Volunteer Moderator
    2023-12-18T23:41:23.3733333+00:00
    0 comments No comments

  3. Olaf Helper 47,586 Reputation points
    2023-12-19T07:17:05.44+00:00

    The data type "image" is deprecated, you shouldn't use it.

    You can the build-in feature FileTable to store files managed by SQL Server, see

    https://learn.microsoft.com/en-us/sql/relational-databases/blob/filetables-sql-server?view=sql-server-ver16

    0 comments No comments

  4. Anonymous
    2023-12-19T10:02:27.34+00:00

    Hi @Robert Brown,

    When I use a byte array type for the property/method in the entity model class, nothing is saved to the database. I have tried using an IFormFile type for the property/method in my entity model class, but it does not convert to the byte array type needed to save the file to the database. I have also used the 'image' SQL datatype for saving an image, and the validation causes an invalid image error.

    You could refer the following sample:

    1.You could create the data class for EF to store the file to the database.

         public class Applicationfile
    
        {
    
            [Key]
    
            public int Id { get; set; }
    
            public string  Name { get; set; }
    
            public byte[] FileContent { get; set; }
    
            public string Description { get; set; }
    
        }
    
    

    2.Add the dbset to the dbcontext

     public DbSet<Applicationfile> Applicationfiles { get; set; }
    

    3.Define a filemodel for uploading the file and other property inside the razor page

        public class FileViewModel
    
        {
    
            public IFormFile FormFile { get; set; }
    
            public string description { get; set; }
    
        }
    

    4.Modify the razor page like below:

    Cs file:

    
    
        public class CreateFileModel : PageModel
    
        {
    
            private readonly ApplicationDbContext _ApplicationDbContext ;
    
            public CreateFileModel(ApplicationDbContext ApplicationDbContext) {
    
                _ApplicationDbContext = ApplicationDbContext;
    
            }
    
                
    
            public void OnGet()
    
            {
    
            }
    
            [BindProperty]
    
            public FileViewModel FileUpload { get; set; }
    
            public async Task<IActionResult> OnPostUploadFileAsync()
    
            {
    
                if (!ModelState.IsValid)
    
                {
    
                    return Page();
    
                }
    
                string fileName = Path.GetFileName(FileUpload.FormFile.FileName);
    
                string contentType = FileUpload.FormFile.ContentType;
    
                using (MemoryStream memoryStream = new MemoryStream())
    
                {
    
                    FileUpload.FormFile.CopyTo(memoryStream);
    
                    var file = new Applicationfile()
    
                    {
    
                         Name = FileUpload.FormFile.FileName,
    
                         FileContent = memoryStream.ToArray(),
    
                         Description = FileUpload.description
    
                    };
    
                    _ApplicationDbContext.Applicationfiles.Add(file);
    
                    await _ApplicationDbContext.SaveChangesAsync();
    
                }
    
                return RedirectToPage("Index");
    
            }
    
        }
    

    Razor page:

    <div class="row">
    
        <div class="col-md-4">
    
            <form method="post" enctype="multipart/form-data" >
    
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    
                <div class="form-group">
    
                    <label asp-for="FileUpload.FormFile" class="control-label"></label>
    
                    <input asp-for="FileUpload.FormFile" class="form-control" type="file" />
    
                    <span asp-validation-for="FileUpload.FormFile" class="text-danger"></span>
    
                </div>
    
                <div class="form-group">
    
                    <label asp-for="FileUpload.description" class="control-label"></label>
    
                    <input asp-for="FileUpload.description" class="form-control"  />
    
                    <span asp-validation-for="FileUpload.description" class="text-danger"></span>
    
                </div>
    
                <div class="form-group">
    
                    <input type="submit" value="Create" class="btn btn-primary" asp-page-handler="UploadFile" />
    
                </div>
    
            </form>
    
        </div>
    
    </div>
    
    <div>
    
        <a asp-page="Index">Back to List</a>
    
    </div>
    
    @section Scripts {
    
        @{
    
            await Html.RenderPartialAsync("_ValidationScriptsPartial");
    
        }
    
    }
    

    Result:

    enter image description here


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  5. Robert Brown 0 Reputation points
    2024-01-14T16:25:10.6033333+00:00

    Thanks for the help, everyone. I managed to solve the issue by creating and using a new model class

    using System; 
    using System.Collections.Generic; 
    using System.ComponentModel.DataAnnotations.Schema; 
    using Microsoft.AspNetCore.Http;  
    
    namespace App.Models;  
    
    public partial class FileUpload {     
    	public IFormFile? File { get; set; } 
    }
    

    with an IFormFile property type and used it in the asp-for attribute in the razor page. In the .cs, I used the [BindProperty] on the new model, used the async task with MemoryStream to convert the file contents from the new model property to a byte array, assigned the existing db model property to the byte array, then saved it to the db. I should mention that the db table column should be set to varbinary(max) with a byte array length check in the .cs for safety.

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.