ASP.Net Core Image Demo
List of Technology used in this Demo
- ASP.NET Core 2.2 (Razor)
- Entity Framework Core 2.2
- Visual Studio Community (I am using 19, but this also work using 17)
- SQL Server - I have it running in a Docker container on a Ubuntu VM (That said, this may work using any DBMS)
Steps to follow
These steps will vary with your setup and needs, so it may go without saying that this page should be used guide rather than an authoritative document
-
Create Your Table
- For this example, I will use TSQL, however there is no reason that mySQL, PostgreSQL, or other relational DB should work just fine
- The most important bit is the data field that is of the VARBINARY(max) type
-
My Example table setup is here:
[ID] [uniqueidentifier] ROWGUIDCOL NOT NULL, [Name] [varchar](200) NOT NULL, [Data] [varbinary](max) NOT NULL, [Width] [int] NOT NULL, [Height] [int] NOT NULL, [ContentType] [varchar](50) NOT NULL, [UplDate] [datetime] NOT NULL ALTER TABLE [dbo].[ImageTB] ADD CONSTRAINT [DF_ImageTB_ID] DEFAULT (newid()) FOR [ID] GO ALTER TABLE [dbo].[ImageTB] ADD CONSTRAINT [DF_ImageTB_UplDate] DEFAULT (getdate()) FOR [UplDate] GO
- I added some defaults, however in this example I set those values in code, so those are optional
-
Create your VS project
-
Select ASP.NET Core Web Application:
- You can give the project any name
-
Select Web Application:
-
Select ASP.NET Core Web Application:
-
Add NewGet Packages
- EntityFrameworkCore
- EntityFrameworkCore.Tools
-
Connect the App to the DB
-
I just used the Scaffold-DbContext command:
Scaffold-DbContext "CS here" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
- I did not make any edits to the Model file or the context file in the ASP project, however there is no reason that you can't do so
-
I just used the Scaffold-DbContext command:
-
Edit the index.chtml.cs file
-
Update the OnGet method:
// Declare a collection to make it available to the Razor Page public List<ImageTb> ListOfImages { get; set; } public async Task OnGet() { // Connect to the DB using(var db = new imgTestContext()) { //Retreive images from the DB ListOfImages = await db.ImageTb.OrderByDescending(d=>d.UplDate).ToListAsync(); } }
- I made mine async to aid in loading speed
- I added a simple LINQ query to retreive all images from the DB
-
Add the Upload method:
/// <summary> /// Method to upload a file to the DB /// </summary> /// <param name="files">The file to upload</param> /// <returns>Back to the index</returns> public async Task<IActionResult> OnPostUploadAsync(IList<IFormFile>files) { if (!ModelState.IsValid) return Page(); IFormFile ui = files.FirstOrDefault(); // Test to see if there is a file at all, and also if it is an image if (ui != null && ui.ContentType.ToLower().StartsWith("image/")) { using (var db = new imgTestContext()) { // These three lines are the imporant bits MemoryStream ms = new MemoryStream(); ui.OpenReadStream().CopyTo(ms); System.Drawing.Image image = System.Drawing.Image.FromStream(ms); // This is my way of extracting just the filename from the file FileInfo fi = new FileInfo(ui.FileName); // The rest of this is just standard EF var newImage = new ImageTb() { Id = Guid.NewGuid(), Name = fi.Name, Data = ms.ToArray(), Width = image.Width, Height = image.Height, ContentType = ui.ContentType, UplDate = DateTime.Now }; db.ImageTb.Add(newImage); await db.SaveChangesAsync(); } } return RedirectToPage("./Index"); }
-
Update the OnGet method:
-
Edit the index.chtml file
- Remove everything
-
Add in the code from my chtml file that you will find here:
@page @model IndexModel @{ ViewData["Title"] = "Home page"; } <div class="text-center"> <h1 class="display-4">Image Test</h1> <p>This is a test</p> </div> <!--This is the FORM that invokes the OnPostUploadAsync method you see above--> <div class="text-center"> <form method="post" enctype="multipart/form-data"> Image: <input type="file" name="files" /> <button class="btn btn-primary" asp-page-handler="upload">Upload</button> </form> </div> <div> <table class="table"> <thead> <tr> <th>@Html.DisplayNameFor(model => model.ListOfImages[0].Data)</th> <th>@Html.DisplayNameFor(model => model.ListOfImages[0].Name)</th> <th>Length / Width</th> <th>@Html.DisplayNameFor(model => model.ListOfImages[0].ContentType)</th> <th>@Html.DisplayNameFor(model => model.ListOfImages[0].UplDate)</th> </tr> </thead> <tbody> @foreach (var myItem in Model.ListOfImages) { <tr> <!--This is the important bit for displaying the image data on the page--> @{ string imageBase64 = Convert.ToBase64String(myItem.Data); string imgsrc = String.Format("data:image/gif;base64,{0}", imageBase64); } <td><img src = "&imgsrc" alt = "@ myItem.Name" /></td> <td>@Html.DisplayFor(mi => myItem.Name)</td> <td>@Html.DisplayFor(mi => myItem.Height) / @Html.DisplayFor(mi => myItem.Width)</td> <td>@Html.DisplayFor(mi => myItem.ContentType)</td> <td>@Html.DisplayFor(mi => myItem.UplDate)</td> </tr> } </tbody> </table> </div>
- If you have other edits from above, be sure to carry them over here
-
Test
-
Upload an image to the DB:
Test #1 - Dispaly the image Pre-Condition: Images are present in the DB Dependancies: That the app can reach the DB Step # Test Steps Test Data Expected Result Actual Result Status(Pass/Fail) Notes 1 Turn on the app null Images will display Post Condition: The user should see any images that are in the db -
Display image on the page:
Test #2 - Upload a picture to the DB Pre-Condition: images are availabel to upload Dependancies: The app can reach in the DB Step # Test Steps Test Data Expected Result Actual Result Status(Pass/Fail) Notes 1 Click the image select test.jpeg the path will be in the selection section 2 click the upload button null the image will now be in the DB 3 View the image list null Your image should appear Post Condition: The image will be saved in the DB and render on the page
-
Upload an image to the DB:
-
After everything is said and done you should have a web page that looks something like this:
Lastly, I know that the web page is not super artsy. However, this is a good a starting point as any. Feel free to reachout to me using the links below if there is any feedback.
Links
Name | Link | Notes |
---|---|---|
Micorsoft | EF Core | EF Core getting started - Existing DB |
Micorsoft | ASP.NET Core | ASP.NET Core (Razor) Getting started |
Micorsoft | SQL Image Type | This is the article that got things rolling for me. I was looing on how to store images and I saw the image type in SSMS. However, when I went to reasearch the actual item, I landed on this page. |
Micorsoft | MSDN | This MSDN article is what got me a long way to the finish on this issue |
Stack Overflow | Image display | Item that got me the answer to the display question |
ToHTML | Syntax Highlighting | The online Syntax Highlighter that I use to color the above. However it does not really do the cshtml very well so that is why that section is plain |