Updating a database call without refreshing a page

A list of images (treasures) is displayed to the user, here the user selects one image that will be saved in the Learner_treauser table:

 List<The_Factory_Chante.Models.Treasure> tresh; using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext()) { string imageSource = ""; tresh = db2.Treasures.ToList(); foreach (var item in tresh) { if (item.itemImage != null) { string imageBase = Convert.ToBase64String(item.itemImage); imageSource = string.Format("data:image/gif;base64,{0}", imageBase); } <img id="@item.treasureID" src="@imageSource" onclick="return MakeSure(@item.treasureID)" /> } } 

The function called when the image is selected. In this function, the image is passed to the webservice method for saving in the database, and the page is updated for updating:

 function MakeSure(treshID) { var id = treshID $.ajax({ url: "../../WebService.asmx/MakeSure", data: "{ 'id': '" + id + "'}", dataType: "json", type: "POST", contentType: "application/json; charset=utf-8", success: function (data) { }, error: function (XMLHttpRequest, textStatus, errorThrown) { } }); window.location.reload(); }; 

However, this is not very pleasant for the user. The best way is to refresh without refreshing the page.

Here is the Webservice method, which takes the selected image identifier and stores it in the Learner_Treasure table.

 public void MakeSure(int id) { using (The_FactoryDBContext db = new The_FactoryDBContext()) { Learner_Treasure learnTreasure = new Learner_Treasure(); learnTreasure.dateCompleted = DateTime.Today; learnTreasure.learnerID = UserInfo.ID; learnTreasure.treasureID = id; db.Learner_Treasure.Add(learnTreasure); db.SaveChanges(); } 

Code for calling the Learner_Treasure table.

 List<The_Factory_Chante.Models.Learner_Treasure> lern; using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext()) { string imageSource = ""; lern = db2.Learner_Treasure.ToList(); if (lern != null) { foreach (var item in lern) { if (item.learnerID == UserInfo.ID) { byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage; string imageBase = Convert.ToBase64String(bytes); imageSource = string.Format("data:image/gif;base64,{0}", imageBase); <img id="@item.treasureID" src="@imageSource"/> } } 

This code will show the user all the images that they have selected, but if I remove window.location.reload(); , this code will only be updated when the page reloads. This means that the user will not see his selected image immediately after selecting it.

What I want to do is update the code that calls Learner_Table without refreshing the page.

+5
source share
6 answers

There is another way to approach this problem, you can use the SignalR library.

This is what you will need to do:

View

 // Include the SignalR Script <script src="~/Scripts/jquery.signalR-2.2.0.js"></script> // Provide a dynamic proxy for SignalR <script src="~/signalr/hubs"></script> // Define hub connection(see below) var hub = $.connection.yourHub; // This is what the Hub will call (Clients.All.getImage(imageSource);) hub.client.getImage = function (img) { var image = '<img id="' + img.treasureId + '" src="data:image/jpg;base64,' + img.image + '"'; $(image).appendTo("body"); }; // Start the connection to the hub // Once we have a connection then call the getLearnerTreasureItem on the Hub $.connection.hub.start().done(function () { var id = // whatever hub.server.getLearnerTreasureItem(id); }; 

hub

 public class YourHub : Hub { public void GetLearnerTreasureItem() { // All your code List<The_Factory_Chante.Models.Learner_Treasure> lern; using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext()) { string imageSource = ""; lern = db2.Learner_Treasure.ToList(); if (lern != null) { foreach (var item in lern) { if (item.learnerID == UserInfo.ID) { byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage; string imageBase = Convert.ToBase64String(bytes); imageSource = string.Format("data:image/gif;base64,{0}", imageBase); } } // This will now call the getImage function on your view. Clients.All.getImage(imageSource); } } 

Dynamic Proxy Information

+2
source

Your problem is the onclick event handler here:

 <img id="@item.treasureID" src="@imageSource" onclick="return MakeSure(@item.treasureID)" /> 

In the MakeSure() function, you are not returning anything. Thus, you have two options, change the MakeSure() function to return false at the end, or change the onclick event to return false after the first function call in the image element, for example, onclick="MakeSure(@item.TreasureID); return false;"

Also you need to remove window.location.reload(); from the MakeSure() function.

Side note, it looks like you are mixing your DbContext in your view, if so, this is very bad practice. You must put your access to the data at some service level, which serves as an intermediary between the view and your data.

Update

Well, after reading my question several times, I understand your problem. The problem is your second part of the code.

 List<The_Factory_Chante.Models.Learner_Treasure> lern; using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext()) { string imageSource = ""; lern = db2.Learner_Treasure.ToList(); if (lern != null) { foreach (var item in lern) { if (item.learnerID == UserInfo.ID) { byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage; string imageBase = Convert.ToBase64String(bytes); imageSource = string.Format("data:image/gif;base64,{0}", imageBase); <img id="@item.treasureID" src="@imageSource"/> } } } } 

This calls the database and gets a list of Learner_Treasure objects that you use for display. Server code runs after each page request, this is exactly what happens. It will not be updated asynchronously without a request to the server.

You need to implement an ajax request to display the last Learner_Treasure list in the view. Again, this boils down to the first note I gave, the reason is that you mix your dbcontext with your view and expect it to be updated on the fly. If you implement a layer that serves your data view (controller), you can call it asynchronously and refresh the page without reloading.

For example, you could write a call in your controller to get one LearnerTreasure element in json.

 [HttpGet] public ActionResult GetLearnerTreasureItem(int Id) { using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext()) { learnerTreasureItem = db2.Learner_Treasure.FirstOrDefault(x => x.Id == Id); return Json(new { image = Convert.ToBase64String(learnerTreasureItem.itemImage), treasureId = learnerTreasureItem.TreasureID }, JsonRequestBehavior.AllowGet); } } 

And then name it with ajax in your view, as you did with the update.

 $.ajax({ cache: false, type: "GET", url: '/YOURCONTROLLERNAME/GetLearnerTreasureItem?id=1', contentType: 'application/json', dataType: "json", success: function (data) { //build image element var image = '<img id="' + data.treasureId + '" src="data:image/jpg;base64,' + data.image + '"'; //add the image to where you need it. $(image).appendTo("body"); }, error: function (xhr) { alert("Error occurred while loading the image."); } }); 

Hope this helps.

0
source

The way I relate to this is to make a partial view for the code that needs to be updated.

 public PartialViewResult UserImages(your paramaters here) { your code here } 

And after successful $ .ajax, I update it

 var id = treshID $.ajax({ url: "../../WebService.asmx/MakeSure", data: "{ 'id': '" + id + "'}", dataType: "json", type: "POST", contentType: "application/json; charset=utf-8", success: function (data) { $.ajax({ url: "/UserImages", data: your data model here, success(function(html)){ $("#yourPartialViewWrapperHere").html(html)); } }); }, error: function (XMLHttpRequest, textStatus, errorThrown) { } }); 
0
source

Refresh Treasure Image List

 <img id="@item.treasureID" src="@imageSource" onclick="return MakeSure(this, @item.treasureID)" /> 

read this parameter in the MakeSure method. I also just assume that Learner_Treasure images are listed in ul with the name 'ulLearnerTreasure'.

 function MakeSure(sender,treshID) { var id = treshID; var imgSrc = $(sender).attr("src"); $.ajax({ url: "../../WebService.asmx/MakeSure", data: "{ 'id': '" + id + "'}", dataType: "json", type: "POST", contentType: "application/json; charset=utf-8", success: function (data) { var li = '<li><img id ="'+ treshID +'"src="'+ imgSrc +'" /></li>'; $("#ulLearnerTreasure").append(li); }, error: function (XMLHttpRequest, textStatus, errorThrown) { } }); }; 
0
source

Modify the MakeSure method to revert the changes and update the html from the jQuery ajax success handler.

0
source

I would use it with HtmlHelpers, for example: (as someone suggested, using db code directly is not good practice, you need to change that.)

 public static class HTMLHelpers { public static IHtmlString TreasureImages(this HtmlHelper helper, List<The_Factory_Chante.Models.Learner_Treasure> lern) { StringBuilder sb = new StringBuilder(); using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext()) { string imageSource = ""; lern = db2.Learner_Treasure.ToList(); if (lern != null) { foreach (var item in lern) { if (item.learnerID == UserInfo.ID) { byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage; string imageBase = Convert.ToBase64String(bytes); imageSource = string.Format("data:image/gif;base64,{0}", imageBase); sb.Append("<li><img id='@item.treasureID' src='@imageSource'/></li>"); } } } } return new HtmlString(sb.ToString()); } } 

Placeholder for your images:

 <ul id="TreaureImagesSection"> </ul> 

On the cshtml page, load the list using this script, for the first time or when you need an updated list

 <script> $.ajax({ cache: false, type: "GET", url: '/YOURCONTROLLER/TreasuresList', contentType: 'application/json; charset=utf-8', success: function (data) { // the data returned is List<The_Factory_Chante.Models.Learner_Treasure> $("#TreaureImagesSection").html('@Html.TreasureImages(data)'); }, error: function (xhr) { alert("Error occurred while loading the image."); } }); </script> 
0
source

Source: https://habr.com/ru/post/1233449/


All Articles