Reputation: 903
A list of images (treasures) are displayed to the user, here the user will choose a single image which will be stored 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 an image is chosen. In this function the image is sent over to a webservice method to be saved to the database, and the page is reload for an update to take place:
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 on the user's point of you. A better way would be to update without refreshing the page.
Here is the Webservice
method that receives the chosen image id 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 to call 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 they have chosen, however in if I take away window.location.reload();
this code is only updated when the page reloads. Meaning that the user will not see their chosen image immediately after they have chosen it.
What I want to do is update the code that calls the Learner_Table
without refreshing the page.
Upvotes: 6
Views: 2253
Reputation: 1064
I would implement it using HtmlHelpers, like so: (as someone suggested, using db code directly is not a 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>
In your cshtml page, load the list with this script, the first time or whenever you need the 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>
Upvotes: 0
Reputation: 8183
There is another way to approach this problem, you could use the SignalR library.
This is what you would 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);
}
}
Information on the dynamic proxy
Upvotes: 2
Reputation: 969
Update in treasures images list
<img id="@item.treasureID" src="@imageSource" onclick="return MakeSure(this, @item.treasureID)" />
read that param in MakeSure method. also I just assume Learner_Treasure images listed in ul named '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) {
}
});
};
Upvotes: 0
Reputation: 5262
Your problem is the onclick
event handler here:
<img id="@item.treasureID" src="@imageSource" onclick="return MakeSure(@item.treasureID)" />
In the MakeSure()
function you don't return anything. So you have two options, change your 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, like this onclick="MakeSure(@item.TreasureID); return false;"
Also you will have to remove the window.location.reload();
from the MakeSure()
function.
Side note, it seems you are mixing up your DbContext in your view, if that's the case, this is very bad practice. You should put your data access behind some sort of service layer that serves as a mediator between the view and your data.
Ok after reading your question a few times I understand your problem The problem is your second piece of 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 DB and gets a list of Learner_Treasure
objects which you use to output on view. Server side code gets executed once every page request, this is exactly what is happening. It will not asynchronously update without a request to the server.
You need to implement an ajax request to pull the latest Learner_Treasure list into the view. Again this comes down to the first side note I gave, the reason is because you are mixing your dbcontext with your view and expecting it to update on the fly. If you implement a layer which serves your view with the data (controller), you could call this asynchronously and have the page update without it reloading.
For instance you could write a call in your controller to get a single LearnerTreasure item 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 call it with ajax in your view, like 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.");
}
});
I hope this helps.
Upvotes: 0
Reputation: 880
The way I approach this is by making a partial View for the code that needs to be refreshed
public PartialViewResult UserImages(your paramaters here)
{
your code here
}
And then after successful $.ajax I refresh 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) {
}
});
Upvotes: 0